Lightning.Credentials.OauthToken (Lightning v2.13.4)
View SourceSchema and functions for managing OAuth tokens. This module handles the storage and validation of OAuth tokens in a 1:1 relationship with credentials.
Each token contains all required OAuth 2.0 fields:
- access_token (required)
- refresh_token (required)
- token_type (required, must be "Bearer")
- scope/scopes (required)
- expires_in/expires_at (required)
Integrates with the enhanced OauthValidation module for comprehensive validation.
Summary
Functions
Creates a changeset for validating and creating an OAuth token.
Checks if the token is still fresh (not expired or about to expire).
Creates a changeset for updating token data.
Types
@type t() :: %Lightning.Credentials.OauthToken{ __meta__: term(), body: map(), credential: Lightning.Credentials.Credential.t() | nil, id: Ecto.UUID.t() | nil, inserted_at: DateTime.t() | nil, last_refreshed: DateTime.t() | nil, oauth_client: Lightning.Credentials.OauthClient.t() | nil, oauth_client_id: Ecto.UUID.t() | nil, oauth_error_details: term(), oauth_error_type: term(), scopes: [String.t()], updated_at: DateTime.t() | nil, user: Lightning.Accounts.User.t() | nil, user_id: Ecto.UUID.t() | nil }
Functions
Creates a changeset for validating and creating an OAuth token.
Parameters
attrs
- A map containing token attributes::body
- The token data (required) - must include access_token, refresh_token, token_type, scope/scopes, expires_in/expires_at:scopes
- List of permission scopes for the token (optional, will be extracted from body if not provided):oauth_client_id
- Reference to the OAuth client (required):user_id
- Reference to the user (required)
Validations
- All required fields are validated
- Referenced oauth_client and user must exist
- Token body must contain valid OAuth 2.0 fields
- Scopes are automatically extracted and normalized if not provided
Examples
iex> OauthToken.changeset(%{
...> body: %{
...> "access_token" => "abc123",
...> "refresh_token" => "xyz789",
...> "token_type" => "Bearer",
...> "scope" => "read write",
...> "expires_in" => 3600
...> },
...> oauth_client_id: client.id,
...> user_id: user.id
...> })
#Ecto.Changeset<...>
@spec changeset(t() | map(), map()) :: Ecto.Changeset.t()
@spec still_fresh?(t(), non_neg_integer()) :: boolean()
Checks if the token is still fresh (not expired or about to expire).
Parameters
oauth_token
- The token to checkbuffer_minutes
- Minutes before expiry to consider stale (default: 5)
Returns
true
- Token is fresh and can be usedfalse
- Token is stale (expired or expires within buffer period)
Examples
iex> OauthToken.still_fresh?(token)
true
iex> OauthToken.still_fresh?(token, 10) # More conservative buffer
false
@spec update_changeset(t(), map()) :: Ecto.Changeset.t()
Creates a changeset for updating token data.
Preserves the refresh_token
from the existing token if the provider doesn't return a new one.
This is common with some OAuth providers that only return refresh_token
on initial authorization.
By default, this function updates the last_refreshed
timestamp to the current UTC time.
If the update is not the result of an actual token refresh (e.g., only scopes changed),
you can pass the option refreshed: false
to skip updating the timestamp.
Parameters
oauth_token
- The existingOauthToken
struct.new_token
- A map containing new token data from the OAuth provider.opts
- (optional) A keyword list of options::refreshed
- Whether this update corresponds to an actual token refresh (default:true
).
Examples
iex> OauthToken.update_token_changeset(existing_token, %{
...> "access_token" => "new_access_token",
...> "expires_in" => 3600,
...> "scope" => "read write admin"
...> })
#Ecto.Changeset<...>
iex> OauthToken.update_token_changeset(existing_token, new_token_map, refreshed: false)
#Ecto.Changeset<...>