Backend Session Validation

This page focuses on backend session validation. Backend session validation is an integral part of secure session management, especially when dealing with APIs or more intricate use cases. This approach validates the session token at the server-side, thereby ensuring that the token has not been tampered with and is valid. It helps to verify that the incoming requests are indeed from authenticated users and not from potential attackers.

If you're looking to set up frontend validation, check out our Client Validation page. For an in-depth understanding of session validation in Descope, refer to our session management article.

Session Validation With Backend SDK

For validating the session, you need to integrate the Descope Backend SDK with your application server. To use the backend SDK, first install the SDK using your package manager. After installing use the code below to add the session validation.

Install SDK

NodeJSPythonGoJavaRuby
npm i --save @descope/node-sdk
pip3 install descope
go get github.com/descope/go-sdk
// Include the following in your `pom.xml` (Maven)
<dependency>
    <artifactId>java-sdk</artifactId>
    <groupId>com.descope</groupId>
    <version>sdk-version</version> // Check https://github.com/descope/descope-java/releases for the latest versions
</dependency>
gem install descope

Import and initialize SDK

NodeJSPythonGoJavaRuby
import DescopeClient from '@descope/node-sdk';
try{
    //  baseUrl="<URL>" // When initializing the Descope clientyou can also configure the baseUrl ex: https://auth.company.com  - this is useful when you utilize CNAME within your Descope project.
    const descopeClient = DescopeClient({ projectId: '__ProjectID__' });
} catch (error) {
    // handle the error
    console.log("failed to initialize: " + error)
}

// Note that you can handle async operation failures and capture specific errors to customize errors.
//     An example can be found here: https://github.com/descope/node-sdk?tab=readme-ov-file#error-handling
from descope import (
    REFRESH_SESSION_TOKEN_NAME,
    SESSION_TOKEN_NAME,
    AuthException,
    DeliveryMethod,
    DescopeClient,
    AssociatedTenant,
    RoleMapping,
    AttributeMapping,
    LoginOptions
)
try:
    # You can configure the baseURL by setting the env variable Ex: export DESCOPE_BASE_URI="https://auth.company.com  - this is useful when you utilize CNAME within your Descope project."
    descope_client = DescopeClient(project_id='__ProjectID__')
except Exception as error:
    # handle the error
    print ("failed to initialize. Error:")
    print (error)
import "github.com/descope/go-sdk/descope"
import "github.com/descope/go-sdk/descope/client"

// Utilizing the context package allows for the transmission of context capabilities like cancellation
//      signals during the function call. In cases where context is absent, the context.Background()
//      function serves as a viable alternative.
//      Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
import (
	"context"
)

// DescopeBaseURL // within the client.Config, you can also configure the baseUrl ex: https://auth.company.com  - this is useful when you utilize CNAME within your Descope project.

descopeClient, err := client.NewWithConfig(&client.Config{ProjectID:"__ProjectID__"})
if err != nil {
    // handle the error
    log.Println("failed to initialize: " + err.Error())
}
import com.descope.client.Config;
import com.descope.client.DescopeClient;

var descopeClient = new DescopeClient(Config.builder().projectId("__ProjectID__").build());
require 'descope'

@project_id = ENV['DESCOPE_PROJECT_ID']
@client = Descope::Client.new({ project_id: @project_id})

Validate Session

The session validation code below should be added to your application middleware (if you are using application middleware) for validating the session on all required routes. If you are not using a middleware, then you can add the validation code to all the routes which serve protected resource. Before validation, you need to extract the session token from the request authorization header.

Note that you can customize certain properties like refresh token timeout in Settings>Projects. Learn more here.

NodeJSPythonGoJavaruby
// Args:
//   sessionToken (str): The session token, which contains the signature that will be validated
//   Optional audience claim: If the jwt contains aud claim, same values have to be passed in the validate_session
const sessionToken="xxxx" // extract from request authorization header. The above sample code sends the the session token in authorization header.

