Skip to main content
Version: 2.0.0-beta

OpenID Connect

Introduction

LoginID supports OpenID Connect to enable easy integrations that require very little effort. This document explains the supported features, how to get started and how to use it.

Overview

LoginID supports OpenID Connect as an OpenID Provider (OP) and allows developers to sign up, register applications and leverage passkeys within their applications without having to implement support for passkeys themselves. Application users register and sign up within the developer's project (which is like a tenant ID) during the authentication and authorization flows. Developers will find an overview of application users within the customer dashboard.

Getting started

To begin utilizing LoginID's OpenID Connect (OIDC) support, the first step is to signin on LoginID's customer dashboard. Following signin, you'll need to create an OIDC project and application.

Creating OIDC Project

After signing in to the dashboard proceed with the following:

  1. Go to the advanced setup page.
  2. Select OIDC project type.
  3. Enter Project Name.
  4. Press Confirm button.
  5. Go to Settings - OIDC section.
  6. This is where you can find all relevant endpoints.

Create OIDC Application

note

In OAuth, applications are commonly referred to as clients.

Public Application

It is recommended to make your application public if your client application falls into any of these categories:

  • Single-page applications (SPAs).
  • Mobile applications without a secure backend.
  • Clients running in environments where securing a client secret is challenging.

Steps

  1. Click on Application tab.
  2. Click on + Add Application
  3. Select OpenID Connect (OIDC).
  4. Enter Application Name.
  5. Enter Redirect URIs. This is the URL to which LoginID redirects users after finishing the authorization_code flow.
  6. Select wanted scopes and/or enter any Custom Scopes. These values are the only ones LoginID will grant and only those will be displayed to application users during the authorization flow.
  7. Click Create.
  8. Obtain the application ID.

Confidential Application

It is recommended to make your application confidential if your client application falls into any of these categories:

  • Web applications running on a server.
  • Mobile applications with a secure backend.
  • Applications where the client can securely store and manage a client secret.

Steps

  1. Click on Application tab.
  2. Click on + Add Application
  3. Select OpenID Connect (OIDC).
  4. Enter Application Name.
  5. Enter Redirect URIs. This is the URL to which LoginID redirects users after finishing the authorization_code flow.
  6. Select wanted scopes and/or enter any Custom Scopes. These values are the only ones LoginID will grant and only those will be displayed to application users during the authorization flow.
  7. Click Generate Key Pair to generate an ES256 private key (more info in here).
  8. Click Create.
  9. Obtain the application ID.

Well-Known Endpoint

{{issuer URL}}/oidc/.well-known/openid-configuration endpoint serves as the discovery endpoint, providing a dynamic and standardized way for client applications to retrieve configuration information about an OpenID Connect provider.

Find the project issuer URL under Settings - OIDC in your project.

Generating a client_secret

Generating a client_secret requires a ES256 private key to first be generated when creating a confidential application. Clicking on Generate Key Pair will create an ES256 keypair through the Web Crypto API. Please note that the private key is visible only once and can be copied and securely stored on your end. The public key will be transmitted to LoginID and used for verifying a signed client_secret with the corresponding private key.

The client_secret is a signed JWT with specific required information. You can use any cryptography library that supports ES256 private key signing for token creation.

{
"iss": "<application ID>",
"sub": "<application ID>",
"aud": "<hostname of your project issuer URL>",
"exp": "<expiry date of the token in epoch seconds>"
}

Here is an actual example:

{
"iss": "AcdrRdnMcfvnQu1YZWuw9Q",
"sub": "AcdrRdnMcfvnQu1YZWuw9Q",
"aud": "8n3y7rz3a0zigtqsh-olpq.gen2.playground.loginid.io",
"exp": 1717564137
}
Generated JWT:
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBY2RyUmRuTWNmdm5RdTFZWld1dzlRIiw
ic3ViIjoipppWNkclJkbk1jZnZuUXUxWVpXdXc5USIsImF1ZCI6IjhuM3k3cnozYTB6aWd0cXNoLW9scHE
uZ2VuMi5xYS5sb2dpbmlkLmlvIiwiZXhwIjoxNzE3NTY0OTk1LCJpYXQiOjE3MDIwMTI5OTV9.mZ3dm_
JFvIj8qPgJZ1n7oLz63G-ctfUz0WL6BBuo8RAFj3wNOsEoD0neeLGH6mZgHDohAtWUGrbZYmbfUSWGTQ
note

Find the project issuer URL under Settings - OIDC in your project.

Initializing an authorization flow

Initialize the authorization code flow

note

Always URL encode any parameter values.

Typically, a client redirects users to the authorization endpoint like this:

Public Applications

curl -X GET "{{base_url}}/oidc/auth" \
-d "client_id={{app_id}}" \
-d "redirect_uri={{redirect_uri}}" \
-d "response_type=code" \
-d "code_challenge={{code}}" \
-d "code_challenge_method=S256" \
-d "scope=openid offline_access" \
-d "state={{state}}" \
-d "nonce={{nonce}}"

Private Applications

curl -X GET "{{base_url}}/oidc/auth" \
-d "client_id={{app_id}}" \
-d "redirect_uri={{redirect_uri}}" \
-d "response_type=code" \
-d "scope=openid offline_access" \
-d "state={{state}}" \
-d "nonce={{nonce}}"

