Utilizing OIDC Endpoints with Descope

If you have deployed your own OIDC client, Descope can become your IdP. OpenID Connect (OIDC) operates over OAuth 2.0, using endpoints for different parts of the authentication and authorization processes. Understanding these endpoints and how to leverage them is key to integrating OIDC authentication.

Available OIDC Endpoints

Descope's OIDC offers the following primary endpoints:

  • Authorization Endpoint: This endpoint initiates the authorization flow leading to the return of an id_token and an access_token. The endpoint for this service is: https://api.descope.com/oauth2/v1/authorize
  • Token Endpoint: Once you have an authorization code from the Authorization Endpoint, you can request tokens from this endpoint. Access it at: https://api.descope.com/oauth2/v1/token
  • UserInfo Endpoint: After you've obtained an access_token, you can retrieve detailed information about the authenticated user from this endpoint. Find it at: https://api.descope.com/oauth2/v1/userinfo
  • JWKS URI: Endpoint containing the JSON Web Key Set, which is a set of keys containing the public key used to verify any JSON Web Token (JWT) issued by the authorization server. Access it at: https://api.descope.com/__ProjectID__/.well-known/jwks.json
  • End Session Endpoint: Used to end the user's session. The endpoint for this service is: https://api.descope.com/oauth2/v1/logout
  • Revocation Endpoint: This is where you can revoke tokens. Visit: https://api.descope.com/oauth2/v1/revoke

Configuring Descope with OIDC using Endpoints

OpenID Connect (OIDC) allows you to authenticate users via an external Identity Provider. Below, we'll guide you on how to use the provided OIDC endpoints to integrate Descope and OIDC.

Descope supports the following grant types with OIDC:

Using PKCE in Your Endpoints

PKCE (Proof Key for Code Exchange) is an extension to OAuth 2.0 for public clients (e.g., mobile applications), preventing interception attacks during the OAuth authorization code flow.

In the PKCE flow:

  1. Code Verifier Generation: The client creates a large random string called the "code verifier".
  2. Code Challenge Calculation: The client then hashes the code verifier to create the "code challenge", typically using SHA-256.
  3. Authorization Request: The client starts the authorization code flow by sending the code challenge and its method (S256 for SHA-256) to the authorization server when accessing the /authorize endpoint.
  4. Token Exchange: Once the client receives the authorization code, it sends a request to the token endpoint, including the code verifier. The server will hash the verifier and ensure it matches the challenge sent earlier.

Guide to Using OIDC Endpoints

Before using any of the endpoints, you will need to generate a Code Verifier and Code Challenge, which you can do here. You can also do this yourself following the code below:

function generateCodeVerifier() {
  let result = '';
  const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
  const charactersLength = characters.length;

  for (let i = 0; i < 128; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));

  return result;

function generateCodeChallenge(verifier) {
  return crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))
    .then(arrayBuffer => {
      const base64Url = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)))
        .replace(/=/g, '')
        .replace(/\+/g, '-')
        .replace(/\//g, '_');
      return base64Url;

const codeVerifier = generateCodeVerifier();
const state = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);

After generating the Code Verifier and Challenge, you should have something like this:

Code Verifier: N7QLWqAp2aYxDGRtqbXjbfusYLE97XAui-nnW9hOofI
Code Challenge: KM6LN2hMVS5xeS3CHhoNuHtqtWD0-EIbkIq8u_KZl3U
State: KM6LN2fFDS32duHtqtWD0-EIbkIq8u_KfG3U

Then you'll need to actually begin the OIDC flow, to generate all of the necessary tokens you'll need (e.g. id_token, access_token).

  1. Make Authorization Request:
const authUrl = `https://api.descope.com/oauth2/v1/authorize?response_type=code&client_id=__ProjectID__&redirect_uri=YOUR_REDIRECT_URI&scope=openid&code_challenge=${codeChallenge}&code_challenge_method=S256&state={state}`;

// Redirect the user to the authorization URL
window.location.href = authUrl;

If you want to have your own hosted Descope Flow, you can use this repository as a template, host it (using Vercel, localhost, etc.), and change the Flow Hosting URL in the Descope Console.

Once the user has authorized the application, they will be redirected to the redirect_uri you specified, with an authorization code attached as a query parameter.

  1. Exchange Authorization Code (w/ Code Verifier) for Tokens: Send a POST request to the Token Endpoint with the authorization code to exchange it for tokens.
const tokenUrl = 'https://api.descope.com/oauth2/v1/token';

const tokenData = {
  grant_type: 'authorization_code',
  redirect_uri: 'YOUR_REDIRECT_URI',
  client_id: '__ProjectID__',
  code_verifier: codeVerifier,

// Use fetch or any HTTP client to POST the data to the tokenUrl
  1. Fetching User Information: With the acquired access_token, you can send a GET request to the UserInfo Endpoint to get detailed user information.
const userInfoUrl = 'https://api.descope.com/oauth2/v1/userinfo';

fetch(userInfoUrl, {
  method: 'GET',
  headers: {
    'Authorization': `Bearer YOUR_ACCESS_TOKEN`
.then(response => response.json())
.then(data => {
  1. Logging out the User: To log the user out, redirect them to the End Session Endpoint. You will need to have access to the id_token created in Step 2, to use this endpoint.
const logoutUrl = 'https://api.descope.com/oauth2/v1/logout?id_token_hint=YOUR_ID_TOKEN&post_logout_redirect_uri=YOUR_POST_LOGOUT_REDIRECT_URI';

window.location.href = logoutUrl;
  1. Token Revocation: If for any reason, you need to invalidate a token (for instance, the user changed their password), send a POST request to the Revocation Endpoint with the token you wish to revoke.
const revokeUrl = 'https://api.descope.com/oauth2/v1/revoke';

const revokeData = {
  client_id: '__ProjectID__',

fetch(revokeUrl, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  body: new URLSearchParams(revokeData),
.then(response => {
  if (response.status === 200) {
    console.log("Token revoked successfully");
  } else {
    console.error("Failed to revoke the token");
  1. Verify JWTs: To verify JWTs, fetch the public key from the JWKS URI and use it to verify the signature of any JWTs you receive.

Client Credentials Flow

With the Client Credentials grant type, applications request access tokens directly without any user intervention. It authenticates the application using its client ID and secret. This is typically used in Machine-to-Machine applications.

You must use Client Secret Basic when handling client secrets in the HTTP request for the access token.You will need to encode the Client ID with a Descope Access Key. Then in the Authorization header, you'll need to take that string and append it after the word Basic.

The Client ID will be an encoded string tied to the specific Access Key that's generated. The Client Secret will be actual Access Key secret generated in the Console.

Client ID under Access Keys
Once you've put the <Client ID>:<Descope Access Key> (UDJQRDhI*********DBaQ2kwdzp:P2PD8H2*******00ZCi0w) together, you'll need to base64 encode the string to make something like this: UDJWSGFwODVOY1JJR***************jJRZERzTGM3TTZjUmwyNTB5SXBHeVc=.

You can see this in the example given below:

curl -X POST \
https://api.descope.com/oauth2/v1/token \
-H 'Authorization: Basic UDJWSGFwODVOY1JJR***************jJRZERzTGM3TTZjUmwyNTB5SXBHeVc=' \
-d 'grant_type=client_credentials&scope=openid%20profile%20email%20phone'   

After making this POST request, you should be able to retrieve the necessary access token for your M2M connection.

If you wish to add custom claims to your JWT created with this Client Credentials flow, utilize our Access Key JWT Templates under your Project Settings.

Silent Authentication

Silent authentication is a process that allows applications to authenticate users without interactive login prompts, thereby providing a seamless user experience.

Silent auth leverages the user's existing login session to grant or renew access tokens without requiring the user to actively re-enter their credentials. It's typically implemented using an invisible iframe or a background HTTP request in web applications.

Use Cases for Silent Authentication

  • Single Page Applications (SPAs) - SPAs can refresh tokens without reloading the entire page or disrupting the user experience.
  • Maintaining User Sessions - Automatically renew user sessions in the background to avoid session timeouts.
  • Microservices Architecture - Seamless authentication across different microservices without prompting the user repeatedly.

How to Use Silent Authentication

If you're using the /authorize endpoint listed above, then all you'll need to do to attempt a silent auth request is include prompt=none as a parameter like this:

If you're looking for how you can alter the prompt parameter when signing in with other OAuth providers in your flow, you can visit this documentation.

Experimental Playground

To have a better understanding and practical experience with these endpoints, you can experiment with the OAuth Tools Collection. This platform provides a visual and interactive way to work with all the available OIDC endpoints. It's especially useful to see how the access_token and id_token are utilized across different requests.