try {
  const authInfo = await descopeSdk.validateSession(sessionToken);
  console.log("Successfully validated user session:");
  console.log(authInfo);
} catch (error) {
  console.log ("Could not validate user session " + error);
}
# Args:
#   session_token (str): The session token, which contains the signature that will be validated
#   audience (str|Iterable[str]|None): Optional, recipients that the JWT is intended for (must be equal to the 'aud' claim on the provided token)
session_token="xxxx" # extract from request authorization header. The above sample code sends the the session token in authorization header.

try:
  jwt_response = descope_client.validate_session(session_token=session_token)
  print ("Successfully validated user session:")
  print (jwt_response)
except Exception as error:
  print ("Could not validate user session. Error:")
  print (error)

-------------- or (use a Python Decorator) --------------

import descope_validate_auth

@app.route('/protected', methods=['GET'])
@descope_validate_auth(descope_client, permissions=["read"], roles=["user"])
def protected_route():
    return "Access to protected resource granted"
// Args:
//   ctx: context.Context - Application context for the transmission of context capabilities like
//        cancellation signals during the function call. In cases where context is absent, the context.Background()
//        function serves as a viable alternative.
//        Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
ctx := context.Background()
//    sessionToken (str): The session token, which contains the signature that will be validated
//    Optional audience claim: If the jwt contains aud claim, same values have to be passed in the validate_session

sessionToken := "xxxx" // extract from request authorization header. The above sample code sends the the session token in authorization header.

authorized, userToken, err := descopeClient.Auth.ValidateSessionWithToken(ctx, sessionToken)
if (err != nil){
  fmt.Println("Could not validate user session: ", err)
} else {
  fmt.Println("Successfully validated user session: ", userToken)
}
// Validate the session. Will return an error if expired
// Pass the aud claim with session token having the same value if there is one in the jwt
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
try {
    Token t = as.validateSessionWithToken(sessionToken);
} catch (DescopeException de) {
    // Handle the unauthorized error
}

// If ValidateSessionWithRequest raises an exception, you will need to refresh the session using
try {
    Token t = as.refreshSessionWithToken(refreshToken);
} catch (DescopeException de) {
    // Handle the unauthorized error
}

// Alternatively, you could combine the two and
// have the session validated and automatically refreshed when expired
try {
    Token t = as.validateAndRefreshSessionWithTokens(sessionToken, refreshToken);
} catch (DescopeException de) {
    // unauthorized error
}
# Validate the session. Will raise if expired
# Optional audience claim: If the jwt contains aud claim, same values have to be passed in the validate_session
begin
    jwt_response = descope_client.validate_session('session_token')
rescue AuthException => e
    # Session expired
end

# If validate_session raises an exception, you will need to refresh the session using
jwt_response = descope_client.refresh_session('refresh_token')

# Alternatively, you could combine the two and
# have the session validated and automatically refreshed when expired
jwt_response = descope_client.validate_and_refresh_session('session_token', 'refresh_token')

Logout Current Session using Backend SDK

You can log out a user from an active session by providing their refreshToken for that session. After calling this function, you must invalidate or remove any cookies you have created.

NodeJSPythonGoJavaRuby
// Args:
//    refreshToken: refresh token from the successful sign-in of the user
const refreshToken = "xxxx"

const resp = await descopeClient.logout(refreshToken);
if (!resp.ok) {
  console.log("Failed to log user out of current session.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully logged user out of current session.")
  console.log(resp.data)
}
# Args:
#    refresh_token: refresh token from the successful sign-in of the user

try:
  resp = descope_client.logout(refresh_token)
  print ("Successfully logged user out of current session.")
except AuthException as error:
  print ("Failed to log user out of current session.")
  print ("Status Code: " + str(error.status_code))
  print ("Error: " + str(error.error_message))

-------------- or (use a Python Decorator) --------------

from descope.flask import descope_logout

@app.route('/logout', methods=['GET'])
@descope_logout(descope_client)
def logout():
    return "Logged out successfully"
// Args:
//  ctx: context.Context - Application context for the transmission of context capabilities like
//        cancellation signals during the function call. In cases where context is absent, the context.Background()
//        function serves as a viable alternative.
//        Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
ctx := context.Background()
//  r: HttpRequest for the action. Refresh token will be taken from the request header or cookies automatically
//  w (optional): If provided, the optional `w http.ResponseWriter` will empty out the session cookies automatically.

