defmodule Ueberauth.Strategy.Oidcc do
@moduledoc """
OIDC Strategy for Ueberauth.
## Options
- uid_field: claim to use for the `uid` field in `Ueberauth.Auth` (default: "sub")
See `UeberauthOidcc.Config` for other configuration.
"""
use Ueberauth.Strategy
import Ueberauth.Strategy.Helpers
alias Ueberauth.Auth.Extra
@doc """
Handles the initial authentication request.
"""
def handle_request!(conn) do
opts = get_options!(conn)
case UeberauthOidcc.Request.handle_request(opts, conn) do
{:ok, conn} ->
conn
{:error, conn, reason} ->
UeberauthOidcc.Error.set_described_error(conn, reason, "handle_request!")
end
end
@doc """
Handles the callback from the OIDC provider.
"""
def handle_callback!(conn) do
opts = get_options!(conn)
conn = put_private(conn, :ueberauth_oidcc_opts, opts)
case UeberauthOidcc.Callback.handle_callback(opts, conn) do
{:ok, conn, token, userinfo} ->
conn
|> put_private(:ueberauth_oidcc_token, token)
|> put_private(:ueberauth_oidcc_userinfo, userinfo)
{:error, conn, reason} ->
UeberauthOidcc.Error.set_described_error(conn, reason, "handle_callback!")
end
end
@doc false
def handle_cleanup!(conn) do
conn
|> put_private(:ueberauth_oidcc_opts, nil)
|> put_private(:ueberauth_oidcc_token, nil)
|> put_private(:ueberauth_oidcc_userinfo, nil)
end
@doc """
Returns the configured uid field from the claims.
"""
def uid(conn) do
opts = conn.private.ueberauth_oidcc_opts
uid_field = Map.get(opts, :uid_field, "sub")
case conn.private do
%{ueberauth_oidcc_userinfo: %{^uid_field => uid}} ->
uid
%{ueberauth_oidcc_token: token} ->
Map.get(token.id.claims, uid_field)
end
end
@doc """
Returns the credentials from the oidc response.
`other` includes `id_token`
"""
def credentials(conn) do
token = conn.private.ueberauth_oidcc_token
UeberauthOidcc.Auth.credentials(token)
end
@doc """
Returns an `Ueberauth.Auth.Extra` struct containing the claims and userinfo response.
"""
def extra(conn) do
%Extra{
raw_info: %UeberauthOidcc.RawInfo{
opts: conn.private.ueberauth_oidcc_opts,
claims: conn.private.ueberauth_oidcc_token.id.claims,
userinfo: conn.private[:ueberauth_oidcc_userinfo]
}
}
end
@doc """
Returns a `Ueberauth.Auth.Info` struct populated with the data returned from
the userinfo endpoint.
This information is also included in the `Ueberauth.Auth.Credentials` struct.
"""
def info(conn) do
UeberauthOidcc.Auth.info(
conn.private.ueberauth_oidcc_token,
conn.private[:ueberauth_oidcc_userinfo]
)
end
defp get_options!(conn) do
compile_opts = options(conn)
runtime_opts =
(Application.get_env(:ueberauth_oidcc, :providers) || [])[strategy_name(conn)] || []
UeberauthOidcc.Config.merge_and_expand_configuration([
compile_opts,
runtime_opts
])
end
end