diff --git a/config/runtime.exs b/config/runtime.exs index 4f3b5009..88fb18a9 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -137,6 +137,10 @@ oidc_auto_redirect_login = get_var_from_path_or_env(config_dir, "OIDC_AUTO_REDIRECT_LOGIN", "false") |> String.to_existing_atom() +oidc_use_pkce = + get_var_from_path_or_env(config_dir, "OIDC_USE_PKCE", "true") + |> String.to_existing_atom() + oidc_property_mappings = get_var_from_path_or_env(config_dir, "OIDC_PROPERTY_MAPPINGS", nil) |> case do @@ -172,7 +176,8 @@ config :claper, :oidc, provider_name: oidc_provider_name, logo_url: oidc_logo_url, property_mappings: oidc_property_mappings, - auto_redirect_login: oidc_auto_redirect_login + auto_redirect_login: oidc_auto_redirect_login, + use_pkce: oidc_use_pkce config :claper, Claper.Repo, url: database_url, diff --git a/lib/claper_web/controllers/user_oidc_auth.ex b/lib/claper_web/controllers/user_oidc_auth.ex index 6cb495d5..e3d918c8 100644 --- a/lib/claper_web/controllers/user_oidc_auth.ex +++ b/lib/claper_web/controllers/user_oidc_auth.ex @@ -18,23 +18,44 @@ defmodule ClaperWeb.UserOidcAuth do |> Base.url_encode64(padding: false) end + defp use_pkce? do + config()[:use_pkce] != false + end + @doc false def new(conn, _params) do - # Generate PKCE verifier and store it in session - pkce_verifier = generate_pkce_verifier() - conn = put_session(conn, :pkce_verifier, pkce_verifier) - - {:ok, redirect_uri} = - Oidcc.create_redirect_url( - Claper.OidcProviderConfig, - client_id(), - client_secret(), - opts(pkce_verifier) - ) + # Use PKCE based on configuration (secure by default) + use_pkce = use_pkce?() + + {conn, pkce_verifier} = + if use_pkce do + # Generate PKCE verifier and store it in session + verifier = generate_pkce_verifier() + {put_session(conn, :pkce_verifier, verifier), verifier} + else + # Ensure no verifier in session for non-PKCE flow + {delete_session(conn, :pkce_verifier), nil} + end + + case Oidcc.create_redirect_url( + Claper.OidcProviderConfig, + client_id(), + client_secret(), + opts(pkce_verifier) + ) do + {:ok, redirect_uri} -> + uri = Enum.join(redirect_uri, "") + redirect(conn, external: uri) - uri = Enum.join(redirect_uri, "") - - redirect(conn, external: uri) + {:error, reason} -> + conn + |> delete_session(:pkce_verifier) + |> put_status(:internal_server_error) + |> put_view(ClaperWeb.ErrorView) + |> render("csrf_error.html", %{ + error: "Authentication initialization failed: #{inspect(reason)}" + }) + end end def callback(conn, %{"code" => code} = _params) do @@ -109,8 +130,7 @@ defmodule ClaperWeb.UserOidcAuth do base_opts = %{ redirect_uri: "#{url}/users/oidc/callback", scopes: scopes(), - preferred_auth_methods: [:client_secret_basic, :client_secret_post], - require_pkce: true + preferred_auth_methods: [:client_secret_basic, :client_secret_post] } if pkce_verifier do