From 322b884ee21d3d6b1c0caa8aa64f63704d8dedf5 Mon Sep 17 00:00:00 2001 From: Giorgio Torres Date: Tue, 10 Feb 2026 15:48:56 +0100 Subject: [PATCH 1/2] Adds protection against CSRF on authorization flow --- lib/oidcc/plug/authorize.ex | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/oidcc/plug/authorize.ex b/lib/oidcc/plug/authorize.ex index d6a99f2..f87184c 100644 --- a/lib/oidcc/plug/authorize.ex +++ b/lib/oidcc/plug/authorize.ex @@ -17,11 +17,6 @@ defmodule Oidcc.Plug.Authorize do ] end ``` - - ## Query Params - - * `state` - State to relay to OpenID Provider. Commonly used for target redirect - URL after authorization. """ @moduledoc since: "0.1.0" @@ -99,11 +94,11 @@ defmodule Oidcc.Plug.Authorize do |> Utils.validate_client_context_opts!() @impl Plug - def call(%Plug.Conn{params: params} = conn, opts) do + def call(%Plug.Conn{} = conn, opts) do redirect_uri = opts |> Keyword.fetch!(:redirect_uri) |> evaluate_config() client_profile_opts = Keyword.get(opts, :client_profile_opts, %{profiles: []}) - state = Map.get(params, "state", :undefined) + state = :crypto.strong_rand_bytes(32) state_verifier = :erlang.phash2(state) nonce = 31 |> :crypto.strong_rand_bytes() |> Base.url_encode64(padding: false) From 50ad3ef28aad3058ba5099bdfed49827ffd1a186 Mon Sep 17 00:00:00 2001 From: Giorgio Torres Date: Wed, 18 Feb 2026 11:55:16 +0100 Subject: [PATCH 2/2] allowing state as parameter with autheticity verification --- lib/oidcc/plug/authorize.ex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/oidcc/plug/authorize.ex b/lib/oidcc/plug/authorize.ex index f87184c..24b6003 100644 --- a/lib/oidcc/plug/authorize.ex +++ b/lib/oidcc/plug/authorize.ex @@ -94,11 +94,12 @@ defmodule Oidcc.Plug.Authorize do |> Utils.validate_client_context_opts!() @impl Plug - def call(%Plug.Conn{} = conn, opts) do + def call(%Plug.Conn{params: params} = conn, opts) do redirect_uri = opts |> Keyword.fetch!(:redirect_uri) |> evaluate_config() client_profile_opts = Keyword.get(opts, :client_profile_opts, %{profiles: []}) - state = :crypto.strong_rand_bytes(32) + state_authenticity = 31 |> :crypto.strong_rand_bytes() |> Base.url_encode64(padding: false) + state = state_authenticity <> Map.get(params, "state", "") state_verifier = :erlang.phash2(state) nonce = 31 |> :crypto.strong_rand_bytes() |> Base.url_encode64(padding: false)