OAuth 2.0 access token response.
A cacheable struct holding the parsed token data from a platform's token
endpoint. Host apps can store this and reuse it across contexts via
Ltix.OAuth.Client.from_access_token/2. To store it outside the VM, such as
in a database, save to_map/1 as JSON and restore it with from_map/1.
Examples
iex> {:ok, token} = Ltix.OAuth.AccessToken.from_response(
...> %{
...> "access_token" => "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9",
...> "token_type" => "Bearer",
...> "expires_in" => 3600,
...> "scope" => "https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly"
...> },
...> now: ~U[2025-01-01 00:00:00Z]
...> )
iex> token.access_token
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9"
iex> token.token_type
"bearer"
iex> token.granted_scopes
MapSet.new(["https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly"])
iex> token.expires_at
~U[2025-01-01 01:00:00Z]
Summary
Types
@type t() :: %Ltix.OAuth.AccessToken{ access_token: String.t(), expires_at: DateTime.t(), granted_scopes: MapSet.t(String.t()), issued_at: DateTime.t() | nil, token_type: String.t() }
Functions
Check whether the token has expired.
A token counts as expired 60 seconds before its expiry, so it isn't used
when about to expire. A token with a lifetime under two minutes counts as
expired halfway through its lifetime. Without an issued_at time,
the 60 seconds apply.
Examples
iex> token = %Ltix.OAuth.AccessToken{expires_at: DateTime.add(DateTime.utc_now(), 3600)}
iex> Ltix.OAuth.AccessToken.expired?(token)
false
@spec from_map(map()) :: {:ok, t()} | {:error, Exception.t()}
Restore a token from a map returned by to_map/1.
Returns Ltix.Errors.Invalid.InvalidField for a missing or malformed
field.
Examples
iex> {:ok, token} = Ltix.OAuth.AccessToken.from_map(%{
...> "access_token" => "tok",
...> "scope" => "scope:read",
...> "expires_at" => "2025-01-01T01:00:00Z"
...> })
iex> {token.access_token, token.granted_scopes, token.expires_at}
{"tok", MapSet.new(["scope:read"]), ~U[2025-01-01 01:00:00Z]}
@spec from_response(term(), keyword()) :: {:ok, t()} | {:error, Exception.t()}
Parse a bearer access token from a token endpoint response body.
If "expires_in" is omitted, the lifetime defaults to 3600 seconds.
Options
:requested_scopes- list of scope strings that were requested, used when the response omits"scope".:now- override current time (defaults toDateTime.utc_now/0).
Convert a token to a map with string keys and values that encodes to JSON.
Restore it with from_map/1.
Examples
iex> token = %Ltix.OAuth.AccessToken{
...> access_token: "tok",
...> token_type: "bearer",
...> granted_scopes: MapSet.new(["scope:write", "scope:read"]),
...> expires_at: ~U[2025-01-01 01:00:00Z]
...> }
iex> Ltix.OAuth.AccessToken.to_map(token)
%{
"access_token" => "tok",
"scope" => "scope:read scope:write",
"expires_at" => "2025-01-01T01:00:00Z"
}