-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
591 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
defmodule Orbit.Authentication.User do | ||
use Ecto.Schema | ||
import Ecto.Changeset | ||
|
||
@type t :: %__MODULE__{ | ||
id: integer(), | ||
email: String.t(), | ||
inserted_at: DateTime.t(), | ||
updated_at: DateTime.t() | ||
} | ||
|
||
schema "users" do | ||
field(:email, :string) | ||
timestamps() | ||
end | ||
|
||
def create_changeset(struct, params \\ %{}) do | ||
struct | ||
|> cast(params, [ | ||
]) | ||
|> validate_required([:email]) | ||
|> unique_constraint( | ||
:users, | ||
name: :users_email_index | ||
) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
defmodule OrbitWeb.Auth.Auth do | ||
alias Orbit.Authentication.User | ||
alias Orbit.Repo | ||
alias Plug.Conn | ||
|
||
@spec login(Conn.t(), String.t(), integer(), [String.t()], String.t() | nil) :: | ||
Conn.t() | ||
def login(conn, username, ttl_seconds, _groups, logout_url) do | ||
email = String.downcase(username) | ||
|
||
case Repo.get_by(User, email: email) do | ||
nil -> | ||
Repo.insert!(%User{email: email}) | ||
|
||
u -> | ||
u | ||
end | ||
|
||
# We use username (email) as the Guardian resource | ||
conn | ||
|> OrbitWeb.Auth.Guardian.Plug.sign_in( | ||
username, | ||
# claims | ||
%{}, | ||
ttl: {ttl_seconds, :seconds} | ||
) | ||
|> Plug.Conn.put_session(:username, username) | ||
|> Plug.Conn.put_session(:logout_url, logout_url) | ||
end | ||
|
||
@spec logged_in_user(Conn.t()) :: map() | nil | ||
def logged_in_user(conn) do | ||
if Map.has_key?(conn.assigns, :logged_in_user) do | ||
conn.assigns[:logged_in_user] | ||
else | ||
if email = OrbitWeb.Auth.Guardian.Plug.current_resource(conn) do | ||
email = String.downcase(email) | ||
Repo.get_by(User, email: email) | ||
else | ||
nil | ||
end | ||
end | ||
end | ||
|
||
@spec logout(Conn.t()) :: Conn.t() | ||
def logout(conn) do | ||
conn | ||
|> Plug.Conn.assign(:logged_in_user, nil) | ||
|> OrbitWeb.Auth.Guardian.Plug.sign_out() | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
defmodule OrbitWeb.Auth.Guardian do | ||
use Guardian, otp_app: :orbit | ||
|
||
@spec subject_for_token(Guardian.Token.resource(), Guardian.Token.claims()) :: | ||
{:ok, String.t()} | {:error, atom()} | ||
def subject_for_token(resource, _claims) do | ||
sub = resource | ||
{:ok, sub} | ||
end | ||
|
||
@spec resource_from_claims(Guardian.Token.claims()) :: | ||
{:ok, Guardian.Token.resource()} | {:error, atom()} | ||
def resource_from_claims(%{"sub" => id}) do | ||
resource = id | ||
{:ok, resource} | ||
end | ||
end | ||
|
||
defmodule OrbitWeb.Auth.Guardian.Pipeline do | ||
use Guardian.Plug.Pipeline, | ||
otp_app: :orbit, | ||
error_handler: OrbitWeb.Auth.Guardian.ErrorHandler, | ||
module: OrbitWeb.Auth.Guardian | ||
|
||
plug(Guardian.Plug.VerifySession, claims: %{"typ" => "access"}) | ||
plug(Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"}) | ||
plug(Guardian.Plug.LoadResource, allow_blank: true) | ||
end | ||
|
||
defmodule OrbitWeb.Auth.Guardian.ErrorHandler do | ||
@behaviour Guardian.Plug.ErrorHandler | ||
|
||
@impl Guardian.Plug.ErrorHandler | ||
def auth_error(conn, {_type, _reason}, _opts) do | ||
conn | ||
|> Plug.Conn.put_session(:login_target, conn.request_path) | ||
# remove the invalid Guardian session so we don't get caught in a redirect loop | ||
|> OrbitWeb.Auth.Auth.logout() | ||
|> OrbitWeb.AuthController.redirect_needs_login() | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
defmodule OrbitWeb.Auth.Strategy.FakeOidcc do | ||
use Ueberauth.Strategy, ignores_csrf_attack: true | ||
|
||
@impl Ueberauth.Strategy | ||
def handle_request!(conn) do | ||
conn | ||
|> put_resp_content_type("text/html") | ||
|> send_resp( | ||
:ok, | ||
~s( | ||
<!doctype html> | ||
<html> | ||
<h1>Fake Keycloak/Oidcc</h1> | ||
<form action="/auth/keycloak/callback"> | ||
<label>Email: <input type="email" name="email" value="[email protected]"></label> | ||
<input type="submit" value="Log In"> | ||
</form> | ||
</html> | ||
) | ||
) | ||
|> halt() | ||
end | ||
|
||
@impl Ueberauth.Strategy | ||
def handle_callback!(conn) do | ||
# add a /.../callback?invalid query param to mock an invalid token for testing | ||
if Map.has_key?(conn.params, "invalid") or is_nil(conn.params["email"]) do | ||
set_errors!(conn, [error("invalid", "invalid callback")]) | ||
else | ||
conn | ||
end | ||
end | ||
|
||
@impl Ueberauth.Strategy | ||
def uid(_conn) do | ||
"fake_uid" | ||
end | ||
|
||
@impl Ueberauth.Strategy | ||
def credentials(_conn) do | ||
nine_hours_in_seconds = 9 * 60 * 60 | ||
expiration_time = System.system_time(:second) + nine_hours_in_seconds | ||
|
||
%Ueberauth.Auth.Credentials{ | ||
token: "fake_access_token", | ||
refresh_token: "fake_refresh_token", | ||
expires: true, | ||
expires_at: expiration_time | ||
} | ||
end | ||
|
||
@impl Ueberauth.Strategy | ||
def info(conn) do | ||
email = Map.get(conn.params, "email") | ||
|
||
%Ueberauth.Auth.Info{ | ||
email: email | ||
} | ||
end | ||
|
||
@impl Ueberauth.Strategy | ||
def extra(conn) do | ||
groups = conn.params["groups"] || [] | ||
|
||
keycloak_client_id = | ||
get_in(Application.get_env(:ueberauth_oidcc, :providers), [:keycloak, :client_id]) | ||
|
||
%Ueberauth.Auth.Extra{ | ||
raw_info: %UeberauthOidcc.RawInfo{ | ||
userinfo: %{ | ||
"resource_access" => %{ | ||
keycloak_client_id => %{"roles" => groups} | ||
} | ||
} | ||
} | ||
} | ||
end | ||
|
||
@impl Ueberauth.Strategy | ||
def handle_cleanup!(conn) do | ||
conn | ||
end | ||
end |
Oops, something went wrong.