err := descopeClient.logout(ctx, request, w)
if (err != nil){
  fmt.Println("Failed to log user out of current session: ", err)
} else {
  fmt.Println("Successfully logged user out of current session.")
}
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
try {
    as.logout(refreshToken);
} catch (DescopeException de) {
    // Handle the error
}
descope_client.sign_out('refresh_token')

Logout All Sessions using Backend SDK

It is possible to sign the user out of all the devices they are currently signed-in with. Calling the logout all function will invalidate all user's refresh tokens. After calling this function, you must invalidate or remove any cookies you have created.

NodeJSPythonGoJavaruby
// Args:
//    refreshToken: refresh token from the successful sign-in of the user
const refreshToken = "xxxx"

const resp = await descopeClient.logoutAll(refreshToken);
if (!resp.ok) {
  console.log("Failed to log user out of all current sessions.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully logged user out of all current sessions.")
  console.log(resp.data)
}
# Args:
#    refresh_token: refresh token from the successful sign-in of the user

try:
  resp = descope_client.logout_all(refresh_token)
  print ("Successfully logged user out of all current sessions.")
except AuthException as error:
  print ("Failed to log user out of all current sessions.")
  print ("Status Code: " + str(error.status_code))
  print ("Error: " + str(error.error_message))
// Args:
//  ctx: context.Context - Application context for the transmission of context capabilities like
//        cancellation signals during the function call. In cases where context is absent, the context.Background()
//        function serves as a viable alternative.
//        Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
ctx := context.Background()
//  r: HttpRequest for the action. Refresh token will be taken from the request header or cookies automatically
//  w (optional): If provided, the optional `w http.ResponseWriter` will empty out the session cookies automatically.

err := descopeClient.logoutAll(ctx, request, w)
if (err != nil){
  fmt.Println("Failed to log user out of all current sessions: ", err)
} else {
  fmt.Println("Successfully logged user out of all current sessions.")
}
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
try {
    as.logoutAll(refreshToken);
} catch (DescopeException de) {
    // Handle the error
}
descope_client.sign_out('refresh_token')

# It is also possible to sign the user out of all the devices they are currently signed-in with. Calling logout_all will invalidate all user's refresh tokens. After calling this function, you must invalidate or remove any cookies you have created.
descope_client.sign_out_all('refresh_token')

Note: To learn more about how refresh token storage works, check out our Session Management page.

Validating roles and permissions

If your applications does not need different roles for the logged in users, then skip this section.

If you are using authorization feature in Descope, then you can use the Descope backend sdk to validate roles and permissions. The roles and permissions for the user are returned in the session token. You can either use your own JWT validation library and access the tenant information, roles and permissions for the authenticated user or use the SDK calls shown below.

If you are using tenant capabilities in Descope, then use the tenant validation calls for validating permissions and roles.

Roles

The "Roles" section pertains to the process of validating user roles within an application. These roles are typically defined and allocated by an administrator and are used to manage user access to certain resources or actions within an application. The validateRoles function is used to confirm whether a user has a valid role, based on the role names provided as arguments. The roles to be validated are provided as a string array. This function returns a Boolean value indicating whether the user's roles are valid (true) or invalid (false).

NodeJSPythonGoJavaRuby
// validateRoles function
// Args:
//   authenticationInfo : authentication information with claims returned from the validateSession call
//   roles: string array containing names of roles to be validated
const roles=[]

// Return value : Boolean (true or false)
try {
    const isRoleValid =  descopeClient.validateRoles(authInfo, roles);
    if (isRoleValid) {
        console.log("These roles are valid for user")
    } else {
        console.log("These roles are invalid for user")
    }
} catch (error) {
    console.log ("Could not confirm if roles are valid - error prior to confirmation. " + error);
}
# validate_roles function
# Args:
#   jwt_response: The response that you get from the validate_session call.
#   roles: list of strings - each string represents a role name that is validated.
roles=[]
# Return value: Boolean (True or False)
try:
    isRoleValid = descope_client.validate_roles(jwt_response, roles)
    if isRoleValid == True:
        print ("These roles are valid for user")
    else:
        print ("These roles are invalid for user")
