Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add login via token for API user for dependabot #963

Merged
merged 3 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/arrow_web/try_api_token_auth.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ defmodule ArrowWeb.TryApiTokenAuth do
ArrowWeb.TryApiTokenAuth.Cognito
end

defp api_login_module_for_token(%Arrow.AuthToken{username: "[email protected]"}) do
ArrowWeb.TryApiTokenAuth.Local
end

defp api_login_module_for_token(_token) do
Application.get_env(:arrow, :api_login_module)
end
Expand Down
19 changes: 19 additions & 0 deletions lib/arrow_web/try_api_token_auth/local.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule ArrowWeb.TryApiTokenAuth.Local do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking suggestions for re-naming this..

@moduledoc """
Signs in an API client from a database token for read-only access.
"""

alias Plug.Conn
require Logger

@spec sign_in(Conn.t(), Arrow.AuthToken.t()) :: Conn.t()
def sign_in(%Conn{} = conn, %Arrow.AuthToken{} = auth_token) do
conn
|> Guardian.Plug.sign_in(
ArrowWeb.AuthManager,
auth_token.username,
%{roles: ["read-only"]},
ttl: {0, :second}
)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
defmodule Arrow.Repo.Migrations.AddCiReadonlyUserToken do
use Ecto.Migration

def change do
Arrow.AuthToken.get_or_create_token_for_user("[email protected]")
end
end
1 change: 1 addition & 0 deletions priv/repo/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -636,3 +636,4 @@ INSERT INTO public."schema_migrations" (version) VALUES (20210922191945);
INSERT INTO public."schema_migrations" (version) VALUES (20210924180538);
INSERT INTO public."schema_migrations" (version) VALUES (20211209185029);
INSERT INTO public."schema_migrations" (version) VALUES (20220105203850);
INSERT INTO public."schema_migrations" (version) VALUES (20240207224211);
37 changes: 37 additions & 0 deletions test/arrow_web/try_api_token_auth/local_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule ArrowWeb.TryApiTokenAuth.LocalTest do
use ArrowWeb.ConnCase
import ExUnit.CaptureLog

alias ArrowWeb.TryApiTokenAuth.Local

describe "sign_in/2" do
test "signs in a read-only token user", %{conn: conn} do
local_token_email = "[email protected]"
auth_token = auth_token_for(local_token_email)

conn = Local.sign_in(conn, auth_token)

assert Guardian.Plug.authenticated?(conn)
claims = Guardian.Plug.current_claims(conn)

assert claims["sub"] == local_token_email
assert claims["typ"] == "access"
assert claims["roles"] == ["read-only"]
assert Guardian.Plug.current_resource(conn) == local_token_email
end

test "does not sign in a token user who does not exist", %{conn: conn} do
auth_token = auth_token_for("[email protected]")

assert_raise FunctionClauseError, fn ->
Local.sign_in(conn, auth_token)
end

refute Guardian.Plug.authenticated?(conn)
end
end

defp auth_token_for(username) do
Arrow.Repo.get_by(Arrow.AuthToken, username: username)
end
end
14 changes: 14 additions & 0 deletions test/arrow_web/try_api_token_auth_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ defmodule ArrowWeb.TryApiTokenAuthTest do
assert Guardian.Plug.current_resource(conn) == "[email protected]"
end

test "handles API token with local database token from gtfs_creator user", %{conn: conn} do
token = Arrow.AuthToken.get_or_create_token_for_user("[email protected]")

conn =
conn
|> put_req_header("x-api-key", token)
|> ArrowWeb.TryApiTokenAuth.call([])

claims = Guardian.Plug.current_claims(conn)

assert claims["roles"] == ["read-only"]
assert Guardian.Plug.current_resource(conn) == "[email protected]"
end

test "handles unexpected response from Cognito API", %{conn: conn} do
reassign_env(:ex_aws_requester, {Fake.ExAws, :unexpected_response})

Expand Down
Loading