From aed30f10aafa92907e024bf230eddb80c829810b Mon Sep 17 00:00:00 2001 From: Ashlynne Mitchell Date: Mon, 13 Apr 2026 18:02:44 +1000 Subject: [PATCH] fix(oauth): don't include client assertion when is_localhost --- CHANGELOG.md | 6 ++++++ lib/atex/config/oauth.ex | 12 +++++++++--- lib/atex/oauth.ex | 13 ++++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7867f3..d56163a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,12 @@ and this project adheres to as `Atex.OAuth.Plug.revoke_session/2` to revoke a conn's session programmaticly (e.g. from a session management dashboard). +### Fixed + +- Fix issue when trying to validate OAuth authorisation codes in localhost mode + on PDS implementations that are more strict than the Bluesky reference + implementation. + ## [0.8.0] - 2026-03-29 ### Breaking Changes diff --git a/lib/atex/config/oauth.ex b/lib/atex/config/oauth.ex index 512c9ba..024b7f1 100644 --- a/lib/atex/config/oauth.ex +++ b/lib/atex/config/oauth.ex @@ -39,6 +39,14 @@ defmodule Atex.Config.OAuth do %{private_key | fields: %{"kid" => key_id}} end + @doc """ + Returns whether OAuth should be put into the localhost loopback mode. + """ + @spec is_localhost() :: boolean() + def is_localhost() do + Keyword.get(Application.get_env(:atex, Atex.OAuth, []), :is_localhost, false) + end + @doc """ Returns the client ID based on configuration. @@ -48,9 +56,7 @@ defmodule Atex.Config.OAuth do """ @spec client_id() :: String.t() def client_id() do - is_localhost = Keyword.get(Application.get_env(:atex, Atex.OAuth, []), :is_localhost, false) - - if is_localhost do + if is_localhost() do query = %{redirect_uri: redirect_uri(), scope: scopes()} |> URI.encode_query() diff --git a/lib/atex/oauth.ex b/lib/atex/oauth.ex index 862aa4d..e2e0376 100644 --- a/lib/atex/oauth.ex +++ b/lib/atex/oauth.ex @@ -362,11 +362,18 @@ defmodule Atex.OAuth do client_id: client_id, redirect_uri: redirect_uri, code: code, - code_verifier: code_verifier, - client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", - client_assertion: client_assertion + code_verifier: code_verifier } + body = + if !Config.is_localhost(), + do: + Map.merge(body, %{ + client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + client_assertion: client_assertion + }), + else: body + Req.new(method: :post, url: authz_metadata.token_endpoint, form: body) |> send_oauth_dpop_request(dpop_key) |> case do -- knotmirror 0.0.1