View Source oidcc_token (Oidcc v3.2.6)
Facilitate OpenID Code/Token Exchanges.
Records
To use the records, import the definition:
-include_lib(["oidcc/include/oidcc_token.hrl"]).
Telemetry
See Oidcc.Token
.
Summary
Types
Access Token Wrapper.
ID Token Wrapper.
Refresh Token Wrapper.
Options for retrieving a token.
Token Response Wrapper.
Options for refreshing a token.
Functions
Authorization headers
Retrieve JSON Web Token (JWT) Profile Token
Refresh Token
Retrieve the token using the authcode received before and directly validate the result.
Validate the JARM response, returning the valid claims as a map.
Validate JWT
Types
-type access() :: #oidcc_token_access{token :: binary(), expires :: pos_integer() | undefined, type :: binary()}.
Access Token Wrapper.
Fields
token
- The retrieved token.expires
- Number of seconds the token is valid.
-type authorization_headers_opts() :: #{dpop_nonce => binary()}.
-type client_credentials_opts() :: #{scope => oidcc_scope:scopes(), refresh_jwks => oidcc_jwt_util:refresh_jwks_for_unknown_kid_fun(), request_opts => oidcc_http_util:request_opts(), url_extension => oidcc_http_util:query_params(), body_extension => oidcc_http_util:query_params()}.
-type error() :: {missing_claim, MissingClaim :: binary(), Claims :: oidcc_jwt_util:claims()} | pkce_verifier_required | no_supported_auth_method | bad_access_token_hash | sub_invalid | token_expired | token_not_yet_valid | {none_alg_used, Token :: t()} | {missing_claim, ExpClaim :: {binary(), term()}, Claims :: oidcc_jwt_util:claims()} | {grant_type_not_supported, authorization_code | refresh_token | jwt_bearer | client_credentials} | {invalid_property, {Field :: id_token | refresh_token | access_token | expires_in | scopes, GivenValue :: term()}} | no_supported_code_challenge | oidcc_jwt_util:error() | oidcc_http_util:error().
-type id() :: #oidcc_token_id{token :: binary(), claims :: oidcc_jwt_util:claims()}.
ID Token Wrapper.
Fields
token
- The retrieved token.claims
- Unpacked claims of the verified token.
-type jwt_profile_opts() :: #{scope => oidcc_scope:scopes(), refresh_jwks => oidcc_jwt_util:refresh_jwks_for_unknown_kid_fun(), request_opts => oidcc_http_util:request_opts(), kid => binary(), url_extension => oidcc_http_util:query_params(), body_extension => oidcc_http_util:query_params()}.
-type refresh() :: #oidcc_token_refresh{token :: binary()}.
Refresh Token Wrapper.
Fields
token
- The retrieved token.
-type refresh_opts() :: #{scope => oidcc_scope:scopes(), refresh_jwks => oidcc_jwt_util:refresh_jwks_for_unknown_kid_fun(), expected_subject := binary(), request_opts => oidcc_http_util:request_opts(), url_extension => oidcc_http_util:query_params(), body_extension => oidcc_http_util:query_params()}.
-type refresh_opts_no_sub() :: #{scope => oidcc_scope:scopes(), refresh_jwks => oidcc_jwt_util:refresh_jwks_for_unknown_kid_fun(), request_opts => oidcc_http_util:request_opts(), url_extension => oidcc_http_util:query_params(), body_extension => oidcc_http_util:query_params()}.
-type retrieve_opts() :: #{pkce_verifier => binary(), require_pkce => boolean(), nonce => binary() | any, scope => oidcc_scope:scopes(), preferred_auth_methods => [oidcc_auth_util:auth_method(), ...], refresh_jwks => oidcc_jwt_util:refresh_jwks_for_unknown_kid_fun(), redirect_uri => uri_string:uri_string(), request_opts => oidcc_http_util:request_opts(), url_extension => oidcc_http_util:query_params(), body_extension => oidcc_http_util:query_params(), dpop_nonce => binary(), trusted_audiences => [binary()] | any}.
Options for retrieving a token.
See https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3.
Fields
pkce_verifier
- PKCE verifier (random string previously given tooidcc_authorization
), see https://datatracker.ietf.org/doc/html/rfc7636#section-4.1.require_pkce
- whether to require PKCE when getting the token.nonce
- Nonce to check.scope
- Scope to store with the token.refresh_jwks
- How to handle tokens with an unknownkid
. Seeoidcc_jwt_util:refresh_jwks_for_unknown_kid_fun/0
.redirect_uri
- Redirect URI given tooidcc_authorization:create_redirect_url/2
.dpop_nonce
- if using DPoP, thenonce
value to use in the proof claim.trusted_audiences
- if present, a list of additional audience values to accept. Defaults toany
which allows any additional values.
-type t() :: #oidcc_token{id :: oidcc_token:id() | none, access :: oidcc_token:access() | none, refresh :: oidcc_token:refresh() | none, scope :: oidcc_scope:scopes()}.
Token Response Wrapper.
Fields
id
-id/0
.access
-access/0
.refresh
-refresh/0
.scope
-oidcc_scope:scopes/0
.
-type validate_jarm_opts() :: #{trusted_audiences => [binary()] | any}.
Options for refreshing a token.
See https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3.
Fields
scope
- Scope to store with the token.refresh_jwks
- How to handle tokens with an unknownkid
. Seeoidcc_jwt_util:refresh_jwks_for_unknown_kid_fun/0
.expected_subject
-sub
of the original token.
Functions
authorization_headers(AccessTokenRecord, Method, Endpoint, ClientContext)
View Source (since 3.2.0)-spec authorization_headers(AccessTokenRecord, Method, Endpoint, ClientContext) -> HeaderMap when AccessTokenRecord :: access(), Method :: post | get, Endpoint :: uri_string:uri_string(), ClientContext :: oidcc_client_context:t(), HeaderMap :: #{binary() => binary()}.
Authorization headers
Generate a map of authorization headers to use when using the given access token to access an API endpoint.
Examples
{ok, ClientContext} =
oidcc_client_context:from_configuration_worker(provider_name,
<<"client_id">>,
<<"client_secret">>),
%% Get Access Token record from somewhere
Headers =
oidcc:authorization_headers(AccessTokenRecord, :get, Url, ClientContext).
authorization_headers(AccessTokenRecord, Method, Endpoint, ClientContext, Opts)
View Source (since 3.0.0)-spec authorization_headers(AccessTokenRecord, Method, Endpoint, ClientContext, Opts) -> HeaderMap when AccessTokenRecord :: access(), Method :: post | get, Endpoint :: uri_string:uri_string(), ClientContext :: oidcc_client_context:t(), Opts :: authorization_headers_opts(), HeaderMap :: #{binary() => binary()}.
-spec client_credentials(ClientContext, Opts) -> {ok, t()} | {error, error()} when ClientContext :: oidcc_client_context:authenticated_t(), Opts :: client_credentials_opts().
-spec jwt_profile(Subject, ClientContext, Jwk, Opts) -> {ok, t()} | {error, error()} when Subject :: binary(), ClientContext :: oidcc_client_context:t(), Jwk :: jose_jwk:key(), Opts :: jwt_profile_opts().
Retrieve JSON Web Token (JWT) Profile Token
See [https://datatracker.ietf.org/doc/html/rfc7523#section-4]
For a high level interface using {@link oidcc_provider_configuration_worker} see {@link oidcc:jwt_profile_token/6}.
Examples
{ok, ClientContext} =
oidcc_client_context:from_configuration_worker(provider_name,
<<"client_id">>,
<<"client_secret">>),
{ok, KeyJson} = file:read_file("jwt-profile.json"),
KeyMap = jose:decode(KeyJson),
Key = jose_jwk:from_pem(maps:get(<<"key">>, KeyMap)),
{ok, #oidcc_token{}} =
oidcc_token:jwt_profile(<<"subject">>,
ClientContext,
Key,
#{scope => [<<"scope">>],
kid => maps:get(<<"keyId">>, KeyMap)}).
-spec refresh(RefreshToken, ClientContext, Opts) -> {ok, t()} | {error, error()} when RefreshToken :: binary(), ClientContext :: oidcc_client_context:t(), Opts :: refresh_opts(); (Token, ClientContext, Opts) -> {ok, t()} | {error, error()} when Token :: oidcc_token:t(), ClientContext :: oidcc_client_context:t(), Opts :: refresh_opts_no_sub().
Refresh Token
For a high level interface using oidcc_provider_configuration_worker
see oidcc:refresh_token/5
.
Examples
{ok, ClientContext} =
oidcc_client_context:from_configuration_worker(provider_name,
<<"client_id">>,
<<"client_secret">>),
%% Get AuthCode from Redirect
{ok, Token} =
oidcc_token:retrieve(AuthCode, ClientContext, #{
redirect_uri => <<"https://example.com/callback">>}).
%% Later
{ok, #oidcc_token{}} =
oidcc_token:refresh(Token,
ClientContext,
#{expected_subject => <<"sub_from_initial_id_token">>}).
-spec retrieve(AuthCode, ClientContext, Opts) -> {ok, t()} | {error, error()} when AuthCode :: binary(), ClientContext :: oidcc_client_context:t(), Opts :: retrieve_opts().
Retrieve the token using the authcode received before and directly validate the result.
The authcode was sent to the local endpoint by the OpenId Connect provider, using redirects.
For a high level interface using oidcc_provider_configuration_worker
see oidcc:retrieve_token/5
.
Examples
{ok, ClientContext} =
oidcc_client_context:from_configuration_worker(provider_name,
<<"client_id">>,
<<"client_secret">>),
%% Get AuthCode from Redirect
{ok, #oidcc_token{}} =
oidcc:retrieve(AuthCode, ClientContext, #{
redirect_uri => <<"https://example.com/callback">>}).
validate_id_token(IdToken, ClientContext, NonceOrOpts)
View Source (since 3.0.0)-spec validate_id_token(IdToken, ClientContext, NonceOrOpts) -> {ok, Claims} | {error, error()} when IdToken :: binary(), ClientContext :: oidcc_client_context:t(), NonceOrOpts :: Nonce | retrieve_opts(), Nonce :: binary() | any, Claims :: oidcc_jwt_util:claims().
-spec validate_jarm(Response, ClientContext, Opts) -> {ok, oidcc_jwt_util:claims()} | {error, error()} when Response :: binary(), ClientContext :: oidcc_client_context:t(), Opts :: validate_jarm_opts().
Validate the JARM response, returning the valid claims as a map.
The response was sent to the local endpoint by the OpenId Connect provider, using redirects.
Examples
{ok, ClientContext} =
oidcc_client_context:from_configuration_worker(provider_name,
<<"client_id">>,
<<"client_secret">>),
%% Get Response from Redirect
{ok, #{<<"code">> := AuthCode}} =
oidcc:validate_jarm(Response, ClientContext, #{}),
{ok, #oidcc_token{}} = oidcc:retrieve(AuthCode, ClientContext,
#{redirect_uri => <<"https://redirect.example/">>}).
-spec validate_jwt(Jwt, ClientContext, Opts) -> {ok, Claims} | {error, error()} when Jwt :: binary(), ClientContext :: oidcc_client_context:t(), Opts :: validate_jwt_opts(), Claims :: oidcc_jwt_util:claims().
Validate JWT
Validates a generic JWT (such as an access token) from the given provider. Useful if the issuer is shared between multiple applications, and the access token generated for a user at one client is used to validate their access at another client.
Examples
{ok, ClientContext} =
oidcc_client_context:from_configuration_worker(provider_name,
<<"client_id">>,
<<"client_secret">>),
%% Get Jwt from Authorization header
{ok, Claims} =
oidcc:validate_jwt(Jwt, ClientContext, Opts).