From 8129d916e314f5e94c12313374c18eb2a9cf28e4 Mon Sep 17 00:00:00 2001 From: Ivan Reshetnikov Date: Thu, 17 Oct 2024 12:22:23 +0500 Subject: [PATCH] Improve validation for token exchange endpoint --- .../controllers/oauth_controller.ex | 47 +++++++++++-------- lib/comfycamp_web/controllers/oauth_json.ex | 6 +++ 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/lib/comfycamp_web/controllers/oauth_controller.ex b/lib/comfycamp_web/controllers/oauth_controller.ex index e076754..15c07a0 100644 --- a/lib/comfycamp_web/controllers/oauth_controller.ex +++ b/lib/comfycamp_web/controllers/oauth_controller.ex @@ -4,7 +4,6 @@ defmodule ComfycampWeb.OauthController do alias Comfycamp.Accounts alias Comfycamp.SSO alias Comfycamp.SSO.OIDCApp - alias Comfycamp.SSO.OIDCCode alias Comfycamp.SSO.IDToken alias Comfycamp.Token @@ -78,31 +77,41 @@ defmodule ComfycampWeb.OauthController do end 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. - %OIDCCode{redirect_uri: ^redirect_uri} = code = SSO.get_oidc_code!(code_value) + {access_token, refresh_token} = Accounts.generate_oauth_tokens(code.user) - # Check that client provided a valid secret for an active OIDC app. - %OIDCApp{enabled: true, client_id: ^client_id} = - oidc_app = SSO.get_oidc_app_by_secret!(client_secret) + id_token = IDToken.build_id_token(code.user, oidc_app.client_id) + {:ok, signed_id_token} = Token.sign(id_token, client_secret) - # Check that OIDC app is referenced by provided code. - ^client_id = code.oidc_app.client_id + render(conn, :token, + 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. - SSO.delete_oidc_code(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) - {:ok, signed_id_token} = Token.sign(id_token, client_secret) + {:app, _} -> + render(conn, :error, description: "Приложение не найдено или отключено") - render(conn, :token, - access_token: Base.url_encode64(access_token), - refresh_token: Base.url_encode64(refresh_token), - id_token: signed_id_token - ) + {:code_ref, _} -> + render(conn, :error, description: "Временный код выдан для другого приложения") + end end def openid_discovery(conn, _params) do diff --git a/lib/comfycamp_web/controllers/oauth_json.ex b/lib/comfycamp_web/controllers/oauth_json.ex index f43b659..32a5508 100644 --- a/lib/comfycamp_web/controllers/oauth_json.ex +++ b/lib/comfycamp_web/controllers/oauth_json.ex @@ -21,4 +21,10 @@ defmodule ComfycampWeb.OauthJSON do claims_supported: ["sub", "email", "preferred_username"] } end + + def error(assigns) do + %{ + description: assigns["description"] + } + end end