Skip to content

feat(oauth2): allow a strategy to supply its own http_adapter - #1192

Open
pinetops wants to merge 3 commits into
team-alembic:mainfrom
u2i:feat/oauth2-http-adapter-option
Open

feat(oauth2): allow a strategy to supply its own http_adapter#1192
pinetops wants to merge 3 commits into
team-alembic:mainfrom
u2i:feat/oauth2-http-adapter-option

Conversation

@pinetops

@pinetops pinetops commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Problem

AshAuthentication.Strategy.OAuth2.Plug unconditionally overwrites config[:http_adapter] with the :ash_authentication, :http_adapter application setting (defaulting to Finch):

defp add_http_adapter(config) do
  http_adapter =
    Application.get_env(:ash_authentication, :http_adapter, {Finch, supervisor: AshAuthentication.Finch})

  {:ok, Map.put(config, :http_adapter, http_adapter)}
end

So a strategy cannot use a custom Assent.HTTPAdapter, even though Assent supports one via config. There is also no per-strategy way to configure it — only the global application setting.

Motivation

Some providers return responses that aren't quite standard, and the clean way to handle that is a small custom Assent.HTTPAdapter that adjusts the response at the transport layer before Assent's spec-compliant OAuth2 parsing runs — keeping Assent itself unmodified and spec-pure.

Concretely: Ed.link wraps its token and profile responses in a {"$data": ...} envelope (which is not RFC 6749 §5.1-compliant). The correct fix is a transport adapter that unwraps it — but there was no way to hand that adapter to the strategy, because the plug clobbers it. (I initially proposed a hook in Assent for this — pow-auth/assent#205 — but that was reasonably rejected)

Change

  • Add an http_adapter option to the oauth2 DSL — a module or {module, opts} tuple.
  • Have add_http_adapter/2 prefer strategy.http_adapter over the application default.
oauth2 :my_provider do
  # ...
  http_adapter MyApp.HTTPAdapter.Unwrap
end

Compatibility

Backward compatible: the option defaults to nil, so strategies that don't set it fall back to the application setting exactly as before. All OAuth2/OIDC-derived strategies inherit the option (regenerated cheat sheets included).

Tests: a new plug test asserts a strategy's http_adapter reaches the Assent config instead of the app default; the existing OAuth2 suite passes.

pinetops added 3 commits July 24, 2026 21:00
The plug unconditionally overwrote `config[:http_adapter]` with the
`:ash_authentication, :http_adapter` application setting (defaulting to
Finch), so a strategy could not use a bespoke HTTP adapter.

Add an `http_adapter` option to the `oauth2` DSL (a module or
`{module, opts}` tuple) and have the plug prefer it over the application
default. This lets a provider that needs bespoke transport handling — for
example an adapter that unwraps a non-standard response envelope before the
standard, spec-compliant OAuth2 parsing runs — plug in without
reimplementing the strategy.

Backward compatible: the option defaults to nil, so strategies that don't
set it fall back to the application setting exactly as before.
@pinetops
pinetops marked this pull request as ready for review July 24, 2026 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant