Improve validation for token exchange endpoint
This commit is contained in:
parent
fbb33369a8
commit
8129d916e3
2 changed files with 34 additions and 19 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue