Improve validation for token exchange endpoint

This commit is contained in:
Ivan R. 2024-10-17 12:22:23 +05:00
parent fbb33369a8
commit 8129d916e3
Signed by: lumin
GPG key ID: E0937DC7CD6D3817
2 changed files with 34 additions and 19 deletions

View file

@ -4,7 +4,6 @@ defmodule ComfycampWeb.OauthController do
alias Comfycamp.Accounts alias Comfycamp.Accounts
alias Comfycamp.SSO alias Comfycamp.SSO
alias Comfycamp.SSO.OIDCApp alias Comfycamp.SSO.OIDCApp
alias Comfycamp.SSO.OIDCCode
alias Comfycamp.SSO.IDToken alias Comfycamp.SSO.IDToken
alias Comfycamp.Token alias Comfycamp.Token
@ -78,31 +77,41 @@ defmodule ComfycampWeb.OauthController do
end end
def token(conn, params = %{"code" => code_value, "redirect_uri" => redirect_uri}) do def token(conn, params = %{"code" => code_value, "redirect_uri" => redirect_uri}) do
{:ok, client_id, client_secret} = get_client_info(conn, params) with {:client_info, {:ok, client_id, client_secret}} <-
{:client_info, get_client_info(conn, params)},
{:code, code} <- {:code, SSO.get_oidc_code!(code_value)},
{:uri, ^redirect_uri} <- {:uri, code.redirect_uri},
{:app, oidc_app = %OIDCApp{enabled: true, client_id: ^client_id}} <-
{:app, SSO.get_oidc_app_by_secret!(client_secret)},
{:code_ref, ^client_id} <- {:code_ref, code.oidc_app.client_id} do
SSO.delete_oidc_code(code)
# Check that code is still valid and redirect uri has not been altered. {access_token, refresh_token} = Accounts.generate_oauth_tokens(code.user)
%OIDCCode{redirect_uri: ^redirect_uri} = code = SSO.get_oidc_code!(code_value)
# Check that client provided a valid secret for an active OIDC app. id_token = IDToken.build_id_token(code.user, oidc_app.client_id)
%OIDCApp{enabled: true, client_id: ^client_id} = {:ok, signed_id_token} = Token.sign(id_token, client_secret)
oidc_app = SSO.get_oidc_app_by_secret!(client_secret)
# Check that OIDC app is referenced by provided code. render(conn, :token,
^client_id = code.oidc_app.client_id access_token: Base.url_encode64(access_token),
refresh_token: Base.url_encode64(refresh_token),
id_token: signed_id_token
)
else
{:client_info, _} ->
render(conn, :error, description: "Нет client id или client secret")
# Delete the code. {:code, _} ->
SSO.delete_oidc_code(code) render(conn, :error, description: "Не удалось найти временный код")
{access_token, refresh_token} = Accounts.generate_oauth_tokens(code.user) {:uri, _} ->
render(conn, :error, description: "Redirect URI не совпадает с изначальным значением")
id_token = IDToken.build_id_token(code.user, oidc_app.client_id) {:app, _} ->
{:ok, signed_id_token} = Token.sign(id_token, client_secret) render(conn, :error, description: "Приложение не найдено или отключено")
render(conn, :token, {:code_ref, _} ->
access_token: Base.url_encode64(access_token), render(conn, :error, description: "Временный код выдан для другого приложения")
refresh_token: Base.url_encode64(refresh_token), end
id_token: signed_id_token
)
end end
def openid_discovery(conn, _params) do def openid_discovery(conn, _params) do

View file

@ -21,4 +21,10 @@ defmodule ComfycampWeb.OauthJSON do
claims_supported: ["sub", "email", "preferred_username"] claims_supported: ["sub", "email", "preferred_username"]
} }
end end
def error(assigns) do
%{
description: assigns["description"]
}
end
end end