Atex.OAuth.Flow (atex v0.10.0)

View Source

AT Protocol OAuth 2.0 authorization flow.

Handles the full OAuth protocol interactions: pushed authorization requests (PAR), authorization code exchange, token refresh, token revocation, client metadata, and client assertions.

See Atex.OAuth.Discovery for authorization server discovery and Atex.OAuth.DPoP for DPoP token creation.

Summary

Functions

Create a JWT client assertion for authenticating with an authorization server.

Get a map containing the client metadata information needed for an authorization server to validate this client.

Revokes the access and refresh tokens with the authorization server.

Exchange an OAuth authorization code for a set of access and refresh tokens.

Types

authorization_metadata()

@type authorization_metadata() :: %{
  issuer: String.t(),
  par_endpoint: String.t(),
  token_endpoint: String.t(),
  authorization_endpoint: String.t(),
  revocation_endpoint: String.t()
}

create_authorization_url_option()

@type create_authorization_url_option() ::
  {:key, JOSE.JWK.t()}
  | {:client_id, String.t()}
  | {:redirect_uri, String.t()}
  | {:scopes, String.t()}

create_client_metadata_option()

@type create_client_metadata_option() ::
  {:key, JOSE.JWK.t()}
  | {:client_id, String.t()}
  | {:redirect_uri, String.t()}
  | {:extra_redirect_uris, [String.t()]}
  | {:scopes, String.t()}

refresh_token_option()

@type refresh_token_option() :: {:key, JOSE.JWK.t()} | {:client_id, String.t()}

tokens()

@type tokens() :: %{
  access_token: String.t(),
  refresh_token: String.t(),
  did: String.t(),
  expires_at: NaiveDateTime.t()
}

validate_authorization_code_option()

@type validate_authorization_code_option() ::
  {:key, JOSE.JWK.t()}
  | {:client_id, String.t()}
  | {:redirect_uri, String.t()}
  | {:scopes, String.t()}

Functions

create_authorization_url(authz_metadata, state, code_verifier, login_hint, opts \\ [])

@spec create_authorization_url(
  authorization_metadata(),
  String.t(),
  String.t(),
  String.t(),
  [create_authorization_url_option()]
) :: {:ok, String.t()} | {:error, any()}

Create an OAuth authorization URL for a PDS.

Submits a PAR request to the authorization server and constructs the authorization URL with the returned request URI. Supports PKCE, DPoP, and client assertions as required by the AT Protocol.

Parameters

  • authz_metadata - Authorization server metadata, from Atex.OAuth.Discovery.get_authorization_server_metadata/2
  • state - Random token for session validation
  • code_verifier - PKCE code verifier
  • login_hint - User identifier (handle or DID) for pre-filled login
  • opts - Optional overrides for :key, :client_id, :redirect_uri, :scopes

Returns

  • {:ok, authorization_url} - Successfully created authorization URL
  • {:error, :invalid_par_response} - Server responded incorrectly to the PAR request
  • {:error, reason} - Error creating authorization URL

create_client_assertion(jwk, client_id, issuer)

@spec create_client_assertion(JOSE.JWK.t(), String.t(), String.t()) :: String.t()

Create a JWT client assertion for authenticating with an authorization server.

Signs a short-lived (60 second) JWT with the client's private key, identifying the client to the authorization server.

Parameters

  • jwk - Client private key (must have a kid field set)
  • client_id - OAuth client identifier
  • issuer - Authorization server issuer URL (used as aud)

create_client_metadata(opts \\ [])

@spec create_client_metadata([create_client_metadata_option()]) :: map()

Get a map containing the client metadata information needed for an authorization server to validate this client.

refresh_token(refresh_token, dpop_key, issuer, token_endpoint, opts \\ [])

@spec refresh_token(
  String.t(),
  JOSE.JWK.t(),
  String.t(),
  String.t(),
  [refresh_token_option()]
) :: {:ok, tokens(), String.t() | nil} | {:error, any()}

Refresh an existing set of OAuth tokens.

Submits the refresh token to the token endpoint using DPoP authentication and a client assertion. Returns the new token set with an updated DPoP nonce.

Parameters

  • refresh_token - The refresh token to exchange
  • dpop_key - JWK for DPoP token generation
  • issuer - Authorization server issuer URL (for client assertion aud)
  • token_endpoint - Token endpoint URL
  • opts - Optional overrides for :key, :client_id

revoke_tokens(session, authz_metadata)

@spec revoke_tokens(Atex.OAuth.Session.t(), authorization_metadata()) :: :ok

Revokes the access and refresh tokens with the authorization server.

Sends the refresh token to the revocation endpoint as defined in RFC 7009. Token revocation failures are logged as warnings rather than returned as errors, since the primary goal (ending the session) is still achieved.

Parameters

  • session - The session containing tokens to revoke
  • authz_metadata - Authorization server metadata including revocation_endpoint

Returns

  • :ok - Tokens revoked (or revocation endpoint unreachable - logged, not raised)

validate_authorization_code(authz_metadata, dpop_key, code, code_verifier, opts \\ [])

@spec validate_authorization_code(
  authorization_metadata(),
  JOSE.JWK.t(),
  String.t(),
  String.t(),
  [validate_authorization_code_option()]
) :: {:ok, tokens(), String.t() | nil} | {:error, any()}

Exchange an OAuth authorization code for a set of access and refresh tokens.

Validates the authorization code by submitting it to the token endpoint along with the PKCE code verifier and client assertion. Returns access tokens for making authenticated requests to the relevant user's PDS.

Parameters

  • authz_metadata - Authorization server metadata containing token endpoint
  • dpop_key - JWK for DPoP token generation
  • code - Authorization code from OAuth callback
  • code_verifier - PKCE code verifier from authorization flow
  • opts - Optional overrides for :key, :client_id, :redirect_uri, :scopes

Returns

  • {:ok, tokens, nonce} - Successfully obtained tokens with returned DPoP nonce
  • {:error, reason} - Error exchanging code for tokens