except Exception as error:
    print ("Could not confirm if roles are valid - error prior to confirmation. Error:")
    print (error)
// ValidateRoles validates the roles that are given as an array using the userToken returned from ValidateSession function
// Args:
// ctx: context.Context - Application context for the transmission of context capabilities like
//        cancellation signals during the function call. In cases where context is absent, the context.Background()
//        function serves as a viable alternative.
//        Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
ctx := context.Background()
//  userToken: token returned from ValidateSession call.
//  roles: list of roles to validate
roles:= []

// Return value:
// bool: true or false depending of the roles match or not
//   err - has the error message (can be populated even if session is valid)
// If the session is not valid, the function returns an error.
if isValidRoles, err := descopeClient.Auth.ValidateRoles(ctx, userToken, roles); !isValidRoles {
    // roles are invalid for the user
    //WIP log.Println("These roles are invalid for the user")
}
// You can validate specific permissions
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
// Or validate roles directly
try {
    if (!as.validateRoles(sessionToken, Arrays.asList("Role to validate"))) {
        // Deny access
    }
} catch (DescopeException de) {
    // Handle the error
}
# Or validate roles directly
valid_roles = descope_client.validate_roles(
    jwt_response: 'resp', roles: ['Role to validate']
)

unless valid_roles
    # Deny access
end

Permissions

The "Permissions" section discusses the mechanism of checking user permissions. Permissions, similar to roles, regulate what actions a user can perform within a system, but they are often more granular and specific. The validatePermissions function is used to validate if a user has specific permissions based on the permission names provided as arguments. Like with roles, the permissions to be validated are supplied as a string array. The function then returns a Boolean value, where 'true' indicates the user has the validated permissions, and 'false' suggests the opposite.

NodeJSPythonGoJavaRuby
// validatePermissions function
// Args:
//   authenticationInfo : authentication information with claims returned from the validateSession call
//   roles: string array containing names of roles to be validated
const permissions=[]

// Return value : Boolean (true or false)
try {
    const isPermissionValid =  descopeClient.validatePermissions(authInfo, permissions);
    if (isPermissionValid) {
        console.log("These permissions are valid for user")
    } else {
        console.log("These permissions are invalid for user")
    }
} catch (error) {
    console.log ("Could not confirm if permissions are valid - error prior to confirmation. " + error);
}
# validate_permissions function
# Args:
#   jwt_response: The response that you get from the validate_session call.
#   permissions: list of strings - each string represents a role name that is validated.
permissions=[]
# Return value: Boolean (True or False)
try:
    isPermissionValid = descope_client.validate_permissions(jwt_response, permissions)
    if isPermissionValid == True:
        print ("These permissions are valid for user")
    else:
        print ("These permissions are invalid for user")
except Exception as error:
    print ("Could not confirm if permissions are valid - error prior to confirmation. Error:")
    print (error)
// ValidatePermissions validates the roles that are given as an array using the userToken returned from ValidateSession function
// Args:
// ctx: context.Context - Application context for the transmission of context capabilities like
//        cancellation signals during the function call. In cases where context is absent, the context.Background()
//        function serves as a viable alternative.
//        Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
ctx := context.Background()
//  userToken: token returned from ValidateSession call.
//  permissions: list of permissions to validate
permissions:=[]

// Return value:
// bool: true or false depending of the permissions match or not
//   err - has the error message (can be populated even if session is valid)
// If the session is not valid, the function returns an error.
if isValidPermissions, err := descopeClient.Auth.ValidatePermissions(ctx, userToken, permissions); !isValidPermissions {
    // permissions are invalid for the user
    //WIP log.Println("These permissions are invalid for the user")
}
// You can validate specific permissions
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
try {
    if (!as.validatePermissions(sessionToken, Arrays.asList("Permission to validate"))) {
        // Deny access
    }
} catch (DescopeException de) {
    // Handle the error
}
# You can validate specific permissions
valid_permissions = descope_client.validate_permissions(
    jwt_response: 'resp', permissions: ['Permission to validate']
)
unless valid_permissions
    # Deny access
end

Roles with Tenant Function

The "Roles with Tenant Function" section deals with the validation of user roles within the context of a specific tenant. In multi-tenant environments, where a single instance of software serves multiple users or groups of users (tenants), users might have different roles depending on the tenant they are interacting with. The validateTenantRoles function is used to check if a user's role is valid for a specific tenant. This function takes in the tenant's ID and the roles to be validated, and it returns a Boolean value indicating the validity of the roles for the specified tenant.

NodeJSPythonGoJavaRuby
// validateRoles with tenant function
// Args:
//   authenticationInfo : authentication information with claims returned from the validateSession call
//   tenantId : tenant id for the tenant the user is logging in
const tenantId="xxx"

//   roles: string array containing names of roles to be validated
const roles=[]

// Return value : Boolean (true or false)
try {
    const isRoleValid =  descopeClient.validateTenantRoles(authInfo, tenantId, roles);
    if (isRoleValid) {
        console.log("These roles are valid for tenant " + tenantId)
    } else {
        console.log("These roles are invalid for tenant " + tenantId)
    }
} catch (error) {
    console.log ("Could not confirm if roles are valid - error prior to confirmation. " + error);
}
# validate_tenant_roles function
# Args:
#   jwt_response: The response that you get from the validate_session call.
#   tenant_id: tenant id for the tenant the user is logging in
tenant_id="xxx"

#   roles: list of strings - each string represents a role name that is validated.
roles=[]

# Return value: Boolean (True or False)
try:
    isRoleValid = descope_client.validate_tenant_roles(jwt_response, tenant_id, roles)
    if isRoleValid == True:
        print ("These roles are valid for tenant " + tenant_id)
    else:
        print ("These roles are invalid for tenant " + tenant_id)
except Exception as error:
    print ("Could not confirm if roles are valid - error prior to confirmation. Error:")
    print (error)
// ValidateTenantRoles validates the roles that are given as an array using the userToken returned from ValidateSession function
// Args:
// ctx: context.Context - Application context for the transmission of context capabilities like
//        cancellation signals during the function call. In cases where context is absent, the context.Background()
//        function serves as a viable alternative.
//        Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
ctx := context.Background()
//  userToken: token returned from ValidateSession call.
//  tenantID: tenant id for the tenant the user is logging in
tenantID:="xxx"

//  roles: list of roles to validate
roles:= []

// Return value:
// bool: true or false depending of the roles match or not
//   err - has the error message (can be populated even if session is valid)
// If the session is not valid, the function returns an error.
if isValidRoles, err := descopeClient.Auth.ValidateTenantRoles(ctx, userToken, tenantID, roles); !isValidRoles {
    // roles are invalid for the tenant
    //WIP log.Println("These roles are invalid for tenant " + tenantID)
}
// You can validate specific permissions
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();

// Or validate roles directly
try {
    if (!as.validateRoles(sessionToken, "my-tenant-ID", Arrays.asList("Role to validate"))) {
        // Deny access
    }
} catch (DescopeException de) {
    // Handle the error
}
# Or validate roles directly
valid_roles = descope_client.validate_tenant_roles(
    jwt_response: 'resp', tenant: 'my-tenant-ID', roles: ['Role to validate']
)

unless valid_roles
    # Deny access
end

Permissions with Tenant Function

The "Permissions with Tenant Function" section revolves around the process of verifying user permissions within the context of a specific tenant. Similar to the role validation, permission validation in multi-tenant environments can be tenant-specific. The validateTenantPermissions function is used to determine whether a user's permissions are valid for a particular tenant. This function takes in the tenant's ID and the permissions to be validated, returning a Boolean value that represents the validity of these permissions for the specified tenant.

NodeJSPythonGoJavaRuby
// validatePermissions with tenant function
// Args:
//   authenticationInfo : authentication information with claims returned from the validateSession call
//   tenantId : tenant id for the tenant the user is logging in
const tenantId="xxx"

//   roles: string array containing names of roles to be validated
const permissions=[]

// Return value : Boolean (true or false)
try {
    const isPermissionValid =  descopeClient.validateTenantPermissions(authInfo, tenantId, permissions);
    if (isPermissionValid) {
        console.log("These permissions are valid for tenant " + tenantId)
    } else {
        console.log("These permissions are invalid for tenant " + tenantId)
    }
} catch (error) {
    console.log ("Could not confirm if permissions are valid - error prior to confirmation. " + error);
}
# validate_tenant_permissions function
# Args:
#   jwt_response: The response that you get from the validate_session call.
#   tenant_id: tenant id for the tenant the user is logging in
tenant_id="xxx"

#   permissions: list of strings - each string represents a role name that is validated.
permissions=[]

# Return value: Boolean (True or False)
try:
    isPermissionValid = descope_client.validate_tenant_permissions(jwt_response, tenant_id, permissions)
    if isPermissionValid == True:
        print ("These permissions are valid for tenant " + tenant_id)
    else:
        print ("These permissions are invalid for tenant " + tenant_id)
except Exception as error:
    print ("Could not confirm if permissions are valid - error prior to confirmation. Error:")
    print (error)
// ValidateTenantPermissions validates the roles that are given as an array using the userToken returned from ValidateSession function
// Args:
// ctx: context.Context - Application context for the transmission of context capabilities like
//        cancellation signals during the function call. In cases where context is absent, the context.Background()
//        function serves as a viable alternative.
//        Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
ctx := context.Background()
//  userToken: token returned from ValidateSession call.
//  tenantID: tenant id for the tenant the user is logging in
tenantID:="xxx"

//  permissions: list of permissions to validate
permissions:=[]

// Return value:
// bool: true or false depending of the permissions match or not
//   err - has the error message (can be populated even if session is valid)
// If the session is not valid, the function returns an error.
if isValidPermissions, err := descopeClient.Auth.ValidateTenantPermissions(ctx, userToken, tenantID, permissions); !isValidPermissions {
    // permissions are invalid for the tenant
    //WIP log.Println("These permissions are invalid for tenant " + tenantID)
}
// You can validate specific permissions
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
try {
    if (!as.validatePermissions(sessionToken, "my-tenant-ID", Arrays.asList("Permission to validate"))) {
        // Deny access
    }
} catch (DescopeException de) {
    // Handle the error
}
# You can validate specific permissions
valid_permissions = descope_client.validate_tenant_permissions(
    jwt_response: 'resp', tenant: 'my-tenant-ID', permissions: ['Permission to validate']
)

unless valid_permissions
    # Deny access
end

Retrieving Matching Roles and Permissions

To get matching roles or permissions of a user, you can use the Descope backend sdk, as shown below.

The roles and permissions for the user are returned in the session token. So alternatively, you can even use your own JWT validation library.

If you are using tenant capabilities in Descope, then use the tenant matching calls for getting matching permissions and roles.

Roles

Roles are extracted from JWT claims based on specified criteria. Below is an example of how to retrieve roles using different programming languages:

 /**
 * Retrieves the roles from JWT top level claims that match the specified roles list
 * @param authInfo JWT parsed info containing the roles
 * @param roles List of roles to match against the JWT claims
 * @returns An array of roles that are both in the JWT claims and the specified list. Returns an empty array if no matches are found
 */

NodeJSPythonGoJava
try {
    const matchedRoles = descopeClient.getMatchedRoles(authInfo, [
    'Role to validate',
    'Another role to validate',
    ]);
   
} catch (error) {
    console.log ("Could not confirm if roles are valid - error prior to confirmation. " + error);
}
try:
    matched_roles = descope_client.get_matched_roles(
		jwt_response, ["role-name1", "role-name2"]
    )
except Exception as error:
    print ("Could not confirm if roles are valid - error prior to confirmation. Error:")
    print (error)
matchedRoles := descopeClient.Auth.GetMatchedRoles(sessionToken, []string{"role-name1", "role-name2"})
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
try {
    List<String> matchedRoles = as.getMatchedRoles(sessionToken, Arrays.asList("Role1", "Role2"));
} catch (DescopeException de) {
    // Handle the error
}

Permissions

Permissions are similarly retrieved from JWT claims and checked against a specified list. Example implementations across different languages are provided below:

