View Source oidcc_token (Oidcc v3.2.1)

Facilitate OpenID Code/Token Exchanges

Records

To use the records, import the definition:

  -include_lib(["oidcc/include/oidcc_token.hrl"]).

Telemetry

See 'Elixir.Oidcc.Token'

Summary

Types

Access Token Wrapper

Refresh Token Wrapper

Options for retrieving a token

t/0

Token Response Wrapper

Options for refreshing a token

Types

Link to this type

access/0

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/0

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

client_credentials_opts/0

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

error/0

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

id/0

View Source (since 3.0.0 -------------------------------------------------------------------)
-type id() :: #oidcc_token_id{token :: binary(), claims :: oidcc_jwt_util:claims()}.
Link to this type

jwt_profile_opts/0

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/0

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/0

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/0

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()

Link to this type

retrieve_opts/0

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

Link to this type

t/0

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

View Source (since 3.0.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/0

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

Retrieve Client Credential Token

See https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.4

For a high level interface using oidcc_provider_configuration_worker see oidcc:client_credentials_token/4.

Examples

  {ok, ClientContext} =
    oidcc_client_context:from_configuration_worker(provider_name,
                                                   <<"client_id">>,
                                                   <<"client_secret">>),
 
  {ok, #oidcc_token{}} =
    oidcc_token:client_credentials(ClientContext,
                                   #{scope => [<<"scope">>]}).
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 oidcc_provider_configuration_worker see 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)}).
Link to this function

refresh(RefreshToken, ClientContext, Opts)

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

Validate ID Token

Usually the id token is validated using retrieve/3. If you get the token passed from somewhere else, this function can validate it.

Examples

  {ok, ClientContext} =
    oidcc_client_context:from_configuration_worker(provider_name,
                                                   <<"client_id">>,
                                                   <<"client_secret">>),
 
  %% Get IdToken from somewhere
 
  {ok, Claims} =
    oidcc:validate_id_token(IdToken, ClientContext, ExpectedNonce).
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).