Parameter Description

  • client_id (required): The unique identifier for your client application.
  • redirect_uri (required): The URI to which LoginID will redirect the user after authentication.
  • response_type (required): The response type requested. Use code to indicate that the response will include an authorization code.
  • code_challenge (required for public applications): A code verifier challenge generated by the client.
  • code_challenge_method (required for public applications): The method used to transform the code verifier into a challenge. Set to S256 for the SHA-256 transformation.
  • scope (required): The requested scopes for the access token. Include a space-separated list of scopes such as openid email offline_access.
  • state (recommended): A random value generated by the client, which will be included in the response to mitigate CSRF attacks.
  • nonce (recommended): A random value generated by the client, which will be included in the ID Token to associate it with the user's session.

LoginID will then handle the authentication flows and will allow the client applications to request user consent.

Once LoginID has handled the user authentication and authorization it will redirect the user back to the client.

The redirect includes either of these parameter combinations:

//success
{redirect_uri}?code={authorization_code}&state={state}

//error
{redirect_uri}?error={error}&error_description={error_description}

Token Response

After receiving the authorization_code the client has to exchange it for a token response which includes an access_token and an id_token. Depending on the grant type, the token request payload will differ.

authorization_code

code_verifier (PKCE)

If you are using a public application you can use authorization_code grant to exchange your token. code_verifier is the original code verifier used during the authorization code request (code_challenge).

curl --request POST '{{base_url}}/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={{client_id}}' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code={{authorization_code}}' \
--data-urlencode 'redirect_uri={{redirect_uri}}' \
--data-urlencode 'code_verifier={{code_verifier}}'

For confidential applications, you have three authentication methods to choose from.

note

A generated client_secret is required.

client_secret_basic

curl --request POST '{{base_url}}/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic {{client_secret}}' \
--data-urlencode 'client_id={{client_id}}' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code={{authorization_code}}' \
--data-urlencode 'redirect_uri={{redirect_uri}}'

client_secret_post

curl --request POST '{{base_url}}/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={{client_id}}' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code={{authorization_code}}' \
--data-urlencode 'redirect_uri={{redirect_uri}}' \
--data-urlencode 'client_secret={{client_secret}}'

private_key_jwt

curl --request POST '{{base_url}}/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={{client_id}}' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code={{authorization_code}}' \
--data-urlencode 'redirect_uri={{redirect_uri}}' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion={{client_secret}}'

refresh_token

The refresh_token flow is used to obtain a new access token by presenting a refresh token to LoginID. This flow is designed to extend the lifetime of an authenticated session without requiring the user to re-enter their credentials.

note

Refresh token will be returned if offline_access scope was requested.

curl --location --request POST '{{base_url}}/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={{app_id}}' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token={{refresh_token}}' \
--data-urlencode 'redirect_uri={{redirect_uri}}'

client_credentials

The client_credentials flow is a grant type designed for scenarios where a confidential client needs to access resources it owns or manages, without the involvement of a user. In this flow, the client authenticates itself directly to LoginID and obtains an access token, which is then used to access protected resources. It is typically used for machine-to-machine communication where machines or services need to communicate securely without user involvement.

One of the three authentication methods can be used. Just replace grant_type with client_credentials.

Response

The successful response (status: 200) will contain these values:

note

Refresh token will be returned if offline_access scope was requested.

{
"id_token": "<id_token>",
"refresh_token": "<refresh_token>",
"access_token": "<access_token>",
"token_type": "Bearer",
"expires_in": 3600
}

An error response (status: >= 400) will have this structure:

{
"error": "<error-reason>",
"error_description": "<error-details>"
}

Processing the token response

The token endpoint provides an id_token and access_token. Here's how LoginID allows you to utilize them.

ID Token

This token is expressed as a JSON Web Token and its content adheres to the OpenID Connect core specification. It represents an authenticated user.

It is recommended to validate the claims.

  • verify that aud matches the app_id
  • verify that iss matches issuer as specified in the openid-configuration
  • verify that exp is in the future
  • verify that nonce matches the value that was included in the initial authorization request
  • verify the jwt-signature
    • LoginID's GET /oidc/keys may be used to retrieve the required public key
    • According to OpenID Connect core, the jwt-signature validation MAY be skipped if the id_token was received via https, directly from the issuer
  • Use sub of the id_token as user identifier within your application.

Use the id_token as id_token_hint on other platforms that accept a LoginID issued id_token as credential.

Userinfo Endpoint

This endpoint serves as the endpoint where the client application can retrieve claims and details about the user. However, some of the retrievable information is also included in the id_token claim.

curl --request POST '{{base_url}}/oidc/userinfo' \
--header 'Authorization: Bearer {{access_token}}'

curl --request GET '{{base_url}}/oidc/userinfo' \
--header 'Authorization: Bearer {{access_token}}'

Revocation Endpoint

This endpoint enables a client to request the revocation of an access token or refresh token, making it invalid. At LoginID, if either the access token or refresh token is revoked, the user will be unauthorized.

curl '{{base_url}}/oidc/revoke' \
--header 'Content-Type: application/json' \
--data '{
"token": "{{access_token}}"
}'

curl '{{base_url}}/oidc/revoke' \
--header 'Content-Type: application/json' \
--data '{
"token": "{{refresh_token}}"
}'

Introspective Endpoint

This endpoint allows a resource server to query LoginID to verify the validity and status of an access token.

curl '{{base_url}}/oidc/introspect' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token={{access_token}}'

More information

For specific questions or feedback, please feel free to contact support@loginid.io!