View Source oidcc_token (Oidcc v3.2.0)

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