diff --git a/.formatter.exs b/.formatter.exs index 4f873c3a..f030df39 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -92,6 +92,7 @@ spark_locals_without_parens = [ grace_period: 1, hash_provider: 1, hashed_password_field: 1, + http_adapter: 1, icon: 1, icon_url_field: 1, id: 1, diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.Apple.md b/documentation/dsls/DSL-AshAuthentication.Strategy.Apple.md index 936bafe4..32c2147a 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.Apple.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.Apple.md @@ -71,6 +71,7 @@ The following defaults are applied: | [`auth_method`](#authentication-strategies-apple-auth_method){: #authentication-strategies-apple-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. | | [`client_secret`](#authentication-strategies-apple-client_secret){: #authentication-strategies-apple-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`trusted_audiences`](#authentication-strategies-apple-trusted_audiences){: #authentication-strategies-apple-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-apple-http_adapter){: #authentication-strategies-apple-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`private_key`](#authentication-strategies-apple-private_key){: #authentication-strategies-apple-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`code_verifier`](#authentication-strategies-apple-code_verifier){: #authentication-strategies-apple-code_verifier } | `boolean` | `false` | Boolean to generate and use a random 128 byte long url safe code verifier for PKCE flow, optional, defaults to false. When set to true the session params will contain :code_verifier, :code_challenge, and :code_challenge_method params | | [`registration_enabled?`](#authentication-strategies-apple-registration_enabled?){: #authentication-strategies-apple-registration_enabled? } | `boolean` | `true` | If enabled, new users will be able to register for your site when authenticating and not already present. If not, only existing users will be able to authenticate. | diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.Auth0.md b/documentation/dsls/DSL-AshAuthentication.Strategy.Auth0.md index b675804c..bde9a8fa 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.Auth0.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.Auth0.md @@ -69,6 +69,7 @@ The following defaults are applied: | [`auth_method`](#authentication-strategies-auth0-auth_method){: #authentication-strategies-auth0-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. | | [`client_secret`](#authentication-strategies-auth0-client_secret){: #authentication-strategies-auth0-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`trusted_audiences`](#authentication-strategies-auth0-trusted_audiences){: #authentication-strategies-auth0-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-auth0-http_adapter){: #authentication-strategies-auth0-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`private_key`](#authentication-strategies-auth0-private_key){: #authentication-strategies-auth0-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_id`](#authentication-strategies-auth0-private_key_id){: #authentication-strategies-auth0-private_key_id } | `(any, any -> any) \| module \| String.t` | | The identifier of the private key (sent as `kid` in the JWT header) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_path`](#authentication-strategies-auth0-private_key_path){: #authentication-strategies-auth0-private_key_path } | `(any, any -> any) \| module \| String.t` | | Path to the private key PEM file (alternative to `:private_key`) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.DynamicOidc.md b/documentation/dsls/DSL-AshAuthentication.Strategy.DynamicOidc.md index 93103ba2..1e8831bd 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.DynamicOidc.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.DynamicOidc.md @@ -123,6 +123,7 @@ the strategy looks up the right row based on the request path | [`prevent_hijacking?`](#authentication-strategies-dynamic_oidc-prevent_hijacking?){: #authentication-strategies-dynamic_oidc-prevent_hijacking? } | `boolean` | `true` | Requires a confirmation add_on to be present if the password strategy is used with the same identity_field. | | [`auth_method`](#authentication-strategies-dynamic_oidc-auth_method){: #authentication-strategies-dynamic_oidc-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. | | [`trusted_audiences`](#authentication-strategies-dynamic_oidc-trusted_audiences){: #authentication-strategies-dynamic_oidc-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-dynamic_oidc-http_adapter){: #authentication-strategies-dynamic_oidc-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`code_verifier`](#authentication-strategies-dynamic_oidc-code_verifier){: #authentication-strategies-dynamic_oidc-code_verifier } | `boolean` | `false` | Boolean to generate and use a random 128 byte long url safe code verifier for PKCE flow, optional, defaults to false. When set to true the session params will contain :code_verifier, :code_challenge, and :code_challenge_method params | | [`registration_enabled?`](#authentication-strategies-dynamic_oidc-registration_enabled?){: #authentication-strategies-dynamic_oidc-registration_enabled? } | `boolean` | `true` | If enabled, new users will be able to register for your site when authenticating and not already present. If not, only existing users will be able to authenticate. | | [`register_action_name`](#authentication-strategies-dynamic_oidc-register_action_name){: #authentication-strategies-dynamic_oidc-register_action_name } | `atom` | | The name of the action to use to register a user, if `registration_enabled?` is `true`. Defaults to `register_with_` See the "Registration and Sign-in" section of the strategy docs for more. | diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.Github.md b/documentation/dsls/DSL-AshAuthentication.Strategy.Github.md index a504c9fb..b85aa229 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.Github.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.Github.md @@ -72,6 +72,7 @@ The following defaults are applied: | [`authorize_url`](#authentication-strategies-github-authorize_url){: #authentication-strategies-github-authorize_url } | `(any, any -> any) \| module \| String.t` | `"https://github.com/login/oauth/authorize"` | The API url to the OAuth2 authorize endpoint, relative to `site`, e.g `authorize_url fn _, _ -> {:ok, "https://exampe.com/authorize"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`token_url`](#authentication-strategies-github-token_url){: #authentication-strategies-github-token_url } | `(any, any -> any) \| module \| String.t` | `"https://github.com/login/oauth/access_token"` | The API url to access the token endpoint, relative to `site`, e.g `token_url fn _, _ -> {:ok, "https://example.com/oauth_token"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`trusted_audiences`](#authentication-strategies-github-trusted_audiences){: #authentication-strategies-github-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-github-http_adapter){: #authentication-strategies-github-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`user_url`](#authentication-strategies-github-user_url){: #authentication-strategies-github-user_url } | `(any, any -> any) \| module \| String.t` | `"/user"` | The API url to access the user endpoint, relative to `site`, e.g `user_url fn _, _ -> {:ok, "https://example.com/userinfo"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key`](#authentication-strategies-github-private_key){: #authentication-strategies-github-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_id`](#authentication-strategies-github-private_key_id){: #authentication-strategies-github-private_key_id } | `(any, any -> any) \| module \| String.t` | | The identifier of the private key (sent as `kid` in the JWT header) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.Google.md b/documentation/dsls/DSL-AshAuthentication.Strategy.Google.md index d93778ab..bc4627ce 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.Google.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.Google.md @@ -72,6 +72,7 @@ The following defaults are applied: | [`auth_method`](#authentication-strategies-google-auth_method){: #authentication-strategies-google-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. | | [`client_secret`](#authentication-strategies-google-client_secret){: #authentication-strategies-google-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`trusted_audiences`](#authentication-strategies-google-trusted_audiences){: #authentication-strategies-google-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-google-http_adapter){: #authentication-strategies-google-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`private_key`](#authentication-strategies-google-private_key){: #authentication-strategies-google-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_id`](#authentication-strategies-google-private_key_id){: #authentication-strategies-google-private_key_id } | `(any, any -> any) \| module \| String.t` | | The identifier of the private key (sent as `kid` in the JWT header) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_path`](#authentication-strategies-google-private_key_path){: #authentication-strategies-google-private_key_path } | `(any, any -> any) \| module \| String.t` | | Path to the private key PEM file (alternative to `:private_key`) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.Microsoft.md b/documentation/dsls/DSL-AshAuthentication.Strategy.Microsoft.md index a2401962..98649fb5 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.Microsoft.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.Microsoft.md @@ -88,6 +88,7 @@ The following defaults are applied: | [`auth_method`](#authentication-strategies-microsoft-auth_method){: #authentication-strategies-microsoft-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. | | [`client_secret`](#authentication-strategies-microsoft-client_secret){: #authentication-strategies-microsoft-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`trusted_audiences`](#authentication-strategies-microsoft-trusted_audiences){: #authentication-strategies-microsoft-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-microsoft-http_adapter){: #authentication-strategies-microsoft-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`private_key`](#authentication-strategies-microsoft-private_key){: #authentication-strategies-microsoft-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_id`](#authentication-strategies-microsoft-private_key_id){: #authentication-strategies-microsoft-private_key_id } | `(any, any -> any) \| module \| String.t` | | The identifier of the private key (sent as `kid` in the JWT header) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_path`](#authentication-strategies-microsoft-private_key_path){: #authentication-strategies-microsoft-private_key_path } | `(any, any -> any) \| module \| String.t` | | Path to the private key PEM file (alternative to `:private_key`) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.OAuth2.md b/documentation/dsls/DSL-AshAuthentication.Strategy.OAuth2.md index 05bcda8b..b9a9e556 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.OAuth2.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.OAuth2.md @@ -252,6 +252,7 @@ OAuth2 authentication | [`auth_method`](#authentication-strategies-oauth2-auth_method){: #authentication-strategies-oauth2-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. | | [`client_secret`](#authentication-strategies-oauth2-client_secret){: #authentication-strategies-oauth2-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`trusted_audiences`](#authentication-strategies-oauth2-trusted_audiences){: #authentication-strategies-oauth2-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-oauth2-http_adapter){: #authentication-strategies-oauth2-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`private_key`](#authentication-strategies-oauth2-private_key){: #authentication-strategies-oauth2-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_id`](#authentication-strategies-oauth2-private_key_id){: #authentication-strategies-oauth2-private_key_id } | `(any, any -> any) \| module \| String.t` | | The identifier of the private key (sent as `kid` in the JWT header) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_path`](#authentication-strategies-oauth2-private_key_path){: #authentication-strategies-oauth2-private_key_path } | `(any, any -> any) \| module \| String.t` | | Path to the private key PEM file (alternative to `:private_key`) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.Oidc.md b/documentation/dsls/DSL-AshAuthentication.Strategy.Oidc.md index 1e4970af..d77358f1 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.Oidc.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.Oidc.md @@ -89,6 +89,7 @@ all the same configuration options should you need them. | [`auth_method`](#authentication-strategies-oidc-auth_method){: #authentication-strategies-oidc-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. | | [`client_secret`](#authentication-strategies-oidc-client_secret){: #authentication-strategies-oidc-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`trusted_audiences`](#authentication-strategies-oidc-trusted_audiences){: #authentication-strategies-oidc-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-oidc-http_adapter){: #authentication-strategies-oidc-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`private_key`](#authentication-strategies-oidc-private_key){: #authentication-strategies-oidc-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_id`](#authentication-strategies-oidc-private_key_id){: #authentication-strategies-oidc-private_key_id } | `(any, any -> any) \| module \| String.t` | | The identifier of the private key (sent as `kid` in the JWT header) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_path`](#authentication-strategies-oidc-private_key_path){: #authentication-strategies-oidc-private_key_path } | `(any, any -> any) \| module \| String.t` | | Path to the private key PEM file (alternative to `:private_key`) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.Okta.md b/documentation/dsls/DSL-AshAuthentication.Strategy.Okta.md index 1d15b8a0..fb45e748 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.Okta.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.Okta.md @@ -89,6 +89,7 @@ The following defaults are applied: | [`auth_method`](#authentication-strategies-okta-auth_method){: #authentication-strategies-okta-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. | | [`client_secret`](#authentication-strategies-okta-client_secret){: #authentication-strategies-okta-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`trusted_audiences`](#authentication-strategies-okta-trusted_audiences){: #authentication-strategies-okta-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-okta-http_adapter){: #authentication-strategies-okta-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`private_key`](#authentication-strategies-okta-private_key){: #authentication-strategies-okta-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_id`](#authentication-strategies-okta-private_key_id){: #authentication-strategies-okta-private_key_id } | `(any, any -> any) \| module \| String.t` | | The identifier of the private key (sent as `kid` in the JWT header) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_path`](#authentication-strategies-okta-private_key_path){: #authentication-strategies-okta-private_key_path } | `(any, any -> any) \| module \| String.t` | | Path to the private key PEM file (alternative to `:private_key`) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | diff --git a/documentation/dsls/DSL-AshAuthentication.Strategy.Slack.md b/documentation/dsls/DSL-AshAuthentication.Strategy.Slack.md index bf353f9e..68f2185a 100644 --- a/documentation/dsls/DSL-AshAuthentication.Strategy.Slack.md +++ b/documentation/dsls/DSL-AshAuthentication.Strategy.Slack.md @@ -67,6 +67,7 @@ The following defaults are applied: | [`auth_method`](#authentication-strategies-slack-auth_method){: #authentication-strategies-slack-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. | | [`client_secret`](#authentication-strategies-slack-client_secret){: #authentication-strategies-slack-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`trusted_audiences`](#authentication-strategies-slack-trusted_audiences){: #authentication-strategies-slack-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | +| [`http_adapter`](#authentication-strategies-slack-http_adapter){: #authentication-strategies-slack-http_adapter } | `atom \| {atom, keyword}` | | The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`). | | [`private_key`](#authentication-strategies-slack-private_key){: #authentication-strategies-slack-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_id`](#authentication-strategies-slack-private_key_id){: #authentication-strategies-slack-private_key_id } | `(any, any -> any) \| module \| String.t` | | The identifier of the private key (sent as `kid` in the JWT header) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | | [`private_key_path`](#authentication-strategies-slack-private_key_path){: #authentication-strategies-slack-private_key_path } | `(any, any -> any) \| module \| String.t` | | Path to the private key PEM file (alternative to `:private_key`) if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. | diff --git a/lib/ash_authentication/strategies/oauth2.ex b/lib/ash_authentication/strategies/oauth2.ex index 50fb2440..e4dc0ded 100644 --- a/lib/ash_authentication/strategies/oauth2.ex +++ b/lib/ash_authentication/strategies/oauth2.ex @@ -232,6 +232,7 @@ defmodule AshAuthentication.Strategy.OAuth2 do client_id: nil, client_secret: nil, icon: nil, + http_adapter: nil, id_token_signed_response_alg: nil, id_token_ttl_seconds: nil, identity_relationship_name: :identities, @@ -291,6 +292,7 @@ defmodule AshAuthentication.Strategy.OAuth2 do client_id: secret, client_secret: secret, icon: nil | atom, + http_adapter: nil | module | {module, keyword}, id_token_signed_response_alg: nil | binary, id_token_ttl_seconds: nil | pos_integer(), identity_relationship_name: atom, diff --git a/lib/ash_authentication/strategies/oauth2/dsl.ex b/lib/ash_authentication/strategies/oauth2/dsl.ex index 42e00678..7958e236 100644 --- a/lib/ash_authentication/strategies/oauth2/dsl.ex +++ b/lib/ash_authentication/strategies/oauth2/dsl.ex @@ -28,6 +28,7 @@ defmodule AshAuthentication.Strategy.OAuth2.Dsl do :base_url, :client_id, :client_secret, + :http_adapter, :identity_resource, :private_key, :private_key_id, @@ -108,6 +109,13 @@ defmodule AshAuthentication.Strategy.OAuth2.Dsl do required: false, default: nil ], + http_adapter: [ + type: {:or, [:atom, {:tuple, [:atom, :keyword_list]}]}, + doc: + "The `Assent.HTTPAdapter` to use for this strategy's OAuth2 requests, as a module or `{module, opts}` tuple. Overrides the `:ash_authentication, :http_adapter` application default. Use this for a provider that needs bespoke transport handling — for example an adapter that unwraps a non-standard response envelope before the standard OAuth2 parsing runs. Defaults to the application setting (`Assent.HTTPAdapter.Finch`).", + required: false, + default: nil + ], user_url: [ type: secret_type, doc: diff --git a/lib/ash_authentication/strategies/oauth2/plug.ex b/lib/ash_authentication/strategies/oauth2/plug.ex index fad251e8..3e9dd84b 100644 --- a/lib/ash_authentication/strategies/oauth2/plug.ex +++ b/lib/ash_authentication/strategies/oauth2/plug.ex @@ -213,7 +213,7 @@ defmodule AshAuthentication.Strategy.OAuth2.Plug do ), {:ok, config} <- add_secret_value(config, strategy, :trusted_audiences, true, context), - {:ok, config} <- add_http_adapter(config), + {:ok, config} <- add_http_adapter(config, strategy), {:ok, config} <- add_secret_value( config, @@ -354,13 +354,17 @@ defmodule AshAuthentication.Strategy.OAuth2.Plug do end end - defp add_http_adapter(config) do + defp add_http_adapter(config, strategy) do + # A strategy may declare its own `http_adapter` (e.g. a provider that needs + # bespoke transport handling); it takes precedence over the application + # default so the plug does not clobber it. http_adapter = - Application.get_env( - :ash_authentication, - :http_adapter, - {Finch, supervisor: AshAuthentication.Finch} - ) + strategy.http_adapter || + Application.get_env( + :ash_authentication, + :http_adapter, + {Finch, supervisor: AshAuthentication.Finch} + ) {:ok, Map.put(config, :http_adapter, http_adapter)} end diff --git a/test/ash_authentication/strategies/oauth2/plug_test.exs b/test/ash_authentication/strategies/oauth2/plug_test.exs index 7b0e1a39..998d4709 100644 --- a/test/ash_authentication/strategies/oauth2/plug_test.exs +++ b/test/ash_authentication/strategies/oauth2/plug_test.exs @@ -26,6 +26,27 @@ defmodule AshAuthentication.Strategy.OAuth2.PlugTest do session = get_session(conn, "user/oauth2") assert session.state =~ ~r/.+/ end + + test "a strategy's `http_adapter` overrides the application default" do + import Mimic + + {:ok, strategy} = Info.strategy(Example.User, :oauth2) + strategy = %{strategy | http_adapter: {MyEnvelopeAdapter, unwrap: true}} + + test_pid = self() + + stub(Assent.Strategy.OAuth2, :authorize_url, fn config -> + send(test_pid, {:config, config}) + {:ok, %{session_params: %{state: "s"}, url: "https://example.com/authorize?state=s"}} + end) + + :get |> conn("/", %{}) |> SessionPipeline.call([]) |> Plug.request(strategy) + + # The config handed to the assent strategy carries the strategy's own + # adapter, not the app default (Finch) — the plug no longer clobbers it. + assert_received {:config, config} + assert config[:http_adapter] == {MyEnvelopeAdapter, unwrap: true} + end end describe "callback/2 with no session (cross-site form_post)" do diff --git a/test/test_helper.exs b/test/test_helper.exs index 6434d67c..f39b093b 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -9,6 +9,7 @@ Mimic.copy(AshAuthentication.Plug.Defaults) Mimic.copy(AshAuthentication.Plug.Helpers) Mimic.copy(AshAuthentication.Strategy.OAuth2.Actions) Mimic.copy(AshAuthentication.Strategy.OAuth2.Plug) +Mimic.copy(Assent.Strategy.OAuth2) Mimic.copy(AshAuthentication.Strategy.Password.Actions) Mimic.copy(AshAuthentication.Strategy.Password.Plug) Mimic.copy(AshAuthentication.TokenResource)