Packages

OpenAM strategy for use with Ueberauth

Current section

Files

Jump to
ueberauth_openam lib ueberauth strategy openam.ex
Raw

lib/ueberauth/strategy/openam.ex

defmodule Ueberauth.Strategy.OpenAM do
@moduledoc """
OpenAM Strategy for Überauth. Redirects the user to an OpenAM
login page and verifies the auth token the OpenAM server returns
after a successful login.
The login flow looks like this:
1. User is redirected to the OpenAM server's login page by
`Ueberauth.Strategy.OpenAM.handle_request!`
2. User signs in to the OpenAM server.
3. OpenAM server redirects back to the Elixir application, sending
an auth token as an HTTP Cookie header.
4. This auth token is validated by this Überauth OpenAM strategy,
fetching the user's information at the same time.
5. User can proceed to use the Elixir application.
"""
use Ueberauth.Strategy
alias Ueberauth.Auth.Info
alias Ueberauth.Auth.Extra
alias Ueberauth.Strategy.OpenAM
@doc """
Ueberauth `request` handler. Redirects to the OpenAM server's login page.
"""
def handle_request!(conn) do
conn
|> redirect!(redirect_url(conn))
end
@doc """
Ueberauth after login callback with a valid OpenAM Cookie.
"""
def handle_callback!(%Plug.Conn{} = conn) do
handle_token(conn, conn.cookies[OpenAM.API.sso_cookie()])
end
@doc "Ueberauth UID callback."
def uid(conn), do: conn.private.openam_user.uid
@doc """
Ueberauth extra information callback. Returns all attributes the OpenAM
server returned about the user that authenticated.
"""
def extra(conn) do
%Extra{
raw_info: %{
user: conn.private.openam_user
}
}
end
@doc """
Ueberauth user information.
"""
def info(conn) do
user = conn.private.openam_user
%Info{
email: user.mail,
name: Enum.join([user.givenName, user.sn], " "),
nickname: user.uid
}
end
defp redirect_url(conn) do
OpenAM.API.login_url
|> URI.merge("?goto=#{callback_url(conn)}")
|> URI.to_string
end
defp handle_token(conn, nil) do
conn
|> set_errors!([error("missing_sso_cookie", "No OpenAM SSO cookie received")])
end
defp handle_token(conn, token) do
token
|> fetch_user
|> handle_token_response(conn)
end
defp handle_token_response({:ok, user}, conn) do
conn
|> put_private(:openam_user, user)
end
defp handle_token_response({:error, reason}, conn) do
conn
|> set_errors!([error(reason.exception, reason)])
end
defp fetch_user(token) do
token
|> OpenAM.API.redeem_token()
end
end