/**
 * Retrieves the permissions from JWT top level claims that match the specified permissions list
 * @param authInfo JWT parsed info containing the permissions
 * @param permissions List of permissions to match against the JWT claims
 * @returns An array of permissions that are both in the JWT claims and the specified list. Returns an empty array if no matches are found
 */

NodeJSPythonGoJava
try {
    const matchedPermissions = descopeClient.getMatchedPermissions(authInfo, [
    'Permission to validate',
    'Another permission to validate',
    ]);
    if (isPermissionValid) {
        console.log("These permissions are valid for user")
    } else {
        console.log("These permissions are invalid for user")
    }
} catch (error) {
    console.log ("Could not confirm if permissions are valid - error prior to confirmation. " + error);
}
try:
    matched_permissions = descope_client.get_matched_permissions(
		jwt_response, ["permission-name1", "permission-name2"]
)
except Exception as error:
    print ("Could not confirm if permissions are valid - error prior to confirmation. Error:")
    print (error)
matchedPermissions := descopeClient.Auth.GetMatchedPermissions(sessionToken, []string{"permission-name1", "permission-name2"})
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
try {
    List<String> matchedPermissions = as.getMatchedPermissions(sessionToken, Arrays.asList("Permission1", "Permission2"));
} catch (DescopeException de) {
    // Handle the error
}

Roles with Tenant Function

When using tenant-specific functionalities, roles can be matched as follows:

/**
* Retrieves the roles from JWT tenant claims that match the specified roles list
* @param authInfo JWT parsed info containing the roles
* @param tenant tenant to match the roles for
* @param roles List of roles to match against the JWT claims
* @returns An array of roles that are both in the JWT claims and the specified list. Returns an empty array if no matches are found
*/

NodeJSPythonGoJava
try {
    const matchedTenantRoles = descopeClient.getMatchedTenantRoles(authInfo, 'my-tenant-ID', [
    'Role to validate',
    'Another role to validate',
    ]);
} catch (error) {
    console.log ("Could not confirm if roles are valid - error prior to confirmation. " + error);
}
try:
   matched_tenant_roles = descope_client.get_matched_tenant_roles(
		jwt_response, "my-tenant-ID", ["role-name1", "role-name2"]
)
except Exception as error:
    print ("Could not confirm if roles are valid - error prior to confirmation. Error:")
    print (error)
matchedTenantRoles := descopeClient.Auth.GetTenantRoles(sessionToken, "my-tenant-ID", []string{"role-name1", "role-name2"})
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
try {
  List<String> matchedRoles = as.getMatchedRoles(sessionToken, "my-tenant-ID", Arrays.asList("Role1", "Role2"));
} catch (DescopeException de) {
    // Handle the error
}

Permissions with Tenant Function

Matching permissions within a specific tenant context is handled similarly:

/**
 * Retrieves the permissions from JWT top level claims that match the specified permissions list
 * @param authInfo JWT parsed info containing the permissions
 * @param permissions List of permissions to match against the JWT claims
 * @returns An array of permissions that are both in the JWT claims and the specified list. Returns an empty array if no matches are found
 */

NodeJSPythonGoJava
try {
   const matchedTenantPermissions = descopeClient.getMatchedTenantPermissions(
    authInfo,
    'my-tenant-ID',
    ['Permission to validate', 'Another permission to validate'],
    );
} catch (error) {
    console.log ("Could not confirm if permissions are valid - error prior to confirmation. " + error);
}
try:
    matched_tenant_permissions = descope_client.get_matched_tenant_permissions(
        jwt_response, "my-tenant-ID", ["permission-name1", "permission-name2"]
    )
except Exception as error:
    print ("Could not confirm if permissions are valid - error prior to confirmation. Error:")
    print (error)
matchedTenantPermissions := descopeClient.Auth.GetTenantPermissions(sessionToken, "my-tenant-ID", []string{"permission-name1", "permission-name2"})
AuthenticationService as = descopeClient.getAuthenticationServices().getAuthenticationService();
try {
   List<String> matchedPermissions = as.getMatchedPermissions(sessionToken, "my-tenant-ID", Arrays.asList("Permission1", "Permission2"));
} catch (DescopeException de) {
    // Handle the error
}