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.

t()

Token Response Wrapper.

Options for refreshing a token.

Types

Link to this type

access()

View Source (since 3.0.0)
-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.
Link to this type

authorization_headers_opts()

View Source (since 3.0.0)
-type authorization_headers_opts() :: #{dpop_nonce => binary()}.
Link to this type

client_credentials_opts()

View Source (since 3.0.0)
-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.
Link to this type

jwt_profile_opts()

View Source (since 3.0.0)
-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()}.
Link to this type

refresh()

View Source (since 3.0.0)
-type refresh() :: #oidcc_token_refresh{token :: binary()}.

Refresh Token Wrapper.

Fields

  • token - The retrieved token.
Link to this type

refresh_opts()

View Source (since 3.0.0)
-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()}.
Link to this type

refresh_opts_no_sub()

View Source (since 3.0.0)
-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()}.

See refresh_opts_no_sub/0.

Link to this type

retrieve_opts()

View Source (since 3.0.0)
-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

-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

Link to this type

validate_jarm_opts()

View Source (since 3.2.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

Link to this type

validate_jwt_opts()

View Source (since 3.2.0)
-type validate_jwt_opts() ::
          #{signing_algs => [binary()] | undefined,
            encryption_algs => [binary()] | undefined,
            encryption_encs => [binary()] | undefined}.

Functions

Link to this function

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).
Link to this function

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()}.
Link to this function

client_credentials(ClientContext, Opts)

View Source (since 3.0.0)
-spec client_credentials(ClientContext, Opts) -> {ok, t()} | {error, error()}
                            when
                                ClientContext :: oidcc_client_context:authenticated_t(),
                                Opts :: client_credentials_opts().
Link to this function

jwt_profile(Subject, ClientContext, Jwk, Opts)

View Source (since 3.0.0)
-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">>}).
Link to this function

retrieve(AuthCode, ClientContext, Opts)

View Source (since 3.0.0)
-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">>}).
Link to this function

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().
Link to this function

validate_jarm(Response, ClientContext, Opts)

View Source (since 3.2.0)
-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/">>}).
Link to this function

validate_jwt(Jwt, ClientContext, Opts)

View Source (since 3.2.0)
-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).