Add a basic user info endpoint

This commit is contained in:
Ivan R. 2024-10-17 14:13:23 +05:00
parent 8129d916e3
commit be7d4adeec
Signed by: lumin
GPG key ID: E0937DC7CD6D3817
6 changed files with 68 additions and 0 deletions

View file

@ -261,6 +261,11 @@ defmodule Comfycamp.Accounts do
Repo.one(query)
end
def get_user_by_bearer_token(token) do
{:ok, query} = UserToken.verify_bearer_token_query(token)
Repo.one(query)
end
@doc """
Deletes the signed token with the given context.
"""

View file

@ -80,6 +80,19 @@ defmodule Comfycamp.Accounts.UserToken do
{:ok, query}
end
@doc """
Checks if the token is valid and returns its underlying lookup query.
"""
def verify_bearer_token_query(token) do
query =
from token in by_token_and_context_query(token, "bearer"),
join: user in assoc(token, :user),
where: token.inserted_at > ago(1, "day"),
select: user
{:ok, query}
end
@doc """
Builds a token and its hash to be delivered to the user's email.

View file

@ -118,6 +118,10 @@ defmodule ComfycampWeb.OauthController do
render(conn, :openid_discovery)
end
def user_info(conn, _params) do
render(conn, :user_info, user: conn.assigns.oauth_user)
end
@doc """
Extract client id and client secret from request parameters or headers.
Returns {:ok, "client_id", "client_secret"} on success.

View file

@ -22,6 +22,14 @@ defmodule ComfycampWeb.OauthJSON do
}
end
def user_info(%{user: user}) do
%{
sub: Integer.to_string(user.id),
email: user.email,
preferred_username: user.username
}
end
def error(assigns) do
%{
description: assigns["description"]

View file

@ -15,6 +15,7 @@ defmodule ComfycampWeb.Router do
pipeline :api do
plug :accepts, ["json"]
plug :fetch_bearer_token
end
scope "/", ComfycampWeb do
@ -35,6 +36,13 @@ defmodule ComfycampWeb.Router do
get "/.well-known/openid-configuration", OauthController, :openid_discovery
end
scope "/", ComfycampWeb do
pipe_through [:api, :require_oauth]
get "/oauth/userinfo", OauthController, :user_info
post "/oauth/userinfo", OauthController, :user_info
end
# Enable LiveDashboard and Swoosh mailbox preview in development
if Application.compile_env(:comfycamp, :dev_routes) do
# If you want to use the LiveDashboard in production, you should put

View file

@ -110,6 +110,36 @@ defmodule ComfycampWeb.UserAuth do
end
end
@doc """
Authenticate the user by looking at Authorization header
and checking Bearer token.
"""
def fetch_bearer_token(conn, _opts) do
case Plug.Conn.get_req_header(conn, "authorization") do
["Bearer " <> header] ->
user = Accounts.get_user_by_bearer_token(header)
assign(conn, :oauth_user, user)
_ ->
conn
end
end
@doc """
Check that request contains a valid bearer token.
Call after fetch_bearer_token plug.
"""
def require_oauth(conn, _opts) do
if conn.assigns[:oauth_user] do
conn
else
conn
|> put_status(:unauthorized)
|> json(%{error: "You must use a bearer token to access this page."})
|> halt()
end
end
@doc """
Handles mounting and authenticating the current_user in LiveViews.