View Source Oidcc.Token (Oidcc v3.2.6)

Facilitate OpenID Code/Token Exchanges

Telemetry

  • [:oidcc, :request_token, :start]

    • Description: Emitted at the start of requesting a code token
    • Measurements: %{system_time: non_neg_integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :request_token, :stop]

    • Description: Emitted at the end of requesting a code token
    • Measurements: %{duration: integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :request_token, :exception]

    • Description: Emitted at the end of requesting a code token
    • Measurements: %{duration: integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :refresh_token, :start]

    • Description: Emitted at the start of refreshing a token
    • Measurements: %{system_time: non_neg_integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :refresh_token, :stop]

    • Description: Emitted at the end of refreshing a token
    • Measurements: %{duration: integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :refresh_token, :exception]

    • Description: Emitted at the end of refreshing a token
    • Measurements: %{duration: integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :jwt_profile_token, :start]

    • Description: Emitted at the start of exchanging a JWT profile token
    • Measurements: %{system_time: non_neg_integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :jwt_profile_token, :stop]

    • Description: Emitted at the end of exchanging a JWT profile token
    • Measurements: %{duration: integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :jwt_profile_token, :exception]

    • Description: Emitted at the end of exchanging a JWT profile token
    • Measurements: %{duration: integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :client_credentials, :start]

    • Description: Emitted at the start of requesting a client credentials token
    • Measurements: %{system_time: non_neg_integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :client_credentials, :stop]

    • Description: Emitted at the end of requesting a client credentials token
    • Measurements: %{duration: integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}
  • [:oidcc, :client_credentials, :exception]

    • Description: Emitted at the end of requesting a client credentials token
    • Measurements: %{duration: integer(), monotonic_time: integer()}
    • Metadata: %{issuer: :uri_string.uri_string(), client_id: String.t()}

Summary

Functions

Retrieve Client Credential Token

Retrieve JSON Web Token (JWT) Profile 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.

Types

@type t() :: %Oidcc.Token{
  access: Oidcc.Token.Access.t() | none(),
  id: Oidcc.Token.Id.t() | none(),
  refresh: Oidcc.Token.Refresh.t() | none(),
  scope: :oidcc_scope.scopes()
}

Functions

Link to this function

client_credentials(client_context, opts)

View Source (since 3.0.0)
@spec client_credentials(
  client_context :: Oidcc.ClientContext.t(),
  opts :: :oidcc_token.client_credentials_opts()
) :: {:ok, t()} | {:error, :oidcc_token.error()}

Retrieve Client Credential Token

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

For a high level interface using Oidcc.ProviderConfiguration.Worker see Oidcc.client_credentials_token/4.

Examples

iex> {:ok, pid} =
...>   Oidcc.ProviderConfiguration.Worker.start_link(%{
...>     issuer: "https://erlef-test-w4a8z2.zitadel.cloud"
...>   })
...>
...> {:ok, client_context} =
...>   Oidcc.ClientContext.from_configuration_worker(
...>     pid,
...>     System.fetch_env!("CLIENT_CREDENTIALS_CLIENT_ID"),
...>     System.fetch_env!("CLIENT_CREDENTIALS_CLIENT_SECRET")
...>   )
...>
...> {:ok, %Oidcc.Token{}} =
...>   Oidcc.Token.client_credentials(
...>     client_context,
...>     %{scope: ["openid"]}
...>   )
Link to this function

jwt_profile(subject, client_context, jwk, opts)

View Source (since 3.0.0)
@spec jwt_profile(
  subject :: String.t(),
  client_context :: Oidcc.ClientContext.t(),
  jwk :: JOSE.JWK.t(),
  opts :: :oidcc_token.jwt_profile_opts()
) :: {:ok, t()} | {:error, :oidcc_token.error()}

Retrieve JSON Web Token (JWT) Profile Token

See https://datatracker.ietf.org/doc/html/rfc7523#section-4

For a high level interface using Oidcc.ProviderConfiguration.Worker see Oidcc.jwt_profile_token/6.

Examples

iex> {:ok, pid} =
...>   Oidcc.ProviderConfiguration.Worker.start_link(%{
...>     issuer: "https://erlef-test-w4a8z2.zitadel.cloud"
...>   })
...>
...> {:ok, client_context} =
...>   Oidcc.ClientContext.from_configuration_worker(
...>     pid,
...>     "JWT Profile Test",
...>     "client_secret"
...>   )
...>
...> %{"key" => key, "keyId" => kid, "userId" => subject} = "JWT_PROFILE"
...>   |> System.fetch_env!()
...>   |> JOSE.decode()
...>
...> jwk = JOSE.JWK.from_pem(key)
...>
...> {:ok, %Oidcc.Token{}} =
...>   Oidcc.Token.jwt_profile(
...>     subject,
...>     client_context,
...>     jwk,
...>     %{scope: ["openid", "urn:zitadel:iam:org:project:id:zitadel:aud"], kid: kid}
...>   )
Link to this function

refresh(token, client_context, opts)

View Source (since 3.0.0)
@spec refresh(
  refresh_token :: String.t(),
  client_context :: Oidcc.ClientContext.t(),
  opts :: :oidcc_token.refresh_opts()
) :: {:ok, t()} | {:error, :oidcc_token.error()}
@spec refresh(
  token :: t(),
  client_context :: Oidcc.ClientContext.t(),
  opts :: :oidcc_token.refresh_opts_no_sub()
) :: {:ok, t()} | {:error, :oidcc_token.error()}

Refresh Token

For a high level interface using Oidcc.ProviderConfiguration.Worker see Oidcc.refresh_token/5.

Examples

iex> {:ok, pid} =
...>   Oidcc.ProviderConfiguration.Worker.start_link(%{
...>     issuer: "https://api.login.yahoo.com"
...>   })
...>
...> {:ok, client_context} =
...>   Oidcc.ClientContext.from_configuration_worker(
...>     pid,
...>     "client_id",
...>     "client_secret"
...>   )
...>
...> # Get refresh_token from redirect
...> refresh_token = "refresh_token"
...>
...> Oidcc.Token.refresh(
...>   refresh_token,
...>   client_context,
...>   %{expected_subject: "sub"}
...> )
...> # => {:ok, %Oidcc.Token{}}
Link to this function

retrieve(auth_code, client_context, opts)

View Source (since 3.0.0)
@spec retrieve(
  auth_code :: String.t(),
  client_context :: Oidcc.ClientContext.t(),
  opts :: :oidcc_token.retrieve_opts()
) :: {:ok, t()} | {:error, :oidcc_token.error()}

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.ProviderConfiguration.Worker see Oidcc.retrieve_token/5.

Examples

iex> {:ok, pid} =
...>   Oidcc.ProviderConfiguration.Worker.start_link(%{
...>     issuer: "https://api.login.yahoo.com"
...>   })
...>
...> {:ok, client_context} =
...>   Oidcc.ClientContext.from_configuration_worker(
...>     pid,
...>     "client_id",
...>     "client_secret"
...>   )
...>
...> # Get auth_code from redirect
...> auth_code = "auth_code"
...>
...> Oidcc.Token.retrieve(
...>   auth_code,
...>   client_context,
...>   %{redirect_uri: "https://my.server/return"}
...> )
...> # => {:ok, %Oidcc.Token{}}
Link to this function

validate_id_token(id_token, client_context, nonce)

View Source (since 3.0.0)
@spec validate_id_token(
  id_token :: String.t(),
  client_context :: Oidcc.ClientContext.t(),
  nonce :: String.t() | any()
) :: {:ok, :oidcc_jwt_util.claims()} | {:error, :oidcc_token.error()}

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

iex> {:ok, pid} =
...>   Oidcc.ProviderConfiguration.Worker.start_link(%{
...>     issuer: "https://api.login.yahoo.com"
...>   })
...>
...> {:ok, client_context} =
...>   Oidcc.ClientContext.from_configuration_worker(
...>     pid,
...>     "client_id",
...>     "client_secret"
...>   )
...>
...> #Get IdToken from somewhere
...> id_token = "id_token"
...>
...> Oidcc.Token.validate_id_token(id_token, client_context, :any)
...> # => {:ok, %{"sub" => "sub", ... }}
Link to this function

validate_jarm(response, client_context, opts)

View Source (since 3.2.0)
@spec validate_jarm(
  response :: String.t(),
  client_context :: Oidcc.ClientContext.t(),
  opts :: :oidcc_token.validate_jarm_opts()
) :: {:ok, :oidcc_jwt_util.claims()} | {:error, :oidcc_token.error()}

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

iex> {:ok, pid} =
...>   Oidcc.ProviderConfiguration.Worker.start_link(%{
...>     issuer: "https://api.login.yahoo.com"
...>   })
...>
...> {:ok, client_context} =
...>   Oidcc.ClientContext.from_configuration_worker(
...>     pid,
...>     "client_id",
...>     "client_secret"
...>   )
...>
...> # Get auth_code from redirect
...> response = "JWT"
...>
...> Oidcc.Token.validate_jarm(
...>   response,
...>   client_context,
...>   %{}
...> )
...> # => {:ok, %{"code" => auth_code}}
Link to this function

validate_jwt(jwt, client_context, opts)

View Source (since 3.0.0)
@spec validate_jwt(
  jwt :: String.t(),
  client_context :: Oidcc.ClientContext.t(),
  opts :: :oidcc_token.validate_jwt_opts()
) :: {:ok, :oidcc_jwt_util.claims()} | {:error, :oidcc_token.error()}

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

iex> {:ok, pid} =
...>   Oidcc.ProviderConfiguration.Worker.start_link(%{
...>     issuer: "https://api.login.yahoo.com"
...>   })
...>
...> {:ok, client_context} =
...>   Oidcc.ClientContext.from_configuration_worker(
...>     pid,
...>     "client_id",
...>     "client_secret"
...>   )
...>
...> #Get JWT from Authorization header
...> jwt = "jwt"
...>
...> opts = %{
...>   signing_algs: client_context.provider_configuration.id_token_signing_alg_values_supported
...> }
...>
...> Oidcc.Token.validate_jwt(jwt, client_context, opts)
...> # => {:ok, %{"sub" => "sub", ... }}