Getting Started with the Identity Domains REST API

The identity domains REST API securely manage resources, including identities and configuration data. Support for OpenID Connect allows integration with compliant applications and identity domains. The OAuth2 service provides an API infrastructure for authorization that supports a range of token grant types that enable you to securely connect clients to services.

The identity domains REST API supports SCIM 2.0 compliant endpoints with standard SCIM 2.0 core schemas and Oracle schema extensions to:

  • Manage users, groups, and apps.

  • Perform identity functions, including password generation and reset.

  • Perform administrative tasks including bulk operations and job scheduling.

  • Configure settings for an identity domain including multifactor authentication, branding, and notification templates.

This guide contains the following sections:

  • Endpoints Deprecation Notices: Learn about endpoints deprecation notices for identity domains.
  • Quick Start: Quickly get started with the identity domains REST API by completing prerequisites, installing curl, and setting up authorization to manage your identity domain resources such as users, groups, and applications.
  • API Rate Limits: Understand the rate limiting for APIs for different identity domain types.
  • Structuring Resource Requests: Learn the guidelines for building send requests in an identity domain.
  • Using cURL: Learn how to use cURL to access the REST APIs.
  • Managing Authorization Using the API: Learn how to use an OAuth client to access identity domains REST API. The identity domains REST API isn't accessible using only an identity domain username and password. To access the identity domains REST API, you need an OAuth2 access token or an API key to use for authorization.
  • API Use Cases: Step through typical use cases using the identity domain REST APIs.

The following resources aren't in this guide but are also available to you.

When using the identity domains user interface:

When using the API or CLI:

  • To manage identity domains (for example, creating or deleting a domain), see IAM API.
  • To manage resources within an identity domain, for example, users, dynamic resource groups, groups, and identity providers, see Identity Domains CLI.

Endpoints Deprecation Notices

Read the endpoint deprecation notices for identity domains in IAM.

To review details about Oracle Cloud Infrastructure breaking changes, such as deprecated features, deprecated APIs, and service behavior changes, see IAM Service Change Announcements.

Quick Start

Quickly get started with the identity domains REST API by completing prerequisites, installing curl, and setting up authorization to manage your identity domain resources such as users, groups, and applications.

Prerequisites

  1. Buy an Oracle Cloud Subscription: See Buy an Oracle Cloud Subscription.
  2. Activate your order: Set up your account or activate your order. See Activate Your Order from Your Welcome Email in Buy an Oracle Cloud Subscription.
  3. Obtain the appropriate account credentials and authorization to access identity domain APIs from your identity domain administrator:
    • To sign in to your identity domain. See your identity domain administrator to obtain your username, password, and identity domain name.

    • To use the API without a user account. Administrators can use the identity domains API without a user account in the identity domain. To use the identity domains API without a user account, request a client ID and a client secret from the identity domain administrator.

Step 1: Sign In to Your Identity Domain

After you activate your account, you're sent sign-in credentials and a link to the home page of your identity domain. Select the link in the email, and then enter the provided sign-in credentials. Your identity domain home page appears. See Sign In to the Console.

Step 2: Install cURL

The examples within this document use the cURL command line tool to demonstrate how to access the identity domains REST API.

To connect securely to the server, you must install a version of cURL that supports SSL and provide an SSL certificate authority (CA) certificate file or bundle to authenticate against the Verisign CA certificate. For more information about:

The following procedure demonstrates how to install cURL on a Windows 64-bit system.
  1. In a browser, navigate to the cURL home page at http://curl.haxx.se/download.html.

  2. On the cURL Releases and Downloads page, find the SSL-enabled version that corresponds to your OS, and then select the link to download the ZIP file.

  3. Install the software.

  4. Navigate to the cURL CA Certs page at http://curl.haxx.se/docs/caextract.html, and then download the ca-bundle.crt SSL certificate authority (CA) certificate bundle into the folder where you installed cURL.

  5. Set the cURL environment variable:
    1. Open a command window.

    2. Navigate to the directory where you installed cURL.

    3. Set the cURL environment variable (CURL_CA_BUNDLE) to the SSLCA certificate bundle location. For example: C:\curl> set CURL_CA_BUNDLE=ca-bundle.crt.

Step 3: Understand the Resource URL Format

You access the identity domains REST API using a URL, which includes the REST endpoint, the resource that you want to access, and any query parameters that you want to include in a request.

The basic endpoint for the identity domains REST API is:

https://<domainURL>/admin/v1/

See Send Requests for specific details on building these URLs.

Step 4: Set Up Authorization

You need to generate the access token that you can then use to authorize requests that you send to the identity domains REST API. See Managing Authorization Using the API.

You're now ready to send requests to an identity domain using cURL.

Step 5: Manage Your Identity Domain Resources

Begin using the REST API to manage overall identity domain configurations and identities and resources.

API Rate Limits

Understand the rate limiting for APIs for different identity domain types.

Oracle APIs are subject to rate limiting to protect the API service usage for all Oracle's customers. If you reach the API limit for the identity domain type, then IAM returns a 429 error code.

Rate Limits for all Identity Domain Types

API Group Per Free Oracle Apps Oracle Apps Premium Premium External User
AuthN second 10 50 80 95 90
AuthN minute 150 1000 2100 4500 3100
BasicAuthN second 10 100 160 95 90
BasicAuthN minute 150 3000 4000 4500 3100
Token Mgmt second 10 40 50 65 60
Token Mgmt minute 150 1000 1700 3400 2300
Others second 20 50 55 90 80
Others minute 150 1500 1750 5000 4000
Bulk second 5 5 5 5 5
Bulk minute 200 200 200 200 200
Import and export day 4 8 10 10 10
Note

The maximum number of Identity Propagation Trust objects that can be created is restricted to 30. Contact support if the limit needs to be increased. For more information on object limits, see IAM Identity Domain Object Limits.

APIs in API Groups

API limits apply to the total of all APIs within a group.

Authentication
  • /sso/v1/user/login
  • /sso/v1/user/secure/login
  • /sso/v1/user/logout
  • /sso/v1/sdk/authenticate
  • /sso/v1/sdk/session
  • /sso/v1/sdk/idp
  • /sso/v1/sdk/secure/session
  • /mfa/v1/requests
  • /mfa/v1/users/{userguid}/factors
  • /oauth2/v1/authorize
  • /oauth2/v1/userlogout
  • /oauth2/v1/consent
  • /fed/v1/user/request/login
  • /fed/v1/sp/sso
  • /fed/v1/idp/sso
  • /fed/v1/idp/usernametoken
  • /fed/v1/metadata
  • /fed/v1/mex
  • /fed/v1/sp/slo
  • /fed/v1/sp/initiatesso
  • /fed/v1/sp/ssomtls
  • /fed/v1/idp/slo
  • /fed/v1/idp/initiatesso
  • /fed/v1/idp/wsfed
  • /fed/v1/idp/wsfedsignoutreturn
  • /fed/v1/user/response/login
  • /fed/v1/user/request/logout
  • /fed/v1/user/response/logout
  • /fed/v1/user/testspstart
  • /fed/v1/user/testspresult
  • /admin/v1/SigningCert/jwk
  • /admin/v1/Asserter
  • /admin/v1/MyAuthenticationFactorInitiator
  • /admin/v1/MyAuthenticationFactorEnroller
  • /admin/v1/MyAuthenticationFactorValidator
  • /admin/v1/MyAuthenticationFactorsRemover
  • /admin/v1/TermsOfUseConsent
  • /admin/v1/MyTermsOfUseConsent
  • /admin/v1/TrustedUserAgents
  • /admin/v1/AuthenticationFactorInitiator
  • /admin/v1/AuthenticationFactorEnroller
  • /admin/v1/AuthenticationFactorValidator
  • /admin/v1/MePasswordResetter
  • /admin/v1/UserPasswordChanger
  • /admin/v1/UserLockedStateChanger
  • /admin/v1/AuthenticationFactorsRemover
  • /admin/v1/BypassCodes
  • /admin/v1/MyBypassCodes
  • /admin/v1/MyTrustedUserAgents
  • /admin/v1/Devices
  • /admin/v1/MyDevices
  • /admin/v1/TermsOfUses
  • /admin/v1/TermsOfUseStatements
  • /admin/v1/AuthenticationFactorSettings
  • /admin/v1/SsoSettings
  • /admin/v1/AdaptiveAccessSettings
  • /admin/v1/RiskProviderProfiles
  • /admin/v1/Threats
  • /admin/v1/UserDevices
  • /session/v1/SessionsLogoutValidator
  • /ui/v1/signin
Basic Authentication
  • /admin/v1/HTTPAuthenticator
  • /admin/v1/PasswordAuthenticator
Tokens
  • /oauth2/v1/token
  • /oauth2/v1/introspect
  • /oauth2/v1/revoke
  • /oauth2/v1/device
Import/Export
  • /job/v1/JobSchedules?jobType=UserImport
  • /job/v1/JobSchedules?jobType=UserExport
  • /job/v1/JobSchedules?jobType=GroupImport
  • /job/v1/JobSchedules?jobType=GroupExport
  • /job/v1/JobSchedules?jobType=AppRoleImport
  • /job/v1/JobSchedules?jobType=AppRoleExport
Bulk
  • /admin/v1/Bulk
  • /admin/v1/BulkUserPasswordChanger
  • /admin/v1/BulkUserPasswordResetter
  • /admin/v1/BulkSourceEvents
Other

Any API not in one of the other API Groups is included in the Other API Group

Other Restrictions

These restrictions are for Bulk, Import, and Export for all tiers:

  • Payload size: 1 MB
  • Bulk API: 50 operations limit per call
  • Only one of these can be run at a time:
    • Import: For Users, Groups & App Role Memberships
    • Full sync from apps
    • Bulk APIs
    • Export: For Users, Groups & App Role Memberships
  • CSV Import: 100 K rows limit per CSV & Max file size: 10 MB
  • CSV Export: 100 K rows limit

Using cURL

cURL is an open source, command line tool for transferring data with URL syntax, supporting various protocols including HTTP and HTTPS. The examples within this document use cURL to demonstrate how to access the identity domains REST API.

Using cURL to Access the REST APIs

  1. Install cURL. See Step 2: Install cURL.

  2. In a command window, set the cURL environment variable, CURL_CA_BUNDLE, to the location of your local CA certificate bundle. For information about CA certificate verification using cURL, see: http://curl.haxx.se/docs/sslcerts.html.

    Note

    See Authorization for more information about authorization and authentication requirements.

  3. Invoke cURL and specify one or more of the following command line options, as required, to direct its execution.

    • -d, --data @file.json: Identifies the request document, in JSON format, on the local machine.
    • -F, --form @file.json: Identifies form data, in JSON format, on the local machine.
    • -H, --header: Defines the request header in the format of HEADER: VALUE. The header values depend on which endpoint that you're accessing.
      • The content type of the request document.

      • The X-Client-ID, API_KEY_ID, for OAuth 2.0 authorization

      • The X-Client-Secret, API_KEY_SECRET, for OAuth2.0 authorization

    • -i: Displays response header information.
    • -X: Indicates the HTTP request method (DELETE, GET, POST, PATCH, or PUT). If this option is omitted, the default is GET.

The cURL Command URL

The URL used with the cURL command is the same as that described in Send Requests except that you must replace spaces in the URL with plus characters (+) and replace quotes (") with %22.

Any characters in a URL that are outside the ASCII character set, such as spaces and quotes, must be URL encoded. For example, the following URL contains a filter query that searches for a user with a username either containing jen or starting with bj. Note that it contains spaces.

https://<domainURL>/admin/v1/Users?filter=userName co "jen" or userName sw "bj"

To use this URL in a cURL command line, you would change it to:

https://<domainURL>/admin/v1/Users?filter=userName+co+%22jen%22+or+userName+sw+%22bj%22

cURL Command for Sending a GET Request

curl 
-H "Accept: application/scim+json" 
-H "Authorization: Bearer <really long access token here>" 
-G https://<domainURL>/admin/v1/Groups?filter=displayName+co+%22admin%22"

cURL Command for Sending a POST Request

curl 
-H "Content-Type: application/scim+json" 
-H "Authorization: Bearer <really long access token here>" 
-d '{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],"userName":"bjensen@example.com","name": {"familyName":"Jensen","givenName": "Barbara","middleName": "Jane"},"emails": [{"value": "bjensen@example.com","type": "work","primary": true}]}' "https://<domainURL>/admin/v1/Users"

Managing Authorization Using the API

The identity domains REST API supports both token-based authorization and OCI request signatures. For security reasons, the identity domains REST API isn't accessible using only the username and password that you use to sign in to the identity domain. To access the identity domains REST API, you need an OAuth2 access token or an API key to use for authorization.

identity domains REST API use the OAuth 2.0 protocol for authentication and authorization and support these common authorization scenarios:

  • Web server

  • Mobile

  • JavaScript applications

The Authorization section discusses the OAuth 2.0 scenarios that identity domains support.

This section contains the following topics:

Registering a Client Application

An application must be registered as an OAuth 2 Client using the identity domain. OAuth clients are HTTP clients that can get and then use an access token.

Complete the following steps to use an OAuth client to access identity domains REST API:

  1. Sign in to the identity domain using the username and password found in your Welcome email.

  2. Create an OAuth client application and make note of the client ID and client secret.

    Note

    When you configure the OAuth client application, select the application roles that you want to assign to the application. This enables your application to access the REST APIs that each of those assigned application roles can access. Each application role has scopes assigned to it that define an even more fine-grain level of access to API operations. For example, select Identity Domain Administrator from the list. All REST API operations available to the identity domain administrator will be accessible to the application.
  3. Use the client ID and client secret to request an access token from the IAM OAuth Service.

  4. Include the access token in the appropriate HTTP header when you make REST API calls.

More Information

Security Recommendations

To securely integrate your applications with identity domains using OAuth, you must implement security controls recommended by the standard.

The security controls may be considered mandatory or optional depending on your application confidentiality, integrity, and availability requirements.

A secure OAuth integration requires:
  • Security controls implemented across all OAuth participants, which includes the Authorization Server ( IAM), the Resource Owner (user), the Client, and the Resource Server applications

  • Confidentiality of key information: code, access_token, refresh_token, client credentials, and user credentials

  • Server authentication established between OAuth participants (to avoid impersonation attacks)

  • Proper information validation for any request (especially for JSON Web Token (JWT) access tokens)

  • Use of tokens with minimal scopes and timeout (to reduce the exposure in case of disclosure and to support the token revocation)

  • Use of typical information security principles such as least privilege

Resources

For more information about OAuth security, access the following links:

Note

We recommend that you monitor security proactively so that you can quickly identify new security threats.

Security Recommendations Checklist

This page lists the most relevant security recommendations as a checklist, so that you can validate your application security and address the security items according to your expectations.

Encryption

  • Use TLS in Client and Resource Server Applications

    The use of TLS with all applications provides confidentiality in communications between identity domain, resource owners, client applications, and resource server applications. This prevents eavesdropping during transmission of the authorization code, access tokens, refresh tokens, client credentials, and user credentials, and preventing replay attacks.

  • Establish Server Authentication (HTTPS with Trusted CA Validation)

    Server authentication allows clients, resource servers, and resource owners to establish communication between themselves and with an identity domain after verifying the public certificate against the trusted CA.

    If the server fails to provide a trusted certificate (provided by a trusted CA and with a matching hostname), the communication is considered a man-in-the-middle attack.

    Server authentication prevents spoofing, proxying, man-in-the-middle, and phishing attacks to capture authorization codes, access tokens, client credentials, and user credentials.

  • Consider Using a Trusted Assertion with Identity Domains

    Critical security clients can use a client assertion with key cryptography (instead of a client secret) for authentication.

  • Protect the Redirect URI with HTTPS and Trusted CA Validation

    HTTPS and using trusted CA validation prevents authorization "code" phishing and user session impersonation.

Administration

  • Configure Applications Following the Least Privilege Principle

    Applications should be configured in an identity domain with only the minimum rights needed for their operation.

    Narrowing down the scope, flows, grant types, and operations improves the security posture and reduces the impact of a compromised application.

  • Provide a Meaningful Name and Description for Applications

    The application information appears for users under the My Apps and the consent pages.

    The use of meaningful application names and descriptions may prevent users from making mistakes during consent authorization and also contributes to better audit reporting.

  • Provide a Meaningful Description for Scopes

    The scope description appears on the consent page. Explaining the scope, which the user is about to grant, in an understandable way prevents the user from making mistakes during authorization and contributes to better audit reporting.

  • Avoid Scopes Provided Without Consent

    To leverage transparency and rely on the resource owner, provide scopes without permission only when a scope is mandatory, and the user must not be able to deny it.

  • Reduce the Access Token Time Out and Use Refresh Tokens

    Identity domains support JWT, an access token that can be validated in resource servers without checking the token in the identity domain. Because of this, access tokens with long duration can't be easily revoked.

    To implement timely revocation, you can configure the access token with a short lifetime, and then use the refresh token for requesting new access tokens. To perform a timely revocation, you need to revoke the refresh token.

  • Rotate the Application's Client Secrets

    For security critical implementations, implement a client secret rotation. This reduces the risk of getting a compromised client secret explored.

Resource Owner (User)

  • Keep the Resource Owner Informed

    Scope use with consent provides transparency to the resource owner and prevents applications from requesting scopes that aren't required.

  • User Awareness

    Teach users how to protect their credentials and identify client, resource server application, and identity domain legitimacy (especially when authentication and consent pages appear). This reduces the risk of phishing attacks and the compromise of user credentials.

Application Development

  • Protect Codes, Access Tokens, Refresh Tokens, and Client Credentials

    Applications must preserve the confidentiality of codes, access tokens, refresh tokens, and client credentials. When you develop the application, consider the following measures (among other application security measures):

    • Don't store codes (use the code only during runtime to obtain the access token)

    • Keep access tokens in transient memory and limit their grants

    • Store refresh tokens and client credentials in secure places that can be accessed only by the application

  • Protect the Redirect URL

    The redirect URL (from where the identity domain retrieves the authorization code) is considered a key component for OAuth security. Be careful when you define this URL to avoid threats such as cross site request forgery and denial of service.

  • Read Tokens from the Native Apps File System

    Attackers may try to get file system access on the device and read the refresh tokens using a malicious application. To reduce this risk, store secrets in secure storage and use device lock to prevent unauthorized device access.

  • Implement Controls for Cloned and Stolen Devices with Native Apps

    To reduce risks when a device with Native Apps gets cloned or stolen, use device lock to prevent unauthorized access and revoke refresh tokens.

  • Validate Application Security Prior to Publication

    Test the application and its hosting environment security before publishing the application to reduce vulnerabilities. Threats related to application hosting and development aren't addressed by identity domains. These threats include but aren't limited to indirect access to application databases and storage, select-jacking, cross-site scripting, script/SQL injection, and information confidentiality flows on the application.

  • Apply Least Privilege During Scope Request

    Client applications should request tokens that contain only scopes that it will possibly or actually use.

    The use of the urn:opc:idm:__myscopes__ scope, although convenient, may retrieve more tokens than needed by the client application.

    A token with extensive scopes can increase the security impact when a token is compromised.

    See Scopes for information about using the scope parameter and an access token to grant different levels of access to identity domains.

  • Validate JWT Tokens

    When receiving an access token (JWT) from any party (except the identity domain server in a direct request from your application), validate the JWT following the JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants and the JWT RFCs.

    See Token Validation for more information on how to validate the token.

    Note

    Resource servers must process information only after the entire JWT validation is performed.
  • Receive JWT Tokens Properly

    Resource server applications must receive the access token using only the Authorization: bearer <token> header to avoid threats related to parameter caching.

  • Implement 2-Way TLS Between Client and Resource Server Applications

    For security critical applications, you can implement a 2-way TLS between client and resource server applications to reduce the risk of denial of service (DoS) and impersonation attacks.

    Don't write applications that collect authentication information directly from users.

  • Prevent Select-Jacking

    For newer browsers, avoid iFrames during authorization by enforcing the use of the X-FRAME-OPTIONS header.

    For older browsers, JavaScript frame-busting techniques can be used but may not be effective in all browsers.

  • Avoid the Use of Resource Owner Password Credentials

    The resource owner flow allows a client to request an access token using an end user's ID, password, and the client's own credentials. This grant type presents a higher risk because:
    • It's in charge of collecting the user credentials on the client application (maintains the UID/password anti-pattern).

    • Doesn't present a consent screen for scope requests.

    Except for migration reasons, avoid the use of this grant type.

  • Use the Cache-Control="no-store" Header

    This header minimizes the risk of not protecting authenticated content and leaking confidential data in HTTP proxies.

  • Avoid Requests with Sensitive Information Sent Using URL Parameters

    The URL parameters (used on GET requests) can be logged in any component between applications such as application logs, proxy servers, firewalls, and network edge components.

    Identity domains implement alternative search REST endpoints using POST that addresses this risk. See the Query Parameters page for more information.

Supported Tokens

A token is used to make security decisions to authorize a user and to store tamper-proof information about a system entity in an identity domain.

Identity domains support JSON Web Tokens (JWT). A JWT is a JSON-based open standard (RFC 7519) that defines a compact and self-contained way for securely sending information between parties as a JSON object. This information can be verified and trusted because it's digitally signed. JSON Web Tokens consist of three parts separated by periods (xxxx.yyyy.zzzz):

  • Header. Consists of two parts: the type of token (JWT) and the hashing algorithm being used, such as SHA256

  • Payload. Contains the claims (the token data)

  • Signature. Consists of the encoded token header and the encoded payload signed with the identity domain private key. The signature is used to verify that the sender of the JWT is who it says it's and ensures that the message wasn't changed along the way.

Identity domains support three different tokens: identity token, access token, and client assertion.

To access detailed information on each supported token, select any of the following links:

For information about token expiration go to:

Identity Token

An Identity Token is an integrity-secured, self-contained token (in JSON Web Token (JWT) format) that's defined in the OpenID Connect standard containing claims about the end user. The Identity Token is the primary extension that OpenID Connect makes to OAuth 2.0 to enable authentication in an identity domain.

The Identity Token JWT consists of three components, a header, a payload, and the digital signature. Following the JWT standard, these three sections are Base64URL encoded and separated by periods.

Note

OpenID Connect requests must contain the openid scope value.

OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows an IAM identity domain client application (registered as an OAuth 2 client with client ID and client secret) to verify the identity of the end user based on the authentication performed by an Authorization Server (AS), and to obtain basic profile information about the end user in an interoperable, REST-like manner. OpenID Connect allows clients of all types, including web-based, mobile, and JavaScript clients to request and receive information about authenticated sessions and end users. See OpenID Connect for more information.

Name Value
amr Authentication Methods References. JSON array of strings that are identifiers for authentication methods used in the authentication. For example, values might indicate that both password and OTP authentication methods were used.
at_hash OAuth 2 Access Token hash value.
aud Identifies recipients for which this ID Token is intended. Must be the OAuth 2.0 client_id (per the OpenID Connect specification). This is the OAuth client name (app.name) that's making the request. Aud also contains the IAM identity domain Issuer, thereby turning the token type (IT) into an IAM identity domain User Assertion.
authn_strength* The value returned by Cloud SSO indicating Authentication Strength from AuthN Context.
auth_time The time (UNIX epoch time) when Cloud SSO actually authenticated the user (in seconds, coming from AuthN Context).
azp Authorized party. The party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It may be included even when the authorized party is the same as the sole audience. The azp value is a case-sensitive string that contains a StringOrURI value.
exp The expiration time (UNIX epoch time) on or after which the ID Token must not be accepted for processing. This value must be same as the session_exp.
iat The time (UNIX epoch time) when the JWT was created (in seconds). UNIX Epoch Time is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in Coordinated Universal Time (UTC) until the date/time.
iss The principal that issued the token: https://<domainURL>
jti The server-generated unique identifier for the JWT ID.
nonce The string value used to associate a client session with an ID Token and to mitigate replay attacks. This value is provided by Cloud Gate.
session_exp* The time (UNIX epoch time) when the Cloud SSO session expires (seconds, must be the same SSO's session expiration in AuthN context).
sid The session ID from Cloud SSO (255 maximum ASCII characters) from AuthN Context.
sub Identifies the user. The subject identifier is locally unique, never reassigned, and is intended to be consumed by the client: User Login ID (255 maximum ASCII characters). This is the user's login ID from AuthN Context.
sub_mappingattr* The attribute used to find the sub in the ID store.
tok_type* Identifies the token type: IT
user_displayname* The User Display Name (255 maximum ASCII characters) from AuthN Context.
user_csr* Indicates (true) that the user is a Customer Service Representative (CSR).
user_id* The user's IAM identity domain GUID from AuthN Context.
user_lang* The user's preferred language.
user_locale* The user's locale.
user_tenantname* The User Tenant Name (255 maximum ASCII characters). Tenant's GUID is specifically not saved in the token
user_tz* The user's time zone.

Client/User JWT Assertion

An assertion is a package of information that facilitates the sharing of identity and security information across security domains. An assertion typically contains information about a subject or principal, information about the party that issued the assertion and when it was issued. It also contains information about the conditions under which the assertion is to be considered valid, such as when and where it can be used. The intent is to provide an alternative client authentication mechanism. Clients can build client assertions and use them as credentials rather than using the client ID and client secret in an OAuth token request.

Identity domains support the use of client and user assertions for authentication. The following information defines the format of the client assertion and the user assertion, including standard and custom claims. Names with (*) are proprietary to Oracle.

Client/User Assertion Headers
Name Value
kid Key identifier. Used to identify the trusted third-party certificate to validate the assertion signature. The x5t or kid claim must be present in the JWT assertion header.
type Type. Identifies the type of assertion, which is always JWT.
alg Algorithm. Identifies the specific type of JWT signing algorithm. This is a required header for the JWT assertion. Identity domains support RS256.
x5t Base64 URL encoded X.509 certificate sha1 thumbprint. This is used to identify specific certificates. The x5t or kid claim must be present in the JWT assertion header.
JWT Body/Claims
Name Value
sub Subject. The principal that's the subject of the JWT: For client assertions, the client ID value must be the identity domain App name attribute. For user assertions, the claim value must be the username.
iss Issuer. The Client that's generating the assertions (identity domain App name attribute). This is a required claim for the assertion.
aud Audience. Identifies the recipients for which the JWT is intended. The identity domain URL (https://<domainURL>) must be one of the aud claim values.
exp Expiration. The time (UNIX epoch time) when the JWT assertion expires. This is a required claim for the assertion.
iat Issued at. The date when the assertion was issued.

Sample JWT Client Assertion

{ 
    "kid": "SampleOAuthClient_1",
    "typ": "JWT",
    "alg": "RS256",
    "x5t": "fa4c3b48128f0a88cb8e3c37fbcd02d341080e4f33f081dc546886e7f4bc26aa"
}
{ 
"aud": ["https://<domainURL>/"],
        "sub": "60da13c1-6f27-41e2-bc4e-9cdbccbb4251",
        "iss": "60da13c1-6f27-41e2-bc4e-9cdbccbb4251",
        "exp": "1598229425738",
        "iat": "1440549425738",
        "jti": "bbd28459-5ba9-4dfb-bfeb-8141eca853c4"
}

Sample JWT User Assertion

{
 "kid": "SampleOAuthClient_1",
 "typ": "JWT",
 "alg": "RS256",
 "x5t": "fa4c3b48128f0a88cb8e3c37fbcd02d341080e4f33f081dc546886e7f4bc26aa"
}

{
 "aud": ["https://<domainURL>/"],
 "sub": "test@oracle.com",
 "iss": "60da13c1-6f27-41e2-bc4e-9cdbccbb4251",
 "exp": "1598229425738",
 "iat": "1440549425738",
 "jti": "bbd28459-5ba9-4dfb-bfeb-8141eca853c4"
}
Generating User and Client Assertions Using a Signing Key

Before You Begin

Ensure that you have the following installed.
  1. GlassFish javax.json-1.0.4 library
  2. JDK 8 to perform the base64 encoding/decoding.

Note: It's not necessary to generate a signed client assertion if the client can authenticate using client ID & client secret. You need to decide how to authenticate the client by using the client ID/client secret or by using PKI.

Assertion Generator Lightweight JDK8

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
 
/**
 *
 * Sample class to generate assertions suitable for IDCS jwt-bearer style OAuth
 * Requires JDK8 in order to perform the Base64 encoding/decoding
 *
 * JSON dependency is javax.json-1.0.4.jar
 * http://central.maven.org/maven2/org/glassfish/javax.json/1.0.4/javax.json-1.0.4.jar
 *
 * Assumptions - self-signed keypair generated using something like ..
 *
 * KEY_ALG=RSA
 * SIG_ALG=SHA256withRSA
 *
 * ${JAVA_HOME}/bin/keytool -genkeypair -v -keystore .... -storetype PKCS12 -storepass .... \
 * -keyalg ${KEY_ALG} -keysize 2048 -sigalg ${SIG_ALG} -validity 1825 \
 * -alias ...  -keypass .... -dname ...."
 *
 * Using client and user assertion output from this class, obtain access token using something like ....
 *
 * grant_type='urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer'
 * user_assertion='XXXXXXX.YYYYYYY.ZZZZZZZZ'
 * client_assertion_type='urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer'
 * client_assertion='AAAAAAA.BBBBBBB.CCCCCCCC'
 * client_id='31282cbe9858409ab5b5a6020e85ccb6'
 * scope='urn:opc:entitlementid=999999999urn:opc:resource:consumer::all'
 *
 * oauth_payload="grant_type=${grant_type}&assertion=${user_assertion}&client_assertion_type=${client_assertion_type}&client_assertion=${client_assertion}&client_id=${client_id}&scope=${scope}"
 *
 * oauth_url='https://idcs-XXXXXXXXXXXX.YYYYYY.com/oauth2/v1/token'
 *
 * curl -i
-H "Content-Type:application/x-www-form-urlencoded;charset=UTF-8" --request POST ${oauth_url} -d ${oauth_payload}
 */
public class AssertionGeneratorLightweightJdk8
{
    // Client certificate in raw form - obtained from the Generate Self-Signed Keypair section
    static String CLIENT_CERT =
        "MIIDtzCCAp+gAwIBAgIENeogPjANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFzAVBgNVBAcTDlJlZHdvb2QgU2hvcmVzMRswGQYDVQQKExJPcmFjbGUgQ29ycG9yYXRpb24xDDAKBgNVBAsTA0lETTEjMCEGA1UEAxMac2xleHRjb21wMTMgQ0VDUyBBc3NlcnRpb24wHhcNMTgwODE1MTAyMDQ1WhcNMjMwODE0MTAyMDQ1WjCBizELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFzAVBgNVBAcTDlJlZHdvb2QgU2hvcmVzMRswGQYDVQQKExJPcmFjbGUgQ29ycG9yYXRpb24xDDAKBgNVBAsTA0lETTEjMCEGA1UEAxMac2xleHRjb21wMTMgQ0VDUyBBc3NlcnRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCT+xQU6S+KzjunLPFuvfpy86BxNcUJp8EppGORDR3VrjNH69G3hVF18gV9J/XAVtPApP4n+ZRRQvaFuzwjaXHf3vZ10wEu/N0RIE3zIq98CBMyRp2C8orTYuboN1pQGjieAEBHe2kp7Y1Jkc2UtircRHSpOBDp7KwuwLlHmlBXC4clF6nzFq8UZ9hg4UkA5+lDR70esRAEgrDxJpnSjp27cJFhZHP8oaLQ+ai4wvg9UReUns/mTcNwc6Acv/HPK+d9m9AEzj7ItAVYhnfhQVZ4fUr/AiAvAT43Pv0ZqEHlyByjqauIYp8O+kvtCC68A4mGMHDUNxvVq10Bs7SozaWzAgMBAAGjITAfMB0GA1UdDgQWBBT8O+7161UPiGFbrsEh0Rua0JJezTANBgkqhkiG9w0BAQsFAAOCAQEAAoh+ThSg3Jk4el/RHCOOJZ1pbSMKjmmzWC46Ca8tpjdJ4iaOYrXe+QQmyUvfp/hGcKdvbvex/Ot19d4TxMwNHxapxPfllKDd8WYzMdBc1th8JLxeGXHYfRhk1ImHQWDW9B1K2x2JC/03Wtg/d+Ipno97ydnzcz1+Ef1HEuG4A8WmXS2GBppldZxIeI4XMqi9nKxyDZX+WQPi6RgbpLkizY3krcHUbdwsuWKoc2JATST8XgUx5hw2znlFezt60+7uXnFbfU72WgYrzwrr8NWiR6d9LLP9t5R9odY2Q4WoifwzljkslpYZ0hjWFuvRdLK/XLzb0hLiU0m15oZz9kQWqw==";
 
    // PKCS8 version of the private key in raw form - obtained from the Generate Self-Signed Keypair section
    
static String CLIENT_PRIVATE_KEY =
        "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCT+xQU6S+KzjunLPFuvfpy86BxNcUJp8EppGORDR3VrjNH69G3hVF18gV9J/XAVtPApP4n+ZRRQvaFuzwjaXHf3vZ10wEu/N0RIE3zIq98CBMyRp2C8orTYuboN1pQGjieAEBHe2kp7Y1Jkc2UtircRHSpOBDp7KwuwLlHmlBXC4clF6nzFq8UZ9hg4UkA5+lDR70esRAEgrDxJpnSjp27cJFhZHP8oaLQ+ai4wvg9UReUns/mTcNwc6Acv/HPK+d9m9AEzj7ItAVYhnfhQVZ4fUr/AiAvAT43Pv0ZqEHlyByjqauIYp8O+kvtCC68A4mGMHDUNxvVq10Bs7SozaWzAgMBAAECggEARy0C0bP/HAJqCtTBI4TZC6VGzG0SYrx/WiopgcEPUpHBNJymeGD1d4d7QGGSAHtCymwRmuSehB9zN4uBN38mOImjfbSJ4zHYmr4w//r08PFpWktAw5UpVNdDPPoyxEh4Zvaz9C3VvUb3KCWq/hZIsz1x51qCOCGQB8TG2TvN3K+BP0zzB0IPRqI7b3ydxLFJ8Hn9Y1HRd/8fi11wiPlHtVwMhKXrqnTiaZTayUW9ARPgLK4ZajtUM5FNC8PRTZqxkMge9qC4Q8067zuIMZhHeRR8bLS/5MHSae6/uR0vZOg9nWmRj6Zq33tlflaPcSer/RWlAY5AygQGFveVJc8fQQKBgQDN5jJQPyPcHN+mopJxO5P0c5f69sv8J4hG05qC1I66P5w+TkZZJQYJGMJbazrDmgHigcrbNdUnjYhrNyOipzaYaSye8FRrmgpTZY1nwlY5qj5HHi5GNjbMq/OJKbs46mBu3aSl3K1d0ujAv+rxUofd9PwNjmBMyfNr95h3Jmew0QKBgQC3/Qv02c0e4RrdWVfpi71AiUqmMQ/nKj1SVQ54XQU6FY0y9RTYENN7+b6mFYHJm9B9CkQPx4NsScmQK/ucvE1ZxZANeFaOENAiq06A+0tj31FGoDBIihVYUkHnrupiJz8ug+9c4jwUoho95V6/iLVnRu4a70Wc97N1LnGeG/QvQwKBgH7GXfRK7Cl7HbncH47YwCCji9BaZP682IvDfj9P4RGMWQeD6oy43x56wDDJtUT6bm6ou959JuFTo8tgB/D+Q/9TwsWZ9GDMV89Bl+9rGOwohnADhTp15wfeV/T8XOqOZRHeJqJ5XcWHNwh3IpGz3zQqw4cVQvYE4nx31siGPRIBAoGAIgDSRN472okfvejVJoR85YB6G1zV45Ma4ix2ECig3qs8/T3uLEBv1WnCok83PVtenL1Y9tGYqFq6tbprNfxXD1BD3zluRbM1xDKEv7GxrTOIgdT5F27tovUQ2RCqoJlARAh+JFxrXiTXVLkfWaaaYAvr1W6DHw9oSy/aL65a4qECgYB85lE4sKn2g97W7i51w7rNZwRPr0WcwDz2ecuXOFaURw9g/+8duD9Cq4zMcxwNSjc/kPbxNrY3PKcbZm2Guq6KSiF6Svg8valbMuEadOar/4CZeGyHy8tfYHRGxHP5w2Bh1HbCVQvjC3IzAZJi6pjknz7HuIdOkuhCcSRGjLhurQ==";
 
static String KEY_ID = "cecsassertionkey"; // the alias/key we registered the public certificate under
 
static String CLIENT_ID = "31282cbe9858409ab5b5a6020e85ccb6"; // the trusted client ID
 
static String USER_NAME = "abc@xyz.com"; // the user whom we want to assert identity for
 
static List<String> AUDIENCE_LIST = Arrays.asList("<domainURL>/");
 
    // JSON Web Token Claims ...
    private static final String ISSUER_CLAIM = "iss";
    private static final String SUBJECT_CLAIM = "sub";
    private static final String AUDIENCE_CLAIM = "aud";
    private static final String EXPIRATION_TIME_CLAIM = "exp";
    private static final String NOT_BEFORE_CLAIM = "nbf";
    private static final String ISSUED_AT_CLAIM = "iat";
    private static final String JWT_ID_CLAIM = "jti";
 
    // JSON Web Token Header Parameters
    private static final String ALGORITHM_HEADER = "alg";
    private static final String KEY_ID_HEADER = "kid";
    private static final String X509CERT_SHA1_HEADER = "x5t";
    private static final String X509CERT_SHA256_HEADER = "x5t#S256";
 
    public static void main(String[] args) throws Exception
    {
        Date now = new Date();
 
        Date expirationTime = new Date((60 * 60 * 1000) + now.getTime()); // (1 hour from current time)
 
        JsonObject clientClaims = buildJWTClaims(CLIENT_ID, CLIENT_ID, AUDIENCE_LIST, expirationTime, now, now,
            UUID.randomUUID().toString());
 
        System.out.println(clientClaims.toString());
 
        // Call the method to generate the assertions for both client and user assertions

        String clientAssertion = generateAndSignJWTAssertion(CLIENT_PRIVATE_KEY, CLIENT_CERT, KEY_ID, clientClaims);
 
        System.out.println("Trusted Client Signed Client Assertion:" + clientAssertion);
 
        JsonObject userClaims = buildJWTClaims(CLIENT_ID, USER_NAME, AUDIENCE_LIST, expirationTime, now, now,
            UUID.randomUUID().toString());
        System.out.println(userClaims.toString());
 
        String userAssertion = generateAndSignJWTAssertion(CLIENT_PRIVATE_KEY, CLIENT_CERT, KEY_ID, userClaims);
 
        System.out.println("Trusted Client Signed User Assertion: " + userAssertion);
    }
 
    // Builds JsonObject with the list of claims
    static JsonObject buildJWTClaims(
        String issuer,
        String subject,
        List<String> audience,
        Date expirationTime,
        Date notBefore,
        Date issuedAt,
        String jwtId
    )
    {
        Map<String, Object> claims = new LinkedHashMap<>();
 
        claims.put(ISSUER_CLAIM, issuer);
        claims.put(SUBJECT_CLAIM, subject);
        claims.put(AUDIENCE_CLAIM, audience);
        claims.put(EXPIRATION_TIME_CLAIM, expirationTime);
        claims.put(NOT_BEFORE_CLAIM, notBefore);
        claims.put(ISSUED_AT_CLAIM, issuedAt);
        claims.put(JWT_ID_CLAIM, jwtId);
 
        return createJsonObjectFromMap(claims);
    }
 
public static String generateAndSignJWTAssertion(
        final String base64EncodedPrivateKey,
        final String base64EncodedCertificate,
        final String keyID,
        final JsonObject claims
) throws CertificateException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
        SignatureException
{
   // Get the certificate from certificate factory
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(
            new ByteArrayInputStream(Base64.getDecoder().decode(base64EncodedCertificate)));
 
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(
            new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64EncodedPrivateKey)));;
 
        // NOTE returned Strings may be padded at end with potentially 0, 1, or 2 trailing '=' signs.
        String base64X5TUrl = getCertificateDigestAsURLSafeBase64EncodedString(certificate, "SHA-1");
 
        String base64X5T256Url = getCertificateDigestAsURLSafeBase64EncodedString(certificate, "SHA-256");
 
       // Populate the header for signing
        Map<String, Object> headers = new LinkedHashMap<>();
 
        headers.put(ALGORITHM_HEADER, "RS256");
        headers.put(KEY_ID_HEADER, keyID);
        headers.put(X509CERT_SHA1_HEADER, base64X5TUrl);
        headers.put(X509CERT_SHA256_HEADER, base64X5T256Url);
 
        JsonObject header = createJsonObjectFromMap(headers);
        System.out.println(header.toString());
 
        String signingInput = toBase64URLSafe(header.toString().getBytes(StandardCharsets.UTF_8), true) + '.'
            + toBase64URLSafe(claims.toString().getBytes(StandardCharsets.UTF_8), true);
 
        Signature signer = Signature.getInstance("SHA256withRSA");
        signer.initSign(privateKey);
        signer.update(signingInput.getBytes(StandardCharsets.UTF_8));
 
        String signature = toBase64URLSafe(signer.sign(), true);
 
        String assertion = signingInput + '.' + signature;
 
        return assertion;
}
 
static JsonObject buildJWTHeader(
        String issuer,
        String subject,
        List<String> audience,
        Date expirationTime,
        Date notBefore,
        Date issuedAt,
        String jwtId
)
{
        Map<String, Object> claims = new LinkedHashMap<>();
 
        claims.put(ISSUER_CLAIM, issuer);
        claims.put(SUBJECT_CLAIM, subject);
        claims.put(AUDIENCE_CLAIM, audience);
        claims.put(EXPIRATION_TIME_CLAIM, expirationTime);
        claims.put(NOT_BEFORE_CLAIM, notBefore);
        claims.put(ISSUED_AT_CLAIM, issuedAt);
        claims.put(JWT_ID_CLAIM, jwtId);
 
        return createJsonObjectFromMap(claims);
}
 
private static JsonObject createJsonObjectFromMap(Map<String, Object> map)
{
        JsonObjectBuilder builder = Json.createObjectBuilder();
 
        for (Map.Entry<String, Object> claim : map.entrySet())
        {
            String key = claim.getKey();
            Object value = claim.getValue();
            if (value == null)
            {
                continue;
            }
 
            if (value instanceof String)
            {
                builder.add(key, (String) value);
            }
            else if (value instanceof Date)
            {
                builder.add(key, Long.valueOf(((Date) value).getTime() / 1000L)); // seconds since epoch
            }
            else if (value instanceof List)
            {
                List<String> list = (List<String>) value;
                if (list.size() == 0)
                {
                    continue;
                }
                else if (list.size() == 1)
                {
                    String listVal = list.get(0);
                    if (listVal != null)
                    {
                        builder.add(key, list.get(0));
                    }
                }
                else
                {
                    JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
                    for (String listVal : list)
                    {
                        if (listVal != null)
                        {
                            arrayBuilder.add(listVal);
                        }
                    }
 
                    builder.add(key, arrayBuilder);
                }
            }
        }
 
        return builder.build();
}
 
public static String getCertificateDigestAsURLSafeBase64EncodedString(
        X509Certificate certificate,
        String hashAlg
) throws NoSuchAlgorithmException, CertificateEncodingException
{
        // hash algorithm "SHA-1" or "SHA-256"
        byte[] certificateEncoded = certificate.getEncoded();
 
        byte[] digest = MessageDigest.getInstance(hashAlg).digest(certificateEncoded);
 
        return toBase64URLSafe(digest, true);
}
 
public static String toBase64URLSafe(byte[] bytes, boolean removePadding)
{
        String base64URLSafeString = Base64.getUrlEncoder().encodeToString(bytes);
 
        return removePadding
            ? trimTrailingBase64Padding(base64URLSafeString)
            : base64URLSafeString;
}
 
public static String trimTrailingBase64Padding(String b64EncodedString)
{
        if (b64EncodedString != null)
        {
            if (b64EncodedString.endsWith("=="))
            {
                return b64EncodedString.substring(0, b64EncodedString.length() - 2);
            }
            else if (b64EncodedString.endsWith("="))
            {
                return b64EncodedString.substring(0, b64EncodedString.length() - 1);
            }
        }
 
        return b64EncodedString;
    }
}
Sample Output and Decoding from Assertion Java Code
Trusted Client Signed User Assertion
eyJhbGciOiJSUzI1NiIsImtpZCI6ImNlY3Nhc3NlcnRpb25rZXkiLCJ4NXQiOiJ4YWhmUG1xOXJqaGlya3V5YldzMXJra1oxZW8iLCJ4NXQjUzI1NiI6InFXbS12X251b3JsNDM3Nlk1LWlTY3hPd3lwVXp5bDB4Y1NsS0Nucm5xX0kifQ.eyJpc3MiOiIzMTI4MmNiZTk4NTg0MDlhYjViNWE2MDIwZTg1Y2NiNiIsInN1YiI6InNoYXVuLmxpbkBvcmFjbGUuY29tIiwiYXVkIjoiaHR0cHM6Ly9pZGVudGl0eS5vcmFjbGVjbG91ZC5jb20vIiwiZXhwIjoxNTM0NDc5ODU0LCJuYmYiOjE1MzQ0NzYyNTQsImlhdCI6MTUzNDQ3NjI1NCwianRpIjoiNmZhOWE3MGYtNTU4Yy00YzkzLWJhYzctYzZhNjcyYTA1OTkyIn0.hCTvkcA_wwSCTAM1mHa4Bib2bcdbyGBdTnJpGJ9oXqh3Tp60Jh5izwvv1Pj3GwUm1QmeAIW-GwKlwZWLuCWOEmj53FByial14E9_4_ZJGc870MGlmCTx-WzvuEMk-wWaRhtjichtYC4ofyl00qzg3Cw3WljfN-Zm4EkLJmgkjL8YflFB7qRwmFfi_X_AMjq_FSI8QPIRZqf9HOcLGLXkSqYLsDh1sEv9Og3PbGkmwRA2Zaq6waP7Izzx0ge5IfQdBIotv76IPJ0cyIVUbfhCc-TO71WqrWlfCA2dZxC7nCE0y01NBYPpaMm8kGj71lWHrIn0yfULJgYS0-lPOiAMYg
Trusted Client Signed Client Assertion
eyJhbGciOiJSUzI1NiIsImtpZCI6ImNlY3Nhc3NlcnRpb25rZXkiLCJ4NXQiOiJ4YWhmUG1xOXJqaGlya3V5YldzMXJra1oxZW8iLCJ4NXQjUzI1NiI6InFXbS12X251b3JsNDM3Nlk1LWlTY3hPd3lwVXp5bDB4Y1NsS0Nucm5xX0kifQ.eyJpc3MiOiIzMTI4MmNiZTk4NTg0MDlhYjViNWE2MDIwZTg1Y2NiNiIsInN1YiI6IjMxMjgyY2JlOTg1ODQwOWFiNWI1YTYwMjBlODVjY2I2IiwiYXVkIjoiaHR0cHM6Ly9pZGVudGl0eS5vcmFjbGVjbG91ZC5jb20vIiwiZXhwIjoxNTM0NDc5ODU0LCJuYmYiOjE1MzQ0NzYyNTQsImlhdCI6MTUzNDQ3NjI1NCwianRpIjoiYTliZGVjZGQtNWNjZS00ZjJkLTk3MTAtMjY2MWYxMGFhYmQxIn0.JvzZaeD1pS2KMrrh2CzdQk61oj04XeRXZOlMfSDDEpmaw6gSys1DrbiOWa4IPircHMRGskQ-SbGTH3IdZ_UqPgPmjDL46EpGg_1i90l-GUepnFpoUTwuUX0uDWGijrpxIF-n0DyyxipVbwVBNbduPm4vd4Gzz2r59O_0xh46DWF1KnIHyKUXiEQBwZl269ZpoFUiPPhaswOzWphYttMixUGzcsvSijPMOdPmbaSrGKXk0vBlxJqJnzQInQ_Kyj4MnP6LTHpsF3mqTnNmtnVkDy1AtShTp9xrjQGJaWLfwpswSwmBZAceMjsGIvJ3g84WJl2XcyoEEDlSR0A8z6Dyxg
Decoding User Assertion
Header
{
   "alg": "RS256",
   "kid": "cecsassertionkey",
   "x5t":
        "xahfPmq9rjhirkuybWs1rkkZ1eo",
   "x5t#S256":
        "qWm-v_nuorl4376Y5-iScxOwypUzyl0xcSlKCnrnq_I"
 }
Payload
{
   "iss": "31282cbe9858409ab5b5a6020e85ccb6",
   "sub":
        "abc@xyz.com",
   "aud": "https://<domainURL>/",
   "exp": 1534479854,
   "nbf": 1534476254,
   "iat":
        1534476254,
   "jti": "6fa9a70f-558c-4c93-bac7-c6a672a05992"
}
Decoding Client Assertion
Header
{
   "alg": "RS256",
   "kid": "cecsassertionkey",
   "x5t":
        "xahfPmq9rjhirkuybWs1rkkZ1eo",
   "x5t#S256":
        "qWm-v_nuorl4376Y5-iScxOwypUzyl0xcSlKCnrnq_I"
}
Payload
{
   "iss": "31282cbe9858409ab5b5a6020e85ccb6",
   "sub":
        "31282cbe9858409ab5b5a6020e85ccb6",
   "aud": "https://<domainURL>/",
   "exp": 1534479854,
   "nbf": 1534476254,
   "iat":
            1534476254,
   "jti": "a9bdecdd-5cce-4f2d-9710-2661f10aabd1"
}
Example Token Requests Using User Assertions
Example Request Using Authorization Header and User Assertion
   curl -i
   -H 'Authorization: Basic <base64Encoded clientid:secret>'
   -H 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8'
   --request POST https://<domainURL>/oauth2/v1/token
   -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=<Base64 encoded user-assertion-value>&scope=<scope value>'
Example Request Using User Assertion and Client Assertion
   curl -i
   -H 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8'
   --request POST https://<domainURL>/oauth2/v1/token
   -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=<Base64 encoded user-assertion-value>&scope=<scope value>' \
   -d 'client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=<Base64 encoded client-assertion-value>'

Token Expiry Table

The token expiry table contains the expiry setting name and provides the default value for the setting.

Setting Name Default Value Description
Per Tenant SSO Session Expiry Per Tenant Per Tenant session expiry time (SSOSettings) that the tenant can modify. The default expiration is eight hours.
Global SSO Session Expiry 8 Hours Global Session expiry time (SSOConfig)
Request Cookie Expiry 15 Minutes Cookie expiry time for IDCS_REQUEST cookie
OAuth Access Token Expiry

3600 Seconds

Note: The default is used when a Resource App Expiry, User Session Expiry or Custom Expiry isn't set.

An access token's (AT) expiry time is in seconds. AT expiry time is determined by a combination of the following factors:

  • OAuthConfig Access Token Expiry time. A global configuration applied to all tenants. Expiry time is in seconds. The default is 3600 seconds. The range is 60 seconds to 1 year.
  • Resource App Expiry time. A configuration applied only to the related Resource App. Expiry time is in seconds. The default is 3600 seconds. The range is 60 seconds to 1 year.
  • User Session Expiry time. A tenant level configuration that applies to all users in the tenant. Expiry time is in minutes. The default is 480 minutes. The expiry time is based on the time remaining in the session. For example, if the time remaining in a session is 15 minutes out of a total of 480 minutes, then 15 minutes is used to calculate the AT expiry time.
  • Custom Expiry time. Specified in the token request by sending urn:opc:resource:expiry=<seconds> in the scope parameter.
    1. If the Resource App Expiry time (400 Seconds) and the User Session Expiry time (15 minutes) are both configured and the Custom Expiry time (500 seconds) is specified in token request, then the AT expiry is a minimum of all three, for example, AT: min(400,500,15*60) = 400s.
    2. If only the Resource App Expiry time (400 Seconds) is configured and the Custom Expiry time (500 seconds) is specified in the token request, then the AT expiry is a minimum of the Resource App Expiry time and the Custom Expiry time (500 seconds), for example, AT: min(400, 500) = 400s.
    3. If only the User Session Expiry time (15 minutes) is configured, then the AT is the minimum of the User Session Expiry time and the OAuth Access Token Expiry time (500 seconds), for example, AT: min(500,15*60) = 500s.
    4. If neither the Resource App Expiry time nor the User Session Expiry time is configured but the Custom Expiry time (500 seconds) is specified in token request, then AT expiry is set to the Custom Expiry time with the max limit of 1 year, for example, AT: min(500s,1yrs) = 500s.
    5. If neither the Resource App Expiry time nor the User Session Expiry time is configured and the Custom Expiry time isn't specified either, then the AT expiry will default to the OAuth Access Token Expiry time of 3600 seconds.
OAuth Identity Token Expiry Set to SSO session Expiry Set to SSO session expiry.
OAuth Refresh Token Expiry 1 week Coming from Resource Server's configuration, if available. Otherwise, it's coming from OAuthConfig for the refresh token-type expiry. If the expiry value isn't defined in OAuthConfig, the default value is one week.
OAuth AZ Code Expiry 3 minutes

Updating Refresh Token Expirations

Refresh tokens carry the information necessary to get a new access token. In other words, whenever an access token is required to access a specific resource, a client may use a refresh token to get a new access token issued by the authentication server.

A common use case is getting new access tokens after old ones have expired, such as an access token expiring on a mobile app. The mobile app sends the refresh token to obtain a new access token with no need for caching the user's password.

Refresh tokens do expire, but are typically long-lived.

Use the following steps when you want to see how long the refresh token is valid or when you need to update the refresh token value.
Note

The default value for the refreshTokenExpiry attribute is seven days. The value is listed in seconds: 604800.
Get the Current Refresh Token Expiration Value

Make a GET request to the /Apps endpoint, requesting a specific App ID, and then specify the refreshTokenExpiry attribute.

Request Example

GET <domainURL>/admin/v1/Apps/{{appID}}?attributes=refreshTokenExpiry

Response Example

The refreshTokenExpiry attribute is returned in the response (in bold in the example).

{
    "isAliasApp": false,
    "displayName": "ResourceOwner",
    "refreshTokenExpiry": 604800,
    "id": "{{appID}}",
    "basedOnTemplate": {
        "value": "CustomWebAppTemplateId"
    }
}

Alternatively, you can make a GET request to the /Apps endpoint, requesting a specific App ID to return all application-specific attributes, including the refreshTokenExpiry attribute.

Request Example

GET <domainURL>/admin/v1/Apps/{{appID}}

Response Example

The refreshTokenExpiry attribute is returned in the response (in bold in the example).

{
    "accessTokenExpiry": 3600,
    "clientType": "confidential",
    "isAliasApp": false,
    "audience": "<domainURL>",
    "meta": {
        "created": "2022-06-25T16:10:26.953Z",
        "lastModified": "2022-06-25T20:37:14.039Z",
        "resourceType": "App",
        "location": "https://<domainURL>/admin/v1/Apps/9fc12da9eecd4927a9ef88512ce5612e"
    },
    "active": true,
    "isLoginTarget": true,
    "idcsCreatedBy": {
        "display": "admin opc",
        "type": "User",
        "value": "855344f8015347e1a26c1ac9b2a2898e",
        "$ref": "https://<domainURL>/admin/v1/Users/855344f8015347e1a26c1ac9b2a2898e"
    },
    "displayName": "ResourceOwner",
    "showInMyApps": false,
    "isMobileTarget": false,
    "allowOffline": true,
    "isUnmanagedApp": false,
    "idcsLastModifiedBy": {
        "display": "OAuthClient",
        "type": "App",
        "value": "66efab799b084c21bf84edcf1f587380",
        "$ref": "https://<domainURL>/admin/v1/Apps/66efab799b084c21bf84edcf1f587380"
    },
    "isOPCService": false,
    "refreshTokenExpiry": 604800,
    "name": "3fd7476a48a94381bd5e1bc88cc92021",
    "isOAuthClient": true,
    "isManagedApp": false,
    "isSamlServiceProvider": false,
    "infrastructure": false,
    "allUrlSchemesAllowed": true,
    "trustScope": "Explicit",
    "id": "9fc12da9eecd4927a9ef88512ce5612e",
    "isWebTierPolicy": false,
    "loginMechanism": "OIDC",
    "allowAccessControl": false,
    "isOAuthResource": true,
    "migrated": false,
    "isKerberosRealm": false,
    "attrRenderingMetadata": [
        {
            "name": "aliasApps",
            "visible": false
        }
    ],
    "basedOnTemplate": {
        "lastModified": "2022-05-04T10:47:12Z",
        "value": "CustomWebAppTemplateId",
        "$ref": "https://<domainURL>/admin/v1/AppTemplates/CustomWebAppTemplateId"
    },
    "redirectUris": [
        "http://localhost:8943"
    ],
    "allowedGrants": [
        "client_credentials",
        "refresh_token",
        "authorization_code"
    ],
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:App"
    ],
    "clientSecret": "this-is-not-the-secret",
    "grantedAppRoles": [
        {
            "value": "29722be952c14f9fac5237e5dd088660",
            "$ref": "https://<domainURL>/admin/v1/AppRoles/29722be952c14f9fac5237e5dd088660",
            "appId": "IDCSAppId",
            "display": "identity domain administrator",
            "type": "direct",
            "appName": "IDCSApp",
            "adminRole": true
        },
        {
            "value": "6aa28be4b79143099e90e5dcdd820844",
            "$ref": "https://<domainURL>/admin/v1/AppRoles/6aa28be4b79143099e90e5dcdd820844",
            "appId": "IDCSAppId",
            "display": "Me",
            "type": "direct",
            "appName": "IDCSApp",
            "adminRole": true
        },
        {
            "value": "99224c8907d84560b9621dcda9ecb8b4",
            "$ref": "https://<domainURL>/admin/v1/AppRoles/99224c8907d84560b9621dcda9ecb8b4",
            "appId": "IDCSAppId",
            "display": "Cloud Gate",
            "type": "direct",
            "appName": "IDCSApp",
            "adminRole": true
        }
    ]
}
Change the Refresh Token Value

To update the refreshTokenExpiry attribute value, make a PATCH request to the /Apps endpoint specifying the App ID, and then define the updated refreshTokenExpiry attribute value in the payload.

Request Example

PATCH <domainURL>/admin/v1/Apps/{{appid}}
{
  "schemas": [
    "urn:ietf:params:scim:api:messages:2.0:PatchOp"
  ],
  "Operations": [{
      "op": "replace",
      "path": "refreshTokenExpiry",
      "value": 904800 
   }
]
}

Response Example

The response returned includes the updated refreshTokenExpiry attribute value (in bold in the example).

{
    "accessTokenExpiry": 3600,
    "clientType": "confidential",
    "isAliasApp": false,
    "audience": "https://<domainURL>",
    "meta": {
        "created": "2022-06-25T16:10:26.953Z",
        "lastModified": "2022-06-25T20:37:14.039Z",
        "resourceType": "App",
        "location": "https://<domainURL>/admin/v1/Apps/9fc12da9eecd4927a9ef88512ce5612e"
    },
    "active": true,
    "isLoginTarget": true,
    "idcsCreatedBy": {
        "display": "admin opc",
        "type": "User",
        "value": "855344f8015347e1a26c1ac9b2a2898e",
        "$ref": "https://<domainURL>/admin/v1/Users/855344f8015347e1a26c1ac9b2a2898e"
    },
    "displayName": "ResourceOwner",
    "showInMyApps": false,
    "isMobileTarget": false,
    "allowOffline": true,
    "isUnmanagedApp": false,
    "idcsLastModifiedBy": {
        "display": "OAuthClient",
        "type": "App",
        "value": "66efab799b084c21bf84edcf1f587380",
        "$ref": "https://<domainURL>/admin/v1/Apps/66efab799b084c21bf84edcf1f587380"
    },
    "isOPCService": false,
    "refreshTokenExpiry": 904800,
    "name": "3fd7476a48a94381bd5e1bc88cc92021",
    "isOAuthClient": true,
    "isManagedApp": false,
    "isSamlServiceProvider": false,
    "infrastructure": false,
    "allUrlSchemesAllowed": true,
    "trustScope": "Explicit",
    "id": "9fc12da9eecd4927a9ef88512ce5612e",
    "isWebTierPolicy": false,
    "loginMechanism": "OIDC",
    "allowAccessControl": false,
    "isOAuthResource": true,
    "migrated": false,
    "isKerberosRealm": false,
    "attrRenderingMetadata": [
        {
            "name": "aliasApps",
            "visible": false
        }
    ],
    "basedOnTemplate": {
        "lastModified": "2022-05-04T10:47:12Z",
        "value": "CustomWebAppTemplateId",
        "$ref": "https://<domainURL>/admin/v1/AppTemplates/CustomWebAppTemplateId"
    },
    "redirectUris": [
        "http://localhost:8943"
    ],
    "allowedGrants": [
        "client_credentials",
        "refresh_token",
        "authorization_code"
    ],
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:App"
    ],
    "clientSecret": "this-is-not-the-secret",
    "grantedAppRoles": [
        {
            "value": "29722be952c14f9fac5237e5dd088660",
            "$ref": "https://<domainURL>/admin/v1/AppRoles/29722be952c14f9fac5237e5dd088660",
            "appId": "IDCSAppId",
            "display": "identity domain administrator",
            "type": "direct",
            "appName": "IDCSApp",
            "adminRole": true
        },
        {
            "value": "6aa28be4b79143099e90e5dcdd820844",
            "$ref": "https://<domainURL>/admin/v1/AppRoles/6aa28be4b79143099e90e5dcdd820844",
            "appId": "IDCSAppId",
            "display": "Me",
            "type": "direct",
            "appName": "IDCSApp",
            "adminRole": true
        },
        {
            "value": "99224c8907d84560b9621dcda9ecb8b4",
            "$ref": "https://<domainURL>/admin/v1/AppRoles/99224c8907d84560b9621dcda9ecb8b4",
            "appId": "IDCSAppId",
            "display": "Cloud Gate",
            "type": "direct",
            "appName": "IDCSApp",
            "adminRole": true
        }
    ]
}

Using an OAuth Token for Platform Services

The OAuth 2.0 token service provided by identity domains is a mechanism that enables you to use a secured token to access the REST endpoints of Oracle Cloud Platform Services (PaaS).

Note

  • To access a cloud platform service that's integrated with identity domains, you need the identity domain URL. If you don't know the identity domain URL, see Finding an Identity Domain URL.

  • cURL examples are used in the procedure to obtain an access token from identity domains, and then access a cloud platform service REST endpoint with the token.

An OAuth access token has an expiration value of 86,400 seconds (24 hours). To make REST API requests 24 hours after getting an access token, you need to obtain a new token.

Prerequisites

Get the following information from the identity domain before you begin.

  • Identity domain URL
  • Client ID
  • Client secret
  • Primary audience URL
  • Allowed scope
  1. Sign in to the My Services dashboard for your identity domain.

    Note

    You need to have either the identity domain administrator role or PaaS administrator role to follow the steps in this procedure.
  2. In the list of services, find the entry for the identity domain, and then select Identity Cloud.

  3. On the Overview tab, find the Service Instances section, and then copy the value shown in the Service Instance URL field.

    For example: https://<domainURL>.identity.oraclecloud.com/ui/v1/adminconsole

    Where <domainURL> is the REST server part of the identity domain URL (which forms part of the endpoint URL for requesting an access token).

  4. Select Open Service Console, expand the Navigation Drawer, and then select Applications.

  5. In the search field, enter PSM and then select the search icon. In the results, find the entry titled PSM App for API OAuth support.

    Note

    The Platform Service Manager App (PSMApp) isn't available for Oracle Cloud accounts that were created before 18.1.4.
  6. Select the name of the application titled PSM App for API OAuth support. The name has the form PSMApp-cacct-string-of-letters-and-numbers.

    For example:

    PSMApp-cacct-9z8x7c6v5b4n3m

    This is the identity domain trusted PSM client application, which is automatically created for Oracle Cloud accounts (after 18.1.4) and associated with the Oracle Cloud Platform Service.

  7. Select Configuration. Under General Information, copy the value shown in the Client ID field.

    This is the PSMApp client ID. For example:

    PSMApp-cacct-9z8x7c6v5b4n3m_APPID

  8. Select Show Secret, and then copy the value.

    This is the PSMApp client secret. For example:

    c53b437-1768-4cb6-911e-1e6eg2g3543

  9. Expand Resources. Copy the value shown in the Primary Audience field.

    This is the PSMApp primary audience URL. For example:

    https://psm-cacct-9z8x7c6v5b4n3m.console.oraclecloud.com

  10. In the Allowed Scopes section, copy the Scope value for 1PaaS Permission.

    urn:opc:resource:consumer::all

Get an OAuth Access Token

With the information that you gathered, use the identity domains REST API endpoint /oauth2/v1/token to obtain a token.

   curl -k 
   -X POST -u "client-id:client-secret" 
   -d "grant_type=password&username=yourusername&password=yourpassword&scope=https://primary-audience-and-scope" "https://identity-cloud-service-instance-url/oauth2/v1/token"

Where:

  • client-id is the PSMApp client ID

  • client-secret is the PSMApp client secret

  • yourusername is the cloud platform service username with an administrator role

  • yourpassword is the password for the username

  • primary-audience-and-scope is a concatenation of the PSMApp primary audience URL and the 1PaaS permission scope

  • identity-cloud-service-instance-url is the REST server part of the identity domain URL

For example:

   curl -k 
-X POST -u "PSMApp-cacct-9z8x7c6v5b4n3m_APPID:c53b437-1768-4cb6-911e-1e6eg2g3543" 
-d "grant_type=password&username=yourusername&password=yourpassword&scope=https://psm-cacct-9z8x7c6v5b4n3m.console.oraclecloud.comurn:opc:resource:consumer::all" "https://<domainURL>.identity.oraclecloud.com/oauth2/v1/token"

The following shows an example of the returned response.

{
    "access_token": "eyJ7NXQ...fMf46Q0yKopDxQ",
    "token_type": "Bearer",
    "expires_in": 86400
}
Note

The token string is truncated in the example response. Copy the entire token string (within the quotation marks) as shown in your response.
Use the OAuth Access Token in Cloud Platform Service REST API Requests

After you obtain an OAuth 2.0 access token, you provide the token in a bearer token header of the cloud platform service REST request.

   curl -i 
   -X GET 
   -H "Authorization: Bearer token-string" "https://primary-audience/rest-endpoint-path"

Where:

  • token-string is the OAuth access token that you obtained

  • primary-audience is the PSMApp primary audience URL

  • rest-endpoint-path is the relative path that defines the cloud platform service REST resource. Note that the identity domain ID might be used in the path.

For example, the following cURL command retrieves all Oracle Java Cloud Service instances.
   curl -i -X GET 
   -H "Authorization: Bearer eyJ7NXQ...fMf46Q0yKopDxQ" "https://psm-cacct-9z8x7c6v5b4n3m.console.oraclecloud.com/paas/api/v1.1/instancemgmt/idcs-9a888b7e6ebb44b4b65/services/jaas/instances"

Token Validation

Why do we validate tokens? When your web application checks credentials directly, it verifies that the username and password that are presented correspond to what you maintain. When using claims-based identity, you're outsourcing that job to an identity provider.

The responsibility shifts from verifying raw credentials to verifying that the requestor went through your preferred identity provider and successfully authenticated. The identity provider represents successful authentication by issuing a token. Before you can use the information or rely on it as an assertion that the user has authenticated, you must validate it.

OpenID Discovery Document

The OpenID Connect 1.0 protocol is a simple identity layer on top of the OAuth 2.0 protocol that requires the use of multiple endpoints for authenticating users and for requesting resources that include user information, tokens, and public keys. To help with discovering what these endpoints are that you need to use, OpenID Connect allows you to use a discovery document, which is a JSON document found at a well-known location. This discovery document contains key/value pairs that provide details about the OpenID Connect provider's configuration, including the URIs of the authorization, token, userinfo, and public keys endpoints. You can retrieve the discovery document for an IAM identity domain's OpenID Connect service from: https://<domainURL>/.well-known/openid-configuration.

See the Oracle Identity Cloud Service OpenID Discovery docs.

Validating Identity Tokens

An Identity (ID) Token is an integrity-secured, self-contained token (in JSON Web Token format) that contains claims about the end user. It represents an authenticated user's session. Therefore, the token must be validated before an application can trust the contents of the ID Token. For example, if a malicious attacker replayed a user's ID Token that they had captured earlier, the application should detect that the token has been replayed or was used after it had expired and deny the authentication.

The ID Token is defined in the OpenID Connect standard and is the primary extension that OpenID Connect makes to OAuth 2.0 to enable authentication. ID Tokens are sensitive and can be misused if intercepted. Ensure that these tokens are handled securely by sending them only over HTTPS and only by using POST data or within request headers. If you store them on your server, you must also store them securely.
  1. Verify that the value of the audience (aud) claim contains the application's client_id value. The aud (audience) claim may contain an array with more than one element. The ID Token must be rejected if the ID token doesn't list the client as a valid audience, or if it contains additional audiences that aren't trusted by the client.

  2. Verify that the current time is before the time represented by the expiry time (exp) claim.

  3. Verify that the ID Token is properly signed by the issuer. IAM identity domain-issued tokens are signed using one of the certificates found at the URI specified in the jwks_uri field of the discovery document.
    • Retrieve the tenant's public certificate from the SigningCert/jwk endpoint (for example, https://acme.identity.oraclecloud.com/admin/v1/SigningCert/jwk).

      Note

      Because identity domains change public keys infrequently, you can cache the public keys and, in the vast majority of cases, efficiently perform local validation. This requires retrieving and parsing certificates and making the appropriate crypto calls to check the signature:
    • Use any JWT libraries available to validate, for example, Connect2id's Nimbus JWT Library for Java. See JWT for a list of available libraries.

      Note

      In case of signature validation failure, to prevent constant re-fetches in case of attacks with bogus tokens, the re-fetching/re-caching of the public key should be based on a time interval, such as 60 minutes, so that re-fetches only happen every 60 minutes.

    Example

    package sample;
     
    import java.net.MalformedURLException;
    import java.net.URL;
     
    import com.nimbusds.jose.JWSAlgorithm;
    import com.nimbusds.jose.jwk.source.JWKSource;
    import com.nimbusds.jose.jwk.source.RemoteJWKSet;
    import com.nimbusds.jose.proc.JWSKeySelector;
    import com.nimbusds.jose.proc.JWSVerificationKeySelector;
    import com.nimbusds.jose.proc.SecurityContext;
    import com.nimbusds.jwt.JWTClaimsSet;
    import com.nimbusds.jwt.proc.ConfigurableJWTProcessor;
    import com.nimbusds.jwt.proc.DefaultJWTProcessor;
     
    public class TokenValidation {
     
        public static void main(String[] args) {
            try {
                String tokenValue = "eyJ4NXQjUzI1....W9J4oQ";
         
                ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor();
     
                // change t
                JWKSource keySource = new RemoteJWKSet(new URL("https://<domainURL>/admin/v1/SigningCert/jwk"));
     
                // The expected JWS algorithm of the token (agreed out-of-band)
                JWSAlgorithm expectedJWSAlg = JWSAlgorithm.RS256;
     
                // Configure the JWT processor with a key selector to feed matching public
                // RSA keys sourced from the JWK set URL
                JWSKeySelector keySelector = new JWSVerificationKeySelector(expectedJWSAlg, keySource);
                jwtProcessor.setJWSKeySelector(keySelector);
     
                // Process the token
                SecurityContext ctx = null; // optional context parameter, not required here
                JWTClaimsSet claimsSet = jwtProcessor.process(tokenValue, ctx);
                // Print out the token claims set
                System.out.println(claimsSet.toJSONObject());
                 
     
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
    }
  4. Verify that the value of the Issuer Identifier (iss) claim exactly matches the value of the iss (issuer) claim: https://<domainURL>/

Validating Access Tokens

Successful OAuth transactions require the identity domain OAuth Authorization Server to issue access tokens for use in authenticating an API call. An access token represents an authorization issued to the client application that contains credentials used to access protected OAuth resources. To validate an access token issued from the Authorization endpoint, the application client should do the following:
Note

See the Access Token table.
  1. Verify that the access token is properly signed by the issuer.

    • Retrieve the tenant's public certificate from the SigningCert/jwk endpoint (for example, https://acme.identity.oraclecloud.com/admin/v1/SigningCert/jwk).

      Note

      Because identity domains change public keys infrequently, you can cache the public keys and, in the vast majority of cases, efficiently perform local validation. This requires retrieving and parsing certificates and making the appropriate crypto calls to check the signature:
    • Use any JWT libraries available to validate, for example, Connect2id's Nimbus JWT Library for Java. See JWT for a list of available libraries.

    • Pass the certificate to the respective library's API, for example, using Nimbus SignedJWT API:

      PublicKey = x509Certificate.getPublicKey();
      // verify the signature.
      JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) (publicKey));
      boolean isTokenValid = signedJWT.verify(verifier);
      
      Note

      In case of signature validation failure, to prevent constant re-fetches in case of attacks with bogus tokens, the re-fetching/re-caching of the public key should be based on a time interval, such as 60 minutes, so that re-fetches only happen every 60 minutes.
  2. Verify that the value of the Issuer Identifier (iss) claim exactly matches the value of the iss (issuer) claim: https://<domainURL>/

  3. Verify that the access token has the audience (aud) claim as requested by the client. The value of the aud claim changes from scope to scope. The aud claim is an array if there are multiple audiences and is a string if there's only one audience.

    The aud claim is the primary audience of the IAM identity domain App's resource server. If there are any secondary audiences defined in the IAM identity domain App, then they're also added as part of the aud claim. As part of the access token validation, the server must allow access if one of the values in the aud array makes sense to the resource server.

  4. Verify that the current time is before the time represented by the expiry time (exp) claim.

  5. Verify that the access token is authorized to perform the operation based on the contents of the scope claim. The scope claim in the access token is a space-separated list of strings.

Working with AppRoles

Learn about AppRole permissions, which AppRoles can be granted to clients and users, and how to grant app roles to apps and groups.

AppRoles That Can Be Granted to Clients and Users

Identity domains application roles define what a user or application client can do in an identity domain. These AppRoles directly translate into identity domain OAuth scopes that are used to secure access to protected identity domain resources. Some AppRoles are available only to clients. Some AppRoles are available to both clients and users.

AppRoles Granted Only to Clients

  • Authenticator Client

  • Change Password

  • Cloud Gate

  • DB administrator

  • Forgot Password

  • Kerberos Authenticator

  • Me

  • MFA Client

  • Reset Password

  • Self Registration

  • Signin

  • Verify Email

AppRoles Granted to Clients and Users

  • Authenticator Client

  • Change Password

  • Cloud Gate

  • DB administrator

  • Forgot Password

  • Kerberos administrator

  • Me

  • MFA Client

  • Reset Password

  • Self Registration

  • Signin

  • Verify Email

Granting AppRoles to Groups

Use the following example to create a request that grants application roles to an a group.

{
  "app": {
    "value": "<app_id>"
  },
  "entitlement": {
    "attributeName": "appRoles",
    "attributeValue": "<appRoles_id>"
  },
  "grantMechanism": "ADMINISTRATOR_TO_GROUP",
  "grantee": {
    "value": "<grantee_id>",
    "type": "Group"
  },
  "schemas": [
    "urn:ietf:params:scim:schemas:oracle:idcs:Grant"
  ]
}

Authentication and On-Demand MFA API HTTP Status Codes

The Authentication and On-Demand Multifactor Authentication (MFA) APIs for identity domains in IAM are REST compliant and use standard HTTP response status codes to indicate failure.

This table describes the different status codes and the use cases in which these status codes are sent.

See the Status Code Definitions section of the Hypertext Transfer Protocol -- HTTP/1.1.

HTTP Status Code

Use Case

Sample JSON Response Body

400 Bad Request

This code indicates a bad request. This code is sent if any attribute is supplied with an invalid value in the payload, which signifies syntax issues.

{
    "status": "failed",
    "ecid": "Suwmo0F0000000000",
    "cause":
            [
                {
                    "message": "Invalid value [EMAILS] for attribute authFactor. One of [USERNAME_PASSWORD,PUSH,TOTP,EMAIL,SMS,BYPASSCODE, SECURITY_QUESTIONS] was expected.",
                    "code": "AUTH-1111"
                }
            ],
    "requestState": "bnJ7Qkz2Vff0RNuxwcJQwnaQFA"
}
401 Unauthorized

This code indicates unauthorized access. This is used when the requestState is invalid or expired, or the ID of the otpCode provided during authentication is invalid.

{
    "status": "failed",
    "ecid": "3YkZh1H0000000000",
    "cause":
            [
                {
                    "message": "You entered an incorrect username or password.",
                    "code": "AUTH-3001"
                }
            ],
    "requestState": "b0EYFnXpo"
}
422

This code is used when the request is syntactically correct, but semantically wrong. 422 means that the request is an unprocessable entity. For example, when the request is missing the op attribute, which is mandatory for a given action.

{
    "status": "failed",
    "ecid": "KIN^r0J0000000000",
    "nextOp": ["credSubmit"],
    "cause":
            [
                {
                    "message": "Your input request is missing the op attribute, which is mandatory.",
                    "code": "AUTH-1111"
                }
            ],
    "requestState": "b0EYFnLpFWEihmJ6btqTXpo",
    "USERNAME_PASSWORD":
            {
                "credentials": ["username", "password"]
            },
    "nextAuthFactors": ["USERNAME_PASSWORD"]
}
500 Internal Server Error

This code indicates an internal server error. When this error occurs, the response contains the ecId and the cause so that the client can contact the administrator for further details.

Authentication and On-Demand MFA API Error Codes

The Authentication and On-Demand Multifactor Authentication (MFA) APIs for identity domains in IAM provide error codes and descriptive messages when errors occur.

This table lists the authentication error codes that the Authentication and On-Demand MFA APIs respond with when errors occur.

Error Code

Error Message
AUTH-3001

You entered an incorrect username or password.

AUTH-3002

Your account is locked. Contact your system administrator.

AUTH-3003

Your account is deactivated. Contact your system administrator.

AUTH-3004

Your password is expired.

AUTH-3005

You must change your password.

AUTH-3006

A system error has occurred in identity domains. Contact your system administrator.

AUTH-3007

The username that you entered is invalid. Contact your system administrator.

AUTH-3008

Invalid token. Contact your system administrator.

AUTH-3009

Token expired. Contact your system administrator.

AUTH-3010

Identity domains can't authenticate the user account. Contact your system administrator.

AUTH-3011

There's a problem with the identity domains server. Contact your system administrator.

AUTH-3012

A federated user can't perform local authentication.

AUTH-3013

The logout URL {0} is invalid.

AUTH-3014

Token has no subject.

AUTH-3015

Token has no issuer.

AUTH-3016

Token has invalid issue time.

AUTH-3017

Token has no expiry time.

AUTH-3018

User not found.

AUTH-3019

Token has no issue time.

AUTH-3020

The Subject claim doesn't match the Issuer claim.

AUTH-3021

The Identity Provider name is either blank or incorrect in the request.

AUTH-3022

No identity provider is configured.

AUTH-3023

The credentials that you entered don't match the existing user session.

AUTH-3024

You aren't authorized to access the app. Contact your system administrator.

AUTH-3025

Your account isn't activated. To activate your account, select the link in the activation email that was sent to your email address.

AUTH-3026

Invalid login request. The request wasn't initiated using a supported protocol channel.

AUTH-3028

Identity domains can't authenticate the user account. Contact your system administrator.

AUTH-3029

MFA is enabled for the user. The user must provide a second factor of authentication in addition to password authentication.

AUTH-3030

Tenant has Multifactor Authentication (MFA) enabled. Use MFA for all users of this tenant.

AUTH-3031

User has Multifactor Authentication (MFA) enabled. Use MFA for this user.

AUTH-3032

The user is already logged in.

AUTH-3033

The sign-on policy prevents the user {0} from accessing applications protected by identity domains because: {1}.

AUTH-3034

You configured an invalid error URL.

AUTH-1001

Invalid request. The required parameter '{0}' is missing from the request.

AUTH-1002

The {0} authentication factor is not supported or enabled.

AUTH-1003

Your request to enroll failed because: {0}. Contact your system administrator.

AUTH-1004

Enrollment initiation request failed because: {0}.

AUTH-1005

You are enrolled in the maximum number of 2-Step Verification methods that are allowed.

AUTH-1006

Authentication initiation request failed because {0}.

AUTH-1007

Authentication failed.

AUTH-1008

Couldn't validate security questions because: {0}.

AUTH-1009

Couldn't update security questions because: {0}.

AUTH-1010

Your account is locked. Contact your system administrator.

AUTH-1011

No MFA factors are enabled for this domain.

AUTH-1012

System error.

AUTH-1013

You are not authorized to use 2-Step Verification. Contact your system administrator.

AUTH-1014

The device with ID {1} is not found. Contact your system administrator.

AUTH-1015

User has not selected any security questions.

AUTH-1016

You can't skip enrollment. 2-Step Verification is required.

AUTH-1017

Your 2-Step Verification methods are no longer valid. Contact your system administrator.

AUTH-1018

The ""{0}"" security question hasn't been enabled for user enrollment. Please contact your system administrator.

AUTH-1020

You've already provided this answer for another security question. Please specify a different answer for this question.

AUTH-1021

The answer to the ""{0}"" security question must have at least {1} characters.

AUTH-1022

You must set up {0} security questions to use the Security Questions feature.

AUTH-1023

The hint can't be the same as the answer of a security question.

AUTH-1024

You can select a security question only once.

AUTH-1026

You have entered the wrong answer.

AUTH-1027

You have exceeded the maximum number of 2-Step Verification attempts. Reset your password to unlock your account.

Contact your system administrator if you can't reset your password.

AUTH-1028

You have exceeded the maximum number of 2-Step Verification attempts. Contact your system administrator to unlock your account.

AUTH-1029

Resetting factors cannot be supported if enrollment type is Required.

AUTH-1030

Your phone number {0} is not valid.

AUTH-1031

The phone number {0} is already enrolled for the user.

AUTH-1032

The device status is not valid.

AUTH-1033

Payload error. Either the payload in the request is null, or the payload couldn't be parsed.

AUTH-1034

You are not authorized to perform this action.

AUTH-1035

You have already enrolled in 2-Step Verification. Register for additional factors using the administrative console.

AUTH-1036

Session is no longer valid. Close the browser and log in again.

AUTH-1037

You must set {0} security questions.

AUTH-1038

Please provide your answer for the ""{0}"" security question.

AUTH-1039

The ID of the {0} security question isn't valid.

AUTH-1040

You must answer {0} security questions.

AUTH-1041

Your answer to the ""{0}"" security question can't exceed {1} characters.

AUTH-1042

Your hint to the ""{0}"" security question can't exceed {1} characters.

AUTH-1100

The SMS authentication factor is not enabled.

AUTH-1101

The PUSH authentication factor is not enabled.

AUTH-1102

The OTP authentication factor is not enabled.

AUTH-1103

The Security Questions authentication factor is not enabled.

AUTH-1104

The Bypass Code authentication factor is not enabled.

AUTH-1105

Invalid passcode.

AUTH-1106

Unable to process the request at this time. Use a backup verification method.

AUTH-1107

Pull notification channel has not been enabled for your tenant.

AUTH-1108

Push Notification approval is pending.

AUTH-1109

Enrollment in the One-Time Passcode authentication method is pending verification.

AUTH-1110

The authentication token has expired.

AUTH-1111

The request provided is invalid. Please look at the error message for validation error details.

AUTH-1112

Unexpected error encountered while processing the request.

AUTH-1113

An authentication factor must be provided while configuring a preferred device.

AUTH-1114

You must provide the deviceId when configuring {0} as the preferred authentication factor.

AUTH-1115

The authentication factor passed in the request is not supported. Supported factors are {0}.

AUTH-1116

The op passed in the request is not supported. Supported operations are {0}.

AUTH-1117

The requestState provided has expired. Please provide a valid requestState.

AUTH-1118

You provided an invalid appName. Verify that the App display name is correct.

AUTH-1119

The operation {0} isn't supported by the {1} endpoint. Use the {2} endpoint.

AUTH-1120

The requestState provided is either invalid or expired. Please provide a valid requestState.

AUTH-1121

You provided an invalid request JSON payload.

AUTH-1122

The application is not active.

AUTH-1123

An error occurred while logging in using social identity.

API Use Cases

Step through typical use cases using the IAM identity domain REST APIs.

The response output that you get might differ from the response examples shown in the use cases. The output depends on the release and environment, and the configuration of the identity domain.

Task More Information

Adaptive Risk Analysis for Custom Client Applications

This use case provides an example request of using the adaptive risk analysis endpoints for custom applications and on-premises access management systems.

See Adaptive Risk Analysis for Custom Client Applications.

Oracle Services Onboarding Using the API

Identity domain administrators can manage the onboarding process of OPC applications to an identity domain.

See Allowing Oracle Services Onboarding Using the API.

Changing Your Own Profile Attributes

Use the API to change your own profile attributes (for example, an email address or a password) by setting the allowSelfChange attribute to true in the request payload or URL query string parameter.

See Using allowSelfChange To Update Profile Attributes.

Creating an Enterprise Application with Authorization Policy

This use case provides an example request of creating an enterprise application using REST API.

See Creating an Enterprise Application with Authorization Policy.

Importing and Exporting Users, Groups, and AppRoles

These use cases provide example requests for bulk loading users, groups, and application roles from other repositories into an identity domain.

See Importing and Exporting Users, Groups, and AppRoles.

Managing Custom Claims

This use case provides an example request of how to add custom claims to an access token, an identity token, or both the tokens.

See Managing Custom Claims.

Managing the Refresh Token Expiration Value

This use case provides an example of how to verify the validity of a refresh token and update the token expiry time.

See Updating Refresh Token Expirations.

Managing User Schema Customizations

This use case provides examples of how to add, update, remove, and enable the import of custom user schema attributes in an identity domain.

See Customizing User Schemas.

Obtaining and Using an OAuth Token for Platform Services

This use case provides an example request of how to use a OAuth 2.0 token issued by an identity domain to access REST endpoints from an Oracle Cloud Platform Services (PaaS).

See Using an OAuth Token for Platform Services.

Triggering an Email Verification Flow if Email Address is Already Verified

This use case provides an example of how custom clients can re the change email flow for users who already have verified their email addresses.

Resending Email Verifications When The Email Address Is Already Verified

Using Duo Security with an IAM identity domain

This use case provides an example of how to use an Authenticate API with Duo Security.

See Using Duo Security with Identity Domains.

Using OpenID Connect to Extend OAuth 2.0

This use case provides an example of how client applications can authenticate to an identity domain using OpenID connect protocol and identity domain REST APIs.

See Using OpenID Connect to Extend OAuth 2.0.

Using Self Service to Enroll in MFA using the SMS Factor

This use case provides a step-by-step example of using the identity domain REST API for Self-Service enrollment in Multifactor Authentication (MFA) using SMS Factor.

See Enrolling in MFA using the SMS Factor Using Self Service.

Using the Authenticate API to develop a custom sign-in page

This use case provides an example of how to use the Authenticate API to develop a custom sign-in page.

Using the Authenticate API to Develop a Custom Sign-in Page

Using the Audit Event APIs

This use case provides example of how to get Audit logs covering significant events, changes, and actions.

Using the Audit Event APIs

Important: IAM identity domains AuditEvents and certain reports templates in the Reports APIs will stop returning new data after May 15, 2024. Instead, you can use the OCI Audit service to get this data. To view service change announcements for IAM, see IAM Service Change Announcements.

Using the onBehalfOf Allowed Operation

This use case provides an example of how to create an application and specify the onBehalfOf User allowed operation.

See Using the onBehalfOf Allowed Operation.

Using the On Demand MFA API to Develop Custom Sign-In Page

This use case provides a step-by-step example of using the Authenticate API to authenticate users and perform multifactor enrollment and authentication. This is used when you develop a custom sign-in page.

See Using the On-Demand MFA API to Develop Custom Sign-In Page.

Working with Apps

These use cases provide example requests to create and activate an OAuth Resource Server, an OAuth Client Apps, and a SAML App using the REST APIs. Each use case also provides the required App attributes.

See Working with Apps.

Working with OAuth 2 to Access the REST API

This use case walks you through using an OAuth client with identity domains to access the REST APIs.

See Using OAuth 2 to Access the REST API.

Using OAuth 2 to Access the REST API

The identity domains REST API supports SCIM 2.0 compliant endpoints with standard SCIM 2.0 core schemas and Oracle schema extensions to programmatically manage users, groups, applications, and identity functions, such as password management and administrative tasks. To make REST API calls to your identity domain, you need an OAuth2 access token to use for authorization. The access token provides a session (with scope and expiration), that your client application can use to perform tasks in an identity domain.

The following sequence diagram illustrates a basic example of the OAuth 2.0 authorization flow to access the identity domains REST API.

A diagram that illustrates a basic example of the OAuth 2.0 authorization flow to access the identity domains REST API.

Use specific OAuth 2.0 parameters when working with an identity domain. The following table describes the most common parameters.

Parameter Value Comments

Authorization Header

Basic <base64_clientid_secret>

Used by the client as a Basic authentication scheme to transmit the access token in a header. The access token value needs to be a base64 UTF-8 encoded value of the Client ID and Client Secret concatenated using a colon as a separator-for example, clientID:clientSecret.

Client ID

<client_id>

Required. A unique "API Key" that's generated when you register your application in the identity domain Console.

Client Secret

<client_secret>

Required. A private key similar to a password that's generated when you register your application in the identity domain Console. Don't share this value.

Access Token URL

/oauth2/v1/token

An endpoint used to obtain an access token from the identity domain.

Auth URL

/oauth2/v1/authorize

An endpoint used to obtain an authorization code from identity domains, and then used during a 3-legged OAuth flow.

Grant Type

client_credentials

Required. It means the REST API that's invoked is owned by the client application.

Scope (required)

urn:opc:idm:__myscopes__

This scope returns all the grants given to your application, other scopes could be used to get specific grants, if necessary.

Step 1: Register a Confidential Application in Identity Domains Using the Console

When you register a confidential application in the identity domain Console, you obtain some of the key parameters that you need to work with OAuth 2.0: Client ID, Client Secret, and Scopes. OAuth 2.0 is a standard for implementing delegated authorization, and authorization is based on the access token required to access a resource. The access token can be issued for a given scope, which defines what the access token can do and what resources it can access. When you register a web application in an identity domain, you add scopes. In the following example, the required scopes to request User searches, edits, creates, and deletes are added. But, if you were to do other things-for example, manage Audit Events, that would require other scopes.

To create and register a confidential application access the OCI Console and then complete the following steps:

  1. Open the navigation menu  and select Identity & Security. Under Identity, select Domains.
  2. Click the name of the identity domain that you want to work in. You might need to change the compartment to find the domain that you want. Then, click Integrated applications.
  3. Select Add application.
  4. In the Add application dialog box, select Confidential Application, and then select Launch workflow.
  5. On the Add application details page, enter an application name and description, and then select Next.
  6. On the Configure OAuth page, under Client configuration, select Configure this application as a client now.
  7. Under Authorization, select only Client Credentials as the Allowed Grant Type.
  8. At the bottom of the page, select Add app roles and then select Add roles.
  9. In the Add app roles panel, select Identity Domain Administrator, and then select Add.
  10. Select Next and then select Finish.
  11. On the application detail page, scroll down to General Information. Copy the Client ID and the Client Secret and store it in a safe place.
  12. After the application is created, select Activate.

Step 2: Base64 Encode the Client ID and Client Secret

You must encode the client ID and client secret when you include it in a request for an access token.
Note

Before base64 encoding, individually URL encode the client ID and the client secret. If your client ID and client secret don't contain special characters, you aren't required to URL encode them first. However, as a best practice, we highly recommend it.
The following sections show you how to base64 encode the client ID and client secret in UTF-8 format using a Windows and a Mac/Linux environment.

Windows

  1. Launch Notepad, and then paste the client ID and client secret into Notepad.

  2. Place the client ID and client secret on the same line and insert a colon between them: clientid:clientsecret

    Note

    Ensure that no spaces are the clientid:clientsecret attribute.
  3. Save the file to C:\temp and name the file appCreds.txt.

  4. In Windows Explorer, right-click C:\temp, and then select CMD Prompt Here from the context menu.

  5. Enter the following command to encode the client ID and client secret:
    certutil -encode appCreds.txt appbase64Creds.txt
  6. In Notepad, open C:\temp\appbase64Creds.txt, copy its contents, and then close the file.
    Note

    For security reasons, delete the appCreds.txt and the appbase64Creds.txt files after you finish.

Mac and Linux

  1. Launch your preferred note utility (for example, Mac Notes, Gedit Linux, or Vi), and then paste the client ID and client secret into the note utility.

  2. Place the client ID and client secret on the same line and insert a colon between them: clientid:clientsecret.

    Note

    Ensure no spaces in the clientid:clientsecret.
    statement.
  3. Copy the clientid:clientsecret line.

  4. Launch a terminal and enter the following command, replacing clientid:clientsecret with the value that you copied to the clipboard.

    echo -n "clientid:clientsecret" | base64 -w 0
    Note

    For Linux, add -w 0 to the command to remove line breaks.
  5. Copy the value that's returned.
    Note

    If the value that's returned is broken into more than one line, return to your text editor and ensure the entire results are on a single line with no text wrapping.

Step 3: Obtain an Access Token

The next step in this process is to request the access token.

  1. Launch a command prompt.

  2. Enter the cURL command below, replacing the text in brackets ( < > ) with the appropriate values:

       curl -i
       -H "Authorization: Basic <base64encoded clientid:secret>"
       -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
       --request POST https://<domainURL>/oauth2/v1/token
       -d "grant_type=client_credentials&scope=urn:opc:idm:__myscopes__"
    Note

    If you're using a UNIX OS, you can append | awk -F"\"" '{print $4}' to the end of the cURL command to parse out just the Bearer token. Just remember that the default expiration of the token is 3600 seconds from the time of the request.
    Note

    Optionally, run the following cURL command to have the access token value accessible through a UNIX variable called AccessTokenValue in your environment:
       export AccessTokenValue=`curl -i
       -H "Authorization: Basic <base64encoded clientid:secret>"
       -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
       --request POST https://<domainURL>/oauth2/v1/token
       -d "grant_type=client_credentials&scope=urn:opc:idm:__myscopes__" | awk -F"\"" '{print $4}' |  tail -n +16`
    You can then run echo $AccessTokenValue command to get the access token value.
    Text in Brackets Value
    base64encoded clientid:secret Replace with the encoded credentials that you generated in the Base64 Encode the client ID and client secret section. Ensure no spaces in the clientid:clientsecret credentials.
    IDCS_Service_Instance Replace with your identity domain URL (for example, https://<domainURL>/).
    Note

    The urn:opc:idm:__myscopes__ scope in the command is used as a tag by identity domain clients requesting access tokens from the OAuth authorization server. Access tokens are returned that contain all applicable identity domains scopes based on the privileges represented by the identity domains administrator roles granted to the requesting client and the user being specified by the client's request (if present). This scope isn't granted directly to any identity domains administrator role.
  3. Copy the access_token value from the response. Ensure to copy only the actual token, which is the access_token value between the quotation marks:

    Status: 200
    "access_token":"eyJ4NXQiOiI4Wk. . ."
    "token":"Bearer",
    "expires_in":3600
    
    Note

    The response includes the expires_in: 3600 parameter. This means that your token is no longer valid after one hour from the time that you generate it. After one hour, you must refresh the token or get a new access token. To refresh the token, enter the cURL command below, replacing the text in brackets ( < > ) with the appropriate values:
    curl -i
      -H "Authorization: Basic <base64 encoded client ID and secret>"
      -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
      --request POST https://<domainURL>/oauth2/v1/token
      -d "grant_type=refresh_token&refresh_token=<token_value>"

Step 4: Make a REST Request to the Environment

After you obtain the OAuth 2.0 access token, you can use the token in a cURL command to send a REST request to the identity domains REST API. The following command returns a list of users in an identity domain.

   curl -X GET
   -H "Content-Type:application/scim+json"
   -H "Authorization: Bearer <access_token>"
   https://<domainURL>/admin/v1/Users
Item Value
Method -X GET
Content Type Header -H "Content-Type:application/scim-json"
Authorization Header -H "Authorization: Bearer <access_token>"
HTTP Protocol HTTP or HTTPS (HTTP is recommended)
Identity Domain The identity domain URL (for example, https://<domainURL>).
Identity Domains REST Endpoint /admin/v1/Users

Example JSON Output from the Identity Domains REST API

In the previous step, the REST request sent using cURL returned a response in JSON format. JSON is an open standard that can be formatted or parsed per your needs such as getting specific attributes required by your application.

{
  "schemas": [
    "urn:scim:api:messages:2.0:ListResponse"
  ],
  "totalResults": 1,
  "Resources": [
    {
      "displayName": "admin opc",
      "name": {
        "givenName": "admin",
        "formatted": "admin opc",
        "familyName": "opc"
      },
      "urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User": {
        "locked": {
          "on": false
        }
      },
      "userName": "admin@example.com",
      "id": "d252a54d83c344eb8f59f7053a0562ce",
      "urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User": {
        "isFederatedUser": false
      },
      "active": true,
      "nickName": "TAS_TENANT_ADMIN_USER",
      "emails": [
        {
          "verified": false,
          "value": "admin@example.com",
          "type": "work",
          "primary": true
        },
        {
          "verified": false,
          "value": "admin@example.com",
          "primary": false,
          "type": "recovery"
        }
      ],
      "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User",
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User",
        "urn:ietf:params:scim:schemas:core:2.0:User"
      ],
      "meta": {
        "resourceType": "User",
        "created": "2022-07-22T18:11:08Z",
        "lastModified": "2022-07-25T21:19:28Z",
        "location": "https://<domainURL>admin/v1/Users/d252a54d83c344eb8f59f7053a0562ce"
      },
      "idcsLastModifiedBy": {
        "value": "idcssso",
        "$ref": "https://<domainURL>admin/v1/Apps/idcssso",
        "type": "App",
        "display": "idcssso"
      }
    }
  ],
  "startIndex": 1,
  "itemsPerPage": 50
}

Adaptive Risk Analysis for Custom Client Applications

Customers moving to the Cloud can leverage IAM identity domain adaptive capabilities to meet risk-based analysis for their on-premises access management system, such as Oracle Access Manager (OAM), or client applications.

Identity domains provide an adaptive REST API interface to enable these on-premises access management systems or client applications to use an identity domain risk-based engine to evaluate authentication activities for users.

For example, John Doe is a user in the OAM identity store and in an identity domain. John accesses a finance application protected by OAM. The OAM server redirects him to the OAM sign-in page for authentication. John Doe submits his credentials and based on the risk score returned by the identity domain adaptive risk-based engine, the OAM server may challenge the user with a second factor. If the risk score is high, then OAM may deny access to John and present him a message indicating his attempt to sign in failed.

The adaptive REST API interface implements three use cases in the form of the corresponding endpoints:
  • Populate Risk: /admin/v1/sdk/adaptive/PopulateRisks

  • Fetch Risk Info: /admin/v1/sdk/adaptive/FetchRisks

  • Mitigate Risk: /admin/v1/sdk/adaptive/MitigateRisks

To make REST API calls to these endpoints, your access management system or custom application needs an access token from a client credential application registered in an identity domain.
Note

To obtain an access token, see Using OAuth 2 to Access the REST API.

The adaptive REST API interface requires the client application to send information such as user identification, information of the device the user uses to sign in, and client's true IP address.

To gather device information that your access management system needs to use a device fingerprint JavaScript file. You can download the device fingerprint JavaScript file from the identity domain console.

  1. Sign in to identity domain Console as an application administrator.
  2. Expand the Navigation Drawer, select Settings, and then select Downloads.
  3. In the Downloads page, download the Identity Cloud Service Device Fingerprint Utility.

The file you download is a compressed (zip) file. Inside the zip file there's a JavaScript file that the access management system sign-in page or the client application itself needs to load to collect fingerprint information. Then use the getFingerprint() function to collect user's device fingerprint to send to the identity domains adaptive REST API interface.

See also Enable the Access for an unknown device Event for a Custom Sign-In Page.

Populate Risk

This endpoint is used to submit risk data to an identity domain to increase the user's risk score.

The cURL command structure is:
   curl -k -X POST 'https://<domainURL>/admin/v1/sdk/adaptive/PopulateRisks' 
   -H 'Authorization: Bearer <Access_Token>' 
   -H 'Accept:application/json' 
   -d '<Request_Body>'
The following is the structure of the request body for the Populate Risk endpoint.
{
    "userName": "<User_Name>",
    "data": [
        {
            "name": "device",
            "value": "<result_of_the_devicefingerprint_javascript_file>"
        },
        {
            "name": "client-ip",
            "value": "<ip_address_of_the_user_browser>"
        }
    ],
    "event": "MAX_PASSWORD_FAILED_ATTEMPTS"
}

The event attribute is optional. If not present in the request then all risk events are going to be used to evaluate risk score. You can use MAX_MFA_FAILED_ATTEMPTS or MAX_PASSWORD_FAILED_ATTEMPTS values.

The following is an example of a request body to evaluate risk for John Doe trying to sign in the access management system from the IP address 10.11.12.13. The device fingerprint and IP address will be validated against all enabled risk events in an identity domain.
   curl -k -X POST https://<domainURL>/v1/sdk/adaptive/PopulateRisks \
     -H 'Content-Type: application/json' \
  
   -H 'Authorization: Bearer <Access_Token>' \
  
   -d '{
    "userName": "johndoe@example.com",
    "data": [
        {
            "name": "device",
            "value": "{\"currentTime\":\"Wed Nov 13 2019 16:57:34 GMT-0700 (Pacific Daylight Time)\",\"screenWidth\":1920,\"screenHeight\":1080,\"screenColorDepth\":24,\"screenPixelDepth\":24,\"windowPixelRatio\":1,\"language\":\"en-US\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0\"}"
        },
        {
            "name": "client-ip",
            "value": "10.11.12.13"
        }
    ]
}'
The following is an example of response body of the populate risk endpoint.
{
    "userName": "johndoe@example.com",
    "riskLevel": "LOW",
    "riskScores": [
        {
            "lastUpdateTimestamp": "2022-11-12T10:41:57.997Z",
            "score": 15,
            "riskLevel": "LOW",
            "value": "ORACLE_IDCS",
            "status": "ACTIVE",
            "source": "Default Risk Provider",
            "$ref": "https://<domainURL>/admin/v1/RiskProviderProfiles/ORACLE_IDCS"
        }
    ]
}

Fetch Risk Info

This endpoint enables clients to get current risk information for a single user, multiple users, or for all users in an identity domain.

The cURL command structure is:
   curl -k 
   -X POST 'https://<domainURL>/admin/v1/sdk/adaptive/FetchRisks' 
   -H 'Authorization: Bearer <Access_Token>' 
   -H 'Accept:application/json' 
   -d '<Request_Body>'
The following is the structure of the Request Body for the Fetch Risk Info cURL command.
{
    "userNames": [
        "<user_name>"
    ]
}
You can call the fetch risk info endpoint for multiple users. To do so, use the following request body structure with the cURL command.
{
    "userNames": [
        "<user_name_1>",
        "<user_name_2>"
    ]
}
If you want to fetch risk info for all users in an identity domain, use the following request body structure with the cURL command.
{}
The following is an example of a request body to fetch risk info for John Doe.
   curl -k -X POST https://<domainURL>/admin/v1/sdk/adaptive/FetchRisks \
     -H 'Content-Type: application/json' \
  
   -H "Authorization: Bearer <Access_Token>' \
  
   -d '{
    "userNames": [
        "johndoe@example.com"
    ]
}'
The following is an example of response body of the fetch risk info endpoint.
{
    "totalResults": 1,
    "resources": [
        {
            "userName": "johndoe@example.com",
            "riskLevel": "LOW",
            "riskScores": [
                {
                    "lastUpdateTimestamp": "2022-11-13T18:41:57.997Z",
                    "score": 15,
                    "riskLevel": "LOW",
                    "value": "ORACLE_IDCS",
                    "status": "ACTIVE",
                    "source": "Default Risk Provider",
                    "$ref": "https://<domainURL>/admin/v1/RiskProviderProfiles/ORACLE_IDCS"
                }
            ]
        }
    ],
    "startIndex": 1,
    "itemsPerPage": 50
}

Mitigate Risk

This endpoint enables client applications to request mitigation of a user's risk score because the user has logged in or reset their password successfully.

The cURL command structure is:
   curl -k 
   -X POST 'https://<domainURL>/admin/v1/sdk/adaptive/MitigateRisks' 
   -H 'Authorization: Bearer <Access_Token>' 
   -H 'Accept:application/json' 
    -d '<Request_Body>'
The following is the structure of the request body for the Mitigate Risk cURL command.
{
    "userName": "<User_Name>",
    "data": [
        {
            "name": "device",
            "value": "<result_of_the_devicefingerprint_javascript_file>"
        },
        {
            "name": "client-ip",
            "value": "<ip_address_of_the_user_browser>"
        }
    ],
    "event": "SSO_THREAT_MITIGATION_SUCCESS"
}
The event attribute of the request body can receive multiple values:
  • For successful user sign-in, provide SSO_THREAT_MITIGATION_SUCCESS.
  • For successful user password reset, provide ADMIN_ME_PASSWORD_CHANGE_SUCCESS.
The following is an example of a request body to the Mitigate Risk endpoint for John Doe because he successfully signed in to the access management system from the IP address 10.11.12.13.
   curl -X POST \
  https://<domainURL>/admin/v1/sdk/adaptive/MitigateRisks \
     -H 'Content-Type: application/json' \
     -H 'Authorization: Bearer <Access_Token>' \
  -d '{
    "userName": "johndoe@example.com",
    "data": [
        {
            "name": "device",
            "value": "{\"currentTime\":\"Thu Nov 14 2019 10:11:18 GMT-0700 (Pacific Daylight Time)\",\"screenWidth\":1440,\"screenHeight\":900,\"screenColorDepth\":24,\"screenPixelDepth\":24,\"windowPixelRatio\":2,\"language\":\"en-US\",\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36\"}"
        },
        {
            "name": "client-ip",
            "value": "10.11.12.13"
        }
    ],
    "event": "SSO_THREAT_MITIGATION_SUCCESS"
}'
The following is an example of response body of the populate risk endpoint:
{
    "userName": "johndoe@example.com",
    "riskLevel": "LOW",
    "riskScores": [
        {
            "lastUpdateTimestamp": 1574726401582,
            "score": 10,
            "riskLevel": "LOW",
            "providerId": "ORACLE_IDCS",
            "providerStatus": "ACTIVE",
            "providerDescription": "Default Risk Provider",
            "reference": "https://<domainURL>/admin/v1/RiskProviderProfiles/ORACLE_IDCS"
        }
    ]
}

Using allowSelfChange To Update Profile Attributes

You can use the API to change your own profile attributes (for example, an email address or a password) in an identity domain by setting the allowSelfChange attribute to true in the request payload or URL query string parameter. By default, this attribute is set to false.

Use the allowSelfChange attribute in the request payload for the following operations:

  • Users (PATCH, REPLACE)
  • UserCapabilityChanger (REPLACE)
  • UserLockedStateChanger (CREATE)
  • UserPasswordChanger (REPLACE)
  • UserPasswordResetter (REPLACE)
  • UserStateChanger (PATCH)
  • UserStatusChanger (REPLACE)
  • UserDbCredentials (CREATE)
  • ApiKeys (CREATE, UPDATE)
  • AuthTokens (CREATE, UPDATE)
  • CustomerSecretKeys (CREATE, UPDATE)
  • OAuth2ClientCredentials (CREATE, UPDATE)
  • SmtpCredentials (CREATE, UPDATE)
  • SupportAccounts (CREATE)
Use the allowSelfChange attribute as a URL query string parameter for the DELETE operation on the following APIs.
Note

You must set allowSelfChange=true as a URL query string parameter for DELETE operations.
  • UserDbCredentials
  • ApiKeys
  • AuthTokens
  • CustomerSecretKeys
  • OAuth2ClientCredentials
  • SmtpCredentials
  • SupportAccounts

Sample Request: /Users

Operation: PATCH /admin/v1/Users/<id>
{
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ],
    "Operations": [
        {
            "op": "replace",
            "path": "phoneNumbers",
            "value": [
                {
                    "type": "home",
                    "value": "555-555-0100"
                }
            ]
        },
        {
            "op": "add",
            "path": "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange",
            "value": true
        }
    ]
}

Sample Request: /UserCapabilitiesChanger

Operation: PUT /admin/v1/UserCapabilitiesChanger/<id>
{
    "canUseApiKeys": true,
    "canUseAuthTokens": false,
    "canUseConsolePassword": true,
    "canUseCustomerSecretKeys": true,
    "canUseOAuth2ClientCredentials": true,
    "canUseSmtpCredentials": true,
    "canUseDbCredentials": true,
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true,
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:UserCapabilitiesChanger"
    ]
}

Sample Request: /UserLockedStateChanger

Operation: POST /admin/v1/UserLockedStateChanger
{
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:UserLockedStateChanger"
    ],
    "userId": "<unique_ID>",
    "locked": false,
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true
}

Sample Request: /UserPasswordChanger

Operation: PUT /admin/v1/UserPasswordChanger
{
    "password": "example-password",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true,
    "schemas": [
      "urn:ietf:params:scim:schemas:oracle:idcs:UserPasswordChanger"
    ]
  }

Sample Request: /UserPasswordResetter

Operation: PUT /admin/v1/UserPasswordResetter
{
    "schemas": [
      "urn:ietf:params:scim:schemas:oracle:idcs:UserPasswordResetter"
    ],
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true
  }

Sample Request: /UserStatusChanger

Operation: PUT /admin/v1/UserStatusChanger
{
    "active": true,
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true,
    "schemas": [
      "urn:ietf:params:scim:schemas:oracle:idcs:UserStatusChanger"
    ]
  }

Sample Requests: /ApiKeys

Operation: POST /admin/v1/ApiKeys
{
    "user": {
        "value": "<unique_ID>"
    },
    "key": "-----BEGIN PUBLIC KEY-----<your_public_key>
 -----END PUBLIC KEY-----",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true,
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:apikey"
    ]
}
Operation: PATCH /admin/v1/ApiKeys/<id>
{
      "Operations": [
        {
          "op": "replace",
          "path": "description",
          "value": "<updated_api_key>"
        },
        {
            "op": "add",
            "path": "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange",
            "value": true
        }
      ],
      "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
      ]
    }
Operation: DELETE /admin/v1/ApiKeys/e1eaf8a28e58485fb86f16f914fd08c7?allowSelfChange=true

Sample Requests: /SmtpCredentials

Operation: POST /admin/v1/SmtpCredentials/<id>
{
    "description": "John's smtp credential",
    "user": {
        "value": "<unique_ID>"
    },
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true,
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:smtpCredential"
    ]
}
Operation: PATCH /admin/v1/SmtpCredentials
{
      "Operations": [
        {
          "op": "replace",
          "path": "description",
          "value": "updated_credential_description"
        },
        {
            "op": "add",
            "path": "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange",
            "value": true
        }
      ],
      "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
      ]
    }

Operation: DELETE /admin/v1/SmtpCredentials/e1eaf8a28e58485fb86f16f914fd08c7?allowSelfChange=true

Sample Requests: /AuthTokens

Operation: POST /admin/v1/AuthTokens
{
    "description": "John's auth token",
    "user": {
        "value": "<unique_ID>"
    },
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true,
    "schemas": ["urn:ietf:params:scim:schemas:oracle:idcs:authToken"]
}
Operation: PATCH /admin/v1/AuthTokens/<id>
{
      "Operations": [
        {
          "op": "replace",
          "path": "description",
          "value": "<updated_credential_description>"
        },
        {
            "op": "add",
            "path": "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange",
            "value": true
        }
      ],
      "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
      ]
    }

Operation: DELETE /admin/v1/SmtpCredentials/e1eaf8a28e58485fb86f16f914fd08c7?allowSelfChange=true

Sample Requests: /CustomerSecretKeys

Operation: POST /admin/v1/CustomerSecretKeys
{
    "diplayName": "Alice Customer Secret Key",
    "description": "Alice's Customer Secret Key",
    "user": {
        "value": "<unique_ID>"
    },
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true,
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:customerSecretKey"
    ]
}
Operation: PATCH /admin/v1/CustomerSecretKeys/<id>
{
      "Operations": [
        {
          "op": "replace",
          "path": "description",
          "value": "<updated_credential_description>"
        },
        {
            "op": "add",
            "path": "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange",
            "value": true
        }
      ],
      "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
      ]
    }

Operation: DELETE /admin/v1/CustomerSecretKeys/e1eaf8a28e58485fb86f16f914fd08c7?allowSelfChange=true

Sample Requests: /OAuth2ClientCredentials

Operation: POST /admin/v1/OAuth2ClientCredentials
{
  "name": "User's oauth2 client credential",
  "scopes": [
    {
      "audience": "urn:opc:idm",
      "scope": "__myscopes__"
    }
  ],
  "user": {
    "value": "<unique_ID>"
  },
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true,
  "schemas": [
    "urn:ietf:params:scim:schemas:oracle:idcs:oauth2ClientCredential"
  ]
}
Operation: PATCH /admin/v1/OAuth2ClientCredentials/<id>
{
      "Operations": [
        {
          "op": "replace",
          "path": "description",
          "value": "<updated_credential_description>"
        },
        {
            "op": "add",
            "path": "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange",
            "value": true
        }
      ],
      "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
      ]
    }

Operation: DELETE /admin/v1/OAuth2ClientCredentials/e1eaf8a28e58485fb86f16f914fd08c7?allowSelfChange=true

Sample Request: /SupportAccounts

Operation: POST /admin/v1/SupportAccounts
{
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:supportAccount"
    ],
    "token": "dummy",
    "user": {
        "ocid": "ocid1.user.region1..<unique_ID>"
    },
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:selfChange:User:allowSelfChange": true
}

Operation: DELETE /admin/v1/ApiKeys/e1eaf8a28e58485fb86f16f914fd08c7?allowSelfChange=true

Supporting Social JIT Provisioning with Group Membership Support

Use the API to manage new identity domain users with social Just-In-Time (JIT) user provisioning for first-time users.

OCI REST API now supports social JIT Provisioning, to automate user account creation when the user first tries to access identity domains when the user doesn't exist in the identity domain. Social JIT provisioning also supports granting group membership as part of user provisioning.

Attribute Definitions

  • socialJitProvisioningEnabled: You can enable/disable social JIT by controlling this social attribute.
  • jitProvGroupStaticListEnabled: When JIT is enabled, you can set this attribute to true to indicate social JIT user provisioning groups should be assigned from a static list.
  • jitProvAssignedGroups: This attribute contains a list of groups to be assigned to each social JIT-provisioned user. JIT user-provisioning applies this static list when jitProvGroupStaticListEnabled is set to true.

Examples

Toggle Social JIT GroupMembership support: PATCH /admin/v1/SocialIdentityProviders/{idpID}

Sample request body:
{
  "Operations": [
    {
      "op": "replace",
      "path": "socialJitProvisioningEnabled",
      "value": true
    },
    {
      "op": "replace",
      "path": "jitProvGroupStaticListEnabled",
      "value": true
    },
    {
        "op": "add",
        "path": "jitProvAssignedGroups",
        "value": [
            {
              "value": “<identitydomain-group-id>”
            }
        ]
    }
  ],
  "schemas": [
    "urn:ietf:params:scim:api:messages:2.0:PatchOp"
  ]
}
Sample response:
{
    "idcsCreatedBy": {
        "type": "User",
        "display": "admin opc",
        "value": “<user-id>",
        "$ref": "https://<domainURL>/admin/v1/Users/<user-id>"
    },
    "id": "<identity-provider-id>",
    "meta": {
        "created": "2024-04-29T17:26:15.646Z",
        "lastModified": "2024-06-06T22:03:43.284Z",
        "version": "<version number>",
        "resourceType": "IdentityProvider",
        "location": "https://<domainURL> /admin/v1/IdentityProviders/<identity-provider-id>"
    },
    "enabled": true,
    "idcsLastModifiedBy": {
        "value": "<user-id>",
        "display": "admin opc",
        "type": "User",
        "$ref": "https://<domainURL>/admin/v1/Users/15ae5123456123456aa123456xxx123456"
    },
    "partnerName": "Google",
    "ocid": “<domain-ocid>",
    "socialJitProvisioningEnabled": true,
    "jitProvGroupStaticListEnabled": true,
    "accountLinkingEnabled": true,
    "registrationEnabled": true,
    "serviceProviderName": "Google",
    "consumerSecret": "clientSecret12345",
    "idAttribute": "email",
    "consumerKey": "clientID12345",
    "jitProvAssignedGroups": [
        {
            "value": "<idcs-group-id>",
            "$ref": "https://<domain-id>/admin/v1/Groups/"<idcs-group-id>"
        }
    ],
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:SocialIdentityProvider"
    ],
    "name": "Google",
    "showOnLogin": true
}

Fetch Group Membership for JIT enabled IDP: GET /admin/v1/SocialIdentityProviders/{idpId}?attributes=jitProvAssignedGroups

Sample response:
{
    "id": "<identity-provider-id>",
    "jitProvAssignedGroups": [
        {
            "value": "<idcs-group-id>",
            "$ref": "https://<domain-id>/admin/v1/Groups/"<idcs-group-id>"
        }
    ],
    "name": "Google"
}

Remove particular group GUID from JIT enabled IDP membership list: PATCH /admin/v1/SocialIdentityProviders/{idpId}

Sample request body:
{
  "schemas": [
    "urn:ietf:params:scim:api:messages:2.0:PatchOp"
  ],
  "Operations": [
    {
      "op": "remove",
      "path": "jitProvAssignedGroups[value eq \"<idcs-group-id>\"]"
    }
  ]
}
Sample response body:
{
    "idcsCreatedBy": {
        "type": "User",
        "display": "admin opc",
        "value": “<user-id>",
        "$ref": "https://<domainURL>/admin/v1/Users/<user-id>"
    },
    "id": "<identity-provider-id>",
    "meta": {
        "created": "2024-04-29T17:26:15.646Z",
        "lastModified": "2024-06-06T22:16:47.515Z",
        "version": "<version number>",
        "resourceType": "IdentityProvider",
        "location": "https://<domainURL> /admin/v1/IdentityProviders/<identity-provider-id>"
    },
    "enabled": true,
    "idcsLastModifiedBy": {
        "value": "<user-id>",
        "display": "admin opc",
        "type": "User",
        "$ref": "https://<domainURL>/admin/v1/Users/15ae5123456123456aa123456xxx123456"
    },
    "partnerName": "Google",
    "ocid": “<domain-ocid>",
    "socialJitProvisioningEnabled": true,
    "jitProvGroupStaticListEnabled": true,
    "accountLinkingEnabled": true,
    "registrationEnabled": true,
    "serviceProviderName": "Google",
    "consumerSecret": "clientSecret12345",
    "idAttribute": "email",
    "consumerKey": "clientID12345",
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:SocialIdentityProvider"
    ],
    "name": "Google",
    "showOnLogin": true
}

Remove Group Membership list for IDP enabled IDP: PATCH /admin/v1/SocialIdentityProviders/{idpId}

Sample request body:
{
  "schemas": [
    "urn:ietf:params:scim:api:messages:2.0:PatchOp"
  ],
  "Operations": [
    {
      "op": "remove",
      "path": "jitProvAssignedGroups"
    }
  ]
}
Sample response body:
{
    "idcsCreatedBy": {
        "type": "User",
        "display": "admin opc",
        "value": “<user-id>",
        "$ref": "https://<domainURL>/admin/v1/Users/<user-id>"
    },
    "id": "<identity-provider-id>",
    "meta": {
        "created": "2024-04-29T17:26:15.646Z",
        "lastModified": "2024-06-06T22:16:47.515Z",
        "version": "<version number>",
        "resourceType": "IdentityProvider",
        "location": "https://<domainURL> /admin/v1/IdentityProviders/<identity-provider-id>"
    },
    "enabled": true,
    "idcsLastModifiedBy": {
        "value": "<user-id>",
        "display": "admin opc",
        "type": "User",
        "$ref": "https://<domainURL>/admin/v1/Users/15ae5123456123456aa123456xxx123456"
    },
    "partnerName": "Google",
    "ocid": “<domain-ocid>",
    "socialJitProvisioningEnabled": true,
    "jitProvGroupStaticListEnabled": true,
    "accountLinkingEnabled": true,
    "registrationEnabled": true,
    "serviceProviderName": "Google",
    "consumerSecret": "clientSecret12345",
    "idAttribute": "email",
    "consumerKey": "clientID12345",
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:SocialIdentityProvider"
    ],
    "name": "Google",
    "showOnLogin": true
}

Managing Custom Claims

You can use the identity domains REST API to add custom claims to an access token, an identity token, or both the tokens.

Custom claims are rules that you can add to a token for the identity domain. There's no limit for the number of custom claims in a token. Token size is limited and the allowed values are "8000", "16000","32000", "128000".

The cURL command examples use the URL structure:
https://<domainURL>/admin/v1/CustomClaims/{id}
  1. Specify the headers on the cURL command line:
       -H Authorization: Bearer <Access Token>
       -H Cache-Control: no-cache
       -H Accept:application/json

    To obtain an access token, see Working with OAuth 2 to Access the REST API.

  2. Create the custom claim name MyATCustomClaim and value MyATValue for the access token by running the following command:
       curl -i -X POST https://<domainURL>/admin/v1/CustomClaims

    Example

       curl -i -X POST https://<domainURL>/admin/v1/CustomClaims

    The following is an example of a JSON request body to create the custom claim:

    {
        "schemas": [
            "urn:ietf:params:scim:schemas:oracle:idcs:CustomClaim"
        ],
        "name": "MyATCustomClaim",
        "value": "MyATValue",
        "expression": false,
        "mode": "always",
        "tokenType": "AT",
        "allScopes": true
    }

    Attribute

    Description

    name

    The custom claim name.

    Note: Maximum length is 100 characters.

    value

    The custom claim value.

    Note: Maximum length is 100 characters. If the value comes from the evaluation of a user expression, then there's no limit.

    expression

    Specify if the custom claim value is a user expression. You can determine the user expression by using the Users endpoints.

    Value: true or false

    Example User Expression

    • $user.name.formatted expression with value admin opc.
    • $user.emails.0.type expression with value recovery.
    • $user.emails.1.type expression with value work.
    • $user.urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User.myCustomAttribute expression with value customValue.
    Based on user expressions, a claim returns either a single value attribute or all the attributes associated with the expression. For example, the following expressions return a single value within an array:
    • $user.emails.0.value
    • $(user.emails[0].value)
    While the following expressions return an array:
    • $user.emails.*.value
    • $(user.emails[*].value)

    allScopes

    Specify whether associate the custom claim with a set of scopes or all the scopes.

    Value: true or false

    mode

    Specify how you want to attach the custom claim to a token.
    • always: The custom claim will be attached to the token.
    • request: The custom claim will be attached to the token only if it's requested or overridden.
    • never: The custom claim will not be attached to the token.

    tokenType

    Specify the token type.
    • AT: To add custom claim for an access token.
    • IT: To add custom claim for an identity token.
    • BOTH: To add custom claim for the access and identity token.

    scopes

    Optional. The Custom Claim will be embedded to tokens if any scope in the scopes array is requested in the token request. You can either specify allScopes equals to true with no associated scopes array or has allScopes equals to false with associated scopes array.

    The following shows an example of the response body:

    {
        "schemas": [
            "urn:ietf:params:scim:schemas:oracle:idcs:CustomClaim"
        ],
        "name": "MyATCustomClaim",
        "value": "MyATValue",
        "expression": false,
        "mode": "always",
        "tokenType": "AT",
        "allScopes": true,
        "id": "ddc7f88bea2a46258c593bddccaf2b86",
        "meta": {
            "created": "2022-05-17T04:33:43.640Z",
            "lastModified": "2022-05-17T04:33:43.640Z",
            "resourceType": "CustomClaim",
            "location": "https://<domainURL>/admin/v1/CustomClaims/ddc7f88bea2a46258c593bddccaf2b86"
        },
        "idcsCreatedBy": {
            "value": "bac027a9500c4db9a09f5cfbcbda5076",
            "type": "App",
            "display": "exampleDomainAdmin",
            "$ref": "https://<domainURL>/admin/v1/Apps/bac027a9500c4db9a09f5cfbcbda5076"
        },
        "idcsLastModifiedBy": {
            "value": "bac027a9500c4db9a09f5cfbcbda5076",
            "type": "App",
            "display": "exampleDomainAdmin",
            "$ref": "https://<domainURL>/admin/v1/Apps/bac027a9500c4db9a09f5cfbcbda5076"
        }
    }

    You can derive the user expression from the /admin/v1/Users endpoint. This is the JSON returned for an admin user.

    The values are parsed as String, and the bold in the sample shows how the values are derived for the following expressions.

    Expression

    Value

    $user.name.formatted

    "admin opc"

    $user.emails.0.type

    This expression and the next are an unlabeled array, with a number that starts from 0 to indicate the index of the element in the array.

    "recovery"

    $user.emails.1.type

    "work"

    $user.urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User.myCustomAttribute

    "customValue"

    {
        "idcsCreatedBy": {
            "type": "App",
            "display": "idcssm",
            "value": "32e72bc93b30417697f323d5fa7bbe2e",
            "$ref": "https://<domainURL>/admin/v1/Apps/32e72bc93b30417697f323d5fa7bbe2e"
        },
        "id": "60703e0bddcf4dae9add114179bf042d",
        "meta": {
            "created": "2022-11-08T02:39:01.932Z",
            "lastModified": "2022-11-13T09:44:55.668Z",
            "resourceType": "User",
            "location": "https://<domainURL>/admin/v1/Users/60703e0bddcf4dae9add114179bf042d"
        },
        "active": true,
        "displayName": "admin opc",
        "idcsLastModifiedBy": {
            "value": "f79371bb03914056821a8afb9da5066d",
            "display": "idcssso",
            "type": "App",
            "$ref": "https://<domainURL>/admin/v1/Apps/f79371bb03914056821a8afb9da5066d"
        },
        "nickName": "TAS_TENANT_ADMIN_USER",
        "userName": "admin@oracle.com",
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User": {
            "isFederatedUser": false,
            "myCustomAttribute": "customValue"
        },
        "emails": [
            {
                "verified": false,
                "primary": false,
                "secondary": false,
                "value": "admin@oracle.com",
                "type": "recovery"
            },
            {
                "verified": false,
                "primary": true,
                "secondary": false,
                "value": "admin@oracle.com",
                "type": "work"
            }
        ],
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User": {
            "locked": {
                "on": false
            }
        },
        "name": {
            "familyName": "opc",
            "givenName": "admin",
            "formatted": "admin opc"
        }
    }
  3. Replace all the attributes for the custom claim id ddc7f88bea2a46258c593bddccaf2b86 by running the following command:
       curl -i -X PUT https://<domainURL>/admin/v1/CustomClaims/{id}

    Example

       curl -i -X PUT https://<domainURL>/admin/v1/CustomClaims/ddc7f88bea2a46258c593bddccaf2b86

    The following shows an example of the request body.

    {
        "schemas": [
            "urn:ietf:params:scim:schemas:oracle:idcs:CustomClaim"
        ],
        "name": "MyATClaim1",
        "value": "MyATValue1",
        "expression": false,
        "mode": "request",
        "tokenType": "AT",
        "allScopes": true
    }

    The following shows an example of the response indicating the request succeeded.

    {
        "idcsLastModifiedBy": {
            "type": "App",
            "value": "bac027a9500c4db9a09f5cfbcbda5076",
            "display": "exampleDomainAdmin",
            "$ref": "https://<domainURL>/admin/v1/Apps/bac027a9500c4db9a09f5cfbcbda5076"
        },
        "idcsCreatedBy": {
            "type": "App",
            "display": "exampleDomainAdmin",
            "value": "bac027a9500c4db9a09f5cfbcbda5076",
            "$ref": "https://<domainURL>/admin/v1/Apps/bac027a9500c4db9a09f5cfbcbda5076"
        },
        "mode": "request",
        "id": "ddc7f88bea2a46258c593bddccaf2b86",
        "value": "MyATValue1",
        "expression": false,
        "meta": {
            "created": "2022-05-17T04:33:43.640Z",
            "lastModified": "2022-05-17T04:41:13.177Z",
            "resourceType": "CustomClaim",
            "location": "https://<domainURL>/admin/v1/CustomClaims/ddc7f88bea2a46258c593bddccaf2b86"
        },
        "allScopes": true,
        "name": "MyATCustomClaim1",
        "tokenType": "AT",
        "schemas": [
            "urn:ietf:params:scim:schemas:oracle:idcs:CustomClaim"
        ]
    }
  4. Set the allScopes to false for the id ddc7f88bea2a46258c593bddccaf2b86 by running the following command:
       curl -i -X PATCH https://<domainURL>/admin/v1/CustomClaims/{id}

    Example

       curl -i -X PATCH https://<domainURL>/admin/v1/CustomClaims/ddc7f88bea2a46258c593bddccaf2b86

    The following shows an example of the request body.

    {
        "Operations": [
            {
                "op": "replace",
                "path": "allScopes",
                "value": false
            }
        ],
        "schemas": [
            "urn:ietf:params:scim:api:messages:2.0:PatchOp"
        ]
    }

    The following shows an example of the response indicating the request succeeded.

    {
        "idcsLastModifiedBy": {
            "type": "User",
            "value": "210d294a075a4c86bbf6f958bceacf0c",
            "display": "admin opc",
            "$ref": "https://yourtenant.identity.oraclecloud.com/admin/v1/Users/210d294a075a4c86bbf6f958bceacf0c"
        },
        "idcsCreatedBy": {
            "type": "User",
            "display": "admin opc",
            "value": "210d294a075a4c86bbf6f958bceacf0c",
            "$ref": "https://<domainURL>/admin/v1/Users/210d294a075a4c86bbf6f958bceacf0c"
        },
        "mode": "always",
        "id": "ddc7f88bea2a46258c593bddccaf2b86",
        "value": "MyATValue",
        "expression": false,
        "meta": {
            "created": "2022-05-31T05:43:32.518Z",
            "lastModified": "2022-05-31T05:58:10.362Z",
            "resourceType": "CustomClaim",
            "location": "https://yourtenant.identity.oraclecloud.com/admin/v1/CustomClaims/ddc7f88bea2a46258c593bddccaf2b86"
        },
        "allScopes": false,
        "name": "MyATCustomClaim",
        "tokenType": "AT",
        "scopes": [
            "phone"
        ],
        "schemas": [
            "urn:ietf:params:scim:schemas:oracle:idcs:CustomClaim"
        ]
    }
  5. View all the custom claims in the tenant by running the following command:
       curl -i -X GET https://<domainURL>/admin/v1/CustomClaims

    Example

       curl -i -X GET https://<domainURL>/admin/v1/CustomClaims
    The following shows an example of the response body.
    {
        "idcsLastModifiedBy": {
            "type": "User",
            "value": "210d294a075a4c86bbf6f958bceacf0c",
            "display": "admin opc",
            "$ref": "https://<domainURL>/admin/v1/Users/ddc7f88bea2a46258c593bddccaf2b86"
        },
        "idcsCreatedBy": {
            "type": "User",
            "display": "admin opc",
            "value": "ddc7f88bea2a46258c593bddccaf2b86",
            "$ref": "https://<domainURL>/admin/v1/Users/210d294a075a4c86bbf6f958bceacf0c"
        },
        "mode": "always",
        "id": "98e94996776845719cf3b737e565199a",
        "value": "MyATValue",
        "expression": false,
        "meta": {
            "created": "2022-05-31T05:43:32.518Z",
            "lastModified": "2022-05-31T05:58:10.362Z",
            "resourceType": "CustomClaim",
            "location": "https://<domainURL>/admin/v1/CustomClaims/98e94996776845719cf3b737e565199a"
        },
        "allScopes": false,
        "name": "MyATCustomClaim",
        "tokenType": "AT",
        "scopes": [
            "phone"
        ],
        "schemas": [
            "urn:ietf:params:scim:schemas:oracle:idcs:CustomClaim"
        ]
    }
  6. View the custom claims in a tenant by providing the query parameter.
       curl -i -X GET https://<domainURL>/admin/v1/CustomClaims?attributes=(schema attributes)

    Example

       curl -i -X GET https://yourtenant.identity.oraclecloud.com/admin/v1/CustomClaims?attributes=name,value

    The following shows an example of the response body after providing the query parameter ?attributes=name,value:

    {
        "schemas": [
            "urn:ietf:params:scim:api:messages:2.0:ListResponse"
        ],
        "totalResults": 4,
        "Resources": [
            {
                "name": "AlwaysAllScopesATClaim10",
                "id": "edf077cbae59435dab3f9de5ba1fd619",
                "value": "AlwaysAllScopesATValue"
            },
            {
                "name": "MyATCustomClaim1",
                "id": "ddc7f88bea2a46258c593bddccaf2b86",
                "value": "MyATValue1"
            },
            {
                "name": "MyATCustomClaim",
                "id": "150d1eae9f0f4301a22312bd680aa4df",
                "value": "MyATValue"
            },
            {
                "name": "MyATCustomClaim2",
                "id": "2680b220be904698b43575e3d654a88c",
                "value": "MyATValue2"
            }
        ],
        "startIndex": 1,
        "itemsPerPage": 50
    }
  7. Optionally, delete the custom claim from the tenant by running the following command:
       curl -i -X DELETE https://<domainURL>/admin/v1/CustomClaims/{id}

    Example

       curl -i -X DELETE https://<domainURL>/admin/v1/CustomClaims/ddc7f88bea2a46258c593bddccaf2b86

Resending Email Verifications When The Email Address Is Already Verified

After a user creates an account in an identity domain using the self-registration process, an email notification is sent to the user to verify the user's email address. After users verify their email addresses, they can no longer verify their email addresses after that.

However, identity domains also allow custom clients to reinitiate the change email flow for the same email address as many times as needed. To support this capability, you must set the triggerEmailVerificationFlowIfEmailAlreadyVerified attribute to true in the MeEmailVerifier request payload.

Use the following steps to trigger the email verification flow, if an email address is already verified:

Step 1: Create a User

This step shows how to create a user by submitting a POST request on the REST resource using cURL. For more information about cURL, see Use cURL.

   curl
   -X POST
   -H "Content-Type:application/json"
   -H "Authorization: Bearer <Access Token Value>"https://<domainURL>/admin/v1/Users
Note

The command in this example uses the URL structure https://<domainURL>/resource-path, where <domainURL> represents the identity domain URL, and the resource path represents the identity domain API. See Send Requests for the appropriate URL structure to use.

Example of Request Body

The following shows an example of a request body in JSON format:

{
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User",
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User"
    ],
    "userName": "bjensen@example.com",
    "password": "{{password}}",
    "name": {
        "familyName": "Jensen",
        "givenName": "Barbara",
        "middleName": "Jane"
    },
    "emails": [
        {
            "value": "bjensen@example.com",
            "type": "work",
            "primary": true
        }
    ]
}

Example of Response Body

The following shows an example of the response body:

{
    "idcsCreatedBy": {
        "type": "User",
        "display": "admin opc",
        "value": "6aa2585abd464991929bcf05ace532e9",
        "$ref": "[https://<domainURL>/admin/v1/Users/6aa2585abd464991929bcf05ace532e9]"
    },
    "id": "ff9a9207fc8c4fd2b3d76af84235e8fd",
    "meta": {
        "created": "2022-03-01T05:19:52.765Z",
        "lastModified": "2022-03-01T05:19:52.765Z",
        "resourceType": "User",
        "location": "[https://<domainURL>/admin/v1/Users/ff9a9207fc8c4fd2b3d76af84235e8fd]"
    },
    "active": true,
    "displayName": "Barbara Jensen",
    "idcsLastModifiedBy": {
        "value": "6aa2585abd464991929bcf05ace532e9",
        "display": "admin opc",
        "type": "User",
        "$ref": "[https://<domainURL>/admin/v1/Users/6aa2585abd464991929bcf05ace532e9]"
    },
    "userName": "bjensen2",
    "emails": [
        {
            "verified": false,
            "primary": false,
            "secondary": false,
            "value": "[bjensen@example.com|mailto:bjensen@example.com]",
            "type": "recovery"
        },
        {
            "verified": false,
            "primary": true,
            "secondary": false,
            "value": "[bjensen@example.com|mailto:bjensen@example.com]",
            "type": "work"
        }
    ],
    "urn:ietf:params:scim:schemas:example:idcs:extension:userState:User": {
        "locked": {
            "on": false
        }
    },
    "name": {
        "familyName": "Jensen",
        "givenName": "Barbara",
        "formatted": "Barbara Jane Jensen",
        "middleName": "Jane"
    },
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User",
        "urn:ietf:params:scim:schemas:example:idcs:extension:userState:User"
    ]
}

Step 2: Get a User

This step shows how to retrieve a user by the user's ID by submitting a GET request on the REST resource using cURL. For more information about cURL, see Use cURL.

   curl
   -X GET
   -H "Content-Type:application/scim+json"
   -H "Authorization: Bearer <Access Token Value>"https://<domainURL>/admin/v1/Users/<user_ocid or user_id>
Note

The command in this example uses the URL structure https://<domainURL>/resource-path, where <domainURL> represents the Identity Service URL, and the resource path represents the Identity Service API. See Send Requests for the appropriate URL structure to use.

Example of Response Body

The following example shows the contents of the response body in JSON format:

{
    "displayName": "Barbara Jensen",
    "name": {
        "givenName": "Barbara",
        "formatted": "Barbara Jane Jensen",
        "middleName": "Jane",
        "familyName": "Jensen"
    },
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User": {
        "locked": {
            "on": false
        }
    },
    "userName": "bjensen@example.com",
    "id": "ff9a9207fc8c4fd2b3d76af84235e8fd",
    "active": true,
    "emails": [
        {
            "verified": "false",
            "value": "bjensen@example.com",
            "type": "recovery"
        },
        {
            "primary": true,
            "value": "bjensen@example.com",
            "type": "work"
        }
    ],
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User",
        "urn:ietf:params:scim:schemas:core:2.0:User"
    ],
    "meta": {
        "resourceType": "User",
        "created": "2022-07-13T07:28:59.227Z",
        "lastModified": "2022-07-13T07:28:59.227Z",
        "location": "http://<domainURL>/admin/v1/Users/ff9a9207fc8c4fd2b3d76af84235e8fd"
    },
    "idcsCreatedBy": {
        "value": "f8fa30db0f5f41f98de00bc07c05a73d",
        "$ref": "/OAuthClients/f8fa30db0f5f41f98de00bc07c05a73d",
        "type": "OAuthClient",
        "display": "admin"
    },
    "idcsLastModifiedBy": {
        "value": "f8fa30db0f5f41f98de00bc07c05a73d",
        "$ref": "/OAuthClients/f8fa30db0f5f41f98de00bc07c05a73d",
        "type": "OAuthClient",
        "display": "admin"
    }
}

Step 3: Initiate Self-Service Email Verification

This step shows how to initiate email validation of either the user's primary or recovery email address by submitting a PUT request on the REST resource using cURL. For more information about cURL, see Using cURL.

   curl
   -X PUT
   -H "Content-Type:application/scim+json"
   -H "Authorization: Bearer <Access Token Value>"https://<domainURL>/admin/v1/MeEmailVerifier

Example of Request Body

The following shows an example of a request body in JSON format:

{
    "email": "bjensen@example.com",
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:MeEmailVerifier"
    ],
    "id": "ff9a9207fc8c4fd2b3d76af84235e8fd",
    "userFlowControlledByExternalClient": true,
    "triggerEmailVerificationFlowIfEmailAlreadyVerified": true
}

Example of Response Body

The following example shows the contents of the response body in JSON format:

{
    "email": "bjensen@example.com",
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:MeEmailVerifier"
    ],
    "id": "ff9a9207fc8c4fd2b3d76af84235e8fd",
    "userFlowControlledByExternalClient": true,
    "triggerEmailVerificationFlowIfEmailAlreadyVerified": true,
    "meta": {
        "resourceType": "MeEmailVerifier",
        "location": "https://<domainURL>/admin/v1/MeEmailVerifier/57044ca14d274d789a586e5ec77c26f3"
    },
    "userToken": {
        "value": "db21a3578d27439ca9fab6349be46c30",
        "$ref": "https://<domainURL>/admin/v1/UserTokens/db21a3578d27439ca9fab6349be46c30"
    }
}

Step 4: Obtain a User Token

This step shows how to retrieve a user token using its ID by submitting a GET request on the REST resource using cURL. For more information about cURL, see Using cURL.

   curl
-X GET
   -H "Content-Type:application/scim+json"
   -H "Authorization: Bearer <Access Token Value>"https://<domainURL>/admin/v1/UserTokens/{{usertokenid}}

Example of Response Body

The following example shows the contents of the response body in JSON format:

{
    "expiryTime": "2022-07-13T07:28:59.227Z",
    "token": "KtXTrZkyIC2OWYVChbYEtfWnE7zhxlYJ0roEvsj0F2I=",
    "tokenType": "email",
    "userId": "5a7550ad5cfa4f50bdc608da1831481b",
    "data": "bjensen@example.com",
    "eventId": "admin.user.password.reset.success",
    "status": 0,
    "id": "3e4b69e99ddf472989e089a904a3c1a7",
    "meta": {
        "created": "2022-07-13T07:28:59.227Z",
        "lastModified": "2022-07-13T07:28:59.227Z",
        "resourceType": "UserToken",
        "location": "$baseUri/UserTokens/{id}"
    },
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:UserToken"
    ],
    "idcsCreatedBy": {
        "value": "14171fc6031a417cac680cdb9d82c2ea",
        "display": "admin",
        "type": "OAuthClient",
        "$ref": "$baseUri/OAuthClient/{id}"
    },
    "idcsLastModifiedBy": {
        "value": "14171fc6031a417cac680cdb9d82c2ea",
        "display": "admin",
        "type": "OAuthClient",
        "$ref": "$baseUri/OAuthClient/{id}"
    }
}

Step 5: Self-Verify Email Address

This step shows how to verify a new email address by submitting a POST request on the REST resource using cURL. This endpoint validates the token, and then marks the email address as verified. For more information about cURL, see Use cURL.

   curl
   -X POST
   -H "Content-Type:application/scim+json"
   -H "Authorization: Bearer <Access Token Value>"https://<domainURL>/admin/v1/MeEmailVerified

Example of Request Body

The following shows an example of a request body in JSON format:

{
  "token": "YzQwYTc4NmE5YmEzNGU4MDg0YjFkY2FhZWRmNThlOTc6TEFGaWtuTXI5OjIwMTUtMDctMjRUMDI6Mjk6NDEuNzEwWg==",
  "schemas": [
    "urn:ietf:params:scim:schemas:oracle:idcs:MeEmailVerified"
  ]
}

Example of Response Body

The following example shows the contents of the response body in JSON format:

{
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:extension:MeEmailVerified"
    ],
    "id": "5fed0efce51f40b4a42b0773a65178c3",
    "meta": {
        "resourceType": "MeEmailVerified",
        "location": "https://<domainURL>/admin/v1/MeEmailVerified/57044ca14d274d789a586e5ec77c26f3"
    }
}

Enrolling in MFA using the SMS Factor Using Self Service

This use case provides a step-by-step example of using the identity domains REST API for Self-Service enrollment in Multifactor Authentication (MFA) using SMS Factor.

Download the identity domains authentication use case examples collection and the global variables file from the idcs-rest-clients folder within the idm-samples GitHub repository and then import them into Postman.

As a prerequisite step, you must obtain a ME token before following these steps. See Generating Access Token Using Authentication API for information on obtaining a ME token.

Note

These steps assume that relevant factors of MFA are enabled using Configure Multifactor Authentication Settings.

Step1: Create the Self Service Enrollment Using the SMS Factor

This step initiates SMS enrollment in a POST request to the /admin/v1/MyAuthenticationFactorEnroller endpoint. The client must include the following attributes:

  • value: defines the user id. You can make a GET call to {{HOST}}/admin/v1/Me to get the "id" value.
  • displayName: defines the display name for the device
  • countryCode: defines the country code of the phone number where the SMS text will be sent
  • phoneNumber: defines the phone number where the SMS text will be sent

Request Example

The following example shows the contents of the POST request body in JSON format:

{
  "schemas": [
    "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorEnroller"
  ],
  "user": {
    "value": "c810ff4522eb437abac013291c1984d1"
  },
  "displayName": "Joe's Personal Phone",
  "countryCode": "+44",
  "phoneNumber": "1122334455",
  "authnFactors": [
    "SMS"
  ]
} 

Response Example

The following example shows the contents of the response body in JSON format:

{
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorEnroller"
    ],
    "user": {
        "value": "c810ff4522eb437abac013291c1984d1",
        "$ref": "https://example.identitycloud.com/admin/v1/Users/c810ff4522eb437abac013291c1984d1"
    },
    "displayName": "Joe's Personal Phone",
    "countryCode": "+44",
    "phoneNumber": "XXXXXXX455",
    "authnFactors": [
        "SMS"
    ],
    "meta": {
        "resourceType": "MyAuthenticationFactorEnroller",
        "location": "https://example.identitycloud.com/admin/v1/MyAuthenticationFactorEnroller"
    },
    "deviceId": "92142250e2ab4608b5c6532eb73e3d7c",
    "requestId": "a0a7f9bf-13a8-43f3-bcc7-2087dc3f7a18o-o1548346179"
}

In the response, the deviceId and the requestId should be passed in the next step.

Error Response Examples

The following example shows the error message in JSON format when the userId is invalid. You get a 400 HTTP response code.
{
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:Error",
        "urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error"
    ],
    "detail": "AuthenticationFactorEnroller.user references a User with ID 1fa35f74491d44ef5a7cc25bfdb1c8b1c that does not exist.",
    "status": "400",
    "urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error": {
        "messageId": "error.common.validation.invalidReferenceResource"
    }
}

The following example shows the error message in JSON format if a phoneNumber is incorrect. You get a 400 HTTP response code.

{
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:Error",
        "urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error"
    ],
    "detail": "Your phone number +91123 is not valid.",
    "status": "400",
    "urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error": {
        "messageId": "error.ssocommon.auth.invalidPhoneNumber",
        "additionalData": {
            "params": "+91123",
            "msgId": "error.ssocommon.auth.invalidPhoneNumber"
        }
    }
}

Step 2: Initiate the Self Service Enrollment Using the OTP by SMS

This step requests that the OTP be sent through SMS in a POST request to the /admin/v1/MyAuthenticationFactorInitiator endpoint. The client must include the following attributes:

requestId: received in the Step 1 response

deviceId: received in the Step 1 response

userName: username of the user

Request Example

The following example shows the contents of the POST request body in JSON format:

{
  "schemas": [
    "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorInitiator"
  ],
  "deviceId": "92142250e2ab4608b5c6532eb73e3d7c",
  "requestId": "a0a7f9bf-13a8-43f3-bcc7-2087dc3f7a18o-o1548346179",
  "userName": "jbloggs",
  "authFactor": "SMS"
}

Response Example

The following example shows the contents of the response in JSON format:

{
    "deviceId": "92142250e2ab4608b5c6532eb73e3d7c",
    "requestId": "a0a7f9bf-13a8-43f3-bcc7-2087dc3f7a18o-o1548346179",
    "authFactor": "SMS",
    "userName": "jbloggs",
    "displayName": "Joe's Personal Phone",
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorInitiator"
    ]
}

An OTP code is sent by using SMS to the user's mobile device. In the response deviceId and requestId should be passed in the next step.

2a. Initiate the Self Service Enrollment Request to Resend OTP by SMS

In case the user wants the server to "resend" the OTP, then same payload as mentioned in the Step 2 should be sent to the server again.

Request Example

The following example shows the contents of the POST request body in JSON format:

{
  "schemas": [
    "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorInitiator"
  ],
  "deviceId": "92142250e2ab4608b5c6532eb73e3d7c",
  "requestId": "a0a7f9bf-13a8-43f3-bcc7-2087dc3f7a18o-o1548346179",
  "userName": "jbloggs",
  "authFactor": "SMS"
}

Response Example

The following example shows the contents of the response in JSON format:

{ 
    "deviceId": "92142250e2ab4608b5c6532eb73e3d7c",
    "requestId": "a0a7f9bf-13a8-43f3-bcc7-2087dc3f7a18o-o1548346179",
    "authFactor": "SMS",
    "userName": "jbloggs",
    "displayName": "Joe's Personal Phone",
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorInitiator"
    ]
}

An OTP code is sent using SMS to the user's mobile device. In the response deviceId and requestId should be passed in the next step.

Step 3: Validate the Self Service Enrollment Using the OTP

This step validates the SMS enrollment of a user in a POST request to the /admin/v1/MyAuthenticationFactorValidator endpoint.

The client must include the following attributes:

  • otpCode: the code received by the user on their device
  • requestId: received in the Step 2 response
  • deviceId: received in the Step 2 response

Request Example

The following example shows the contents of the POST request in JSON format:

{
  "schemas": [
    "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorValidator"
  ],
  "deviceId": "92142250e2ab4608b5c6532eb73e3d7c",
  "requestId": "a0a7f9bf-13a8-43f3-bcc7-2087dc3f7a18o-o1548346179",
  "otpCode": "191224",
  "authFactor": "SMS",
  "scenario": "ENROLLMENT"
}
    

Response Example

The following example shows the contents of the response in JSON format:

{
    "authFactor": "SMS",
    "deviceId": "92142250e2ab4608b5c6532eb73e3d7c",
    "requestId": "a0a7f9bf-13a8-43f3-bcc7-2087dc3f7a18o-o1548346179",
    "scenario": "ENROLLMENT",
    "status": "SUCCESS",
    "displayName": "Joe's Personal Phone",
    "schemas": [
        "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorValidator"
    ],
    "mfaStatus": "ENROLLED",
    "mfaPreferredDevice": "2b27b8c072d64b899d41c8470acea32a",
    "mfaPreferredAuthenticationFactor": "SMS",
    "securityQuestionsPresent": false,
    "devicesCount": 3,
    "emailFactorEnrolled": true
} 
In the response, the attribute mfaStaus:"ENROLLED" indicates that user has enrolled for MFA. The mfapreferredAuthenticationFactor attribute indicates the factor set as the preferred method. In this case, it's SMS.
Note

This value may be different, if the first enrolled factor is different from SMS.

Error Response Examples

The following example shows the error message in JSON format if OTP is incorrect. You get a 401 HTTP response code and the enrollment fails.

{
  "schemas": [
    "urn:ietf:params:scim:api:messages:2.0:Error",
    "urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error"
  ],
  "detail": "Invalid passcode.",
  "status": "401",
  "urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error": {
    "messageId": "error.ssocommon.auth.invalidPasscode"
  }
}

Resetting Authentication Factors for Multiple Users Using The Bulk Endpoint

You can use the Bulk endpoint to reset the authentication factors for up to 40 users at a time using a POST call.

Sample Request

curl
-X POST
-H "Content-Type:application/scim+json"
-H "Authorization: Bearer <Access_Token>"
https://<domainURL>/admin/v1/Bulk

Sample Payload

{
   "schemas": [
      "urn:ietf:params:scim:api:messages:2.0:BulkRequest"
   ],
   "Operations": [
      {
         "method": "POST",
         "path": "/AuthenticationFactorsRemover",
         "bulkId": "<bulkid1>",
         "data": {
            "schemas": [
               "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorsRemover"
            ],
            "user":
{                "value": "<user_1_id>"             }
         }
      },
      {
         "method": "POST",
         "path": "/AuthenticationFactorsRemover",
         "bulkId": "<bulkid2>",
         "data": {
            "schemas": [
               "urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorsRemover"
            ],
            "user":
{                "value": "<user_2_id>"             }
         }
      }
   ]
}

Using the onBehalfOf Allowed Operation

The onBehalfOf allowed operation provides a way to ensure that access privileges can be generated from the user's privileges alone, so that a client application can access endpoints to which the user has access, even if the client application by itself wouldn't normally have access.

When an authorized client application implements functionality that requires it to access identity domains endpoints, that client is granted the necessary privileges to do so. A web application client, on the other hand, implements functionality that requires the client application to access endpoints using the privileges and scopes acquired from the logged-in user. With identity domains default authorization behavior, that client must still have the full set of privileges required to access those endpoints without regard to the privileges granted to the user. The onBehalfOf allowed operation provides an administrator a way to indicate that the user's privileges alone should be used rather than an intersection of the user's scopes (if a user is present) and the client's scopes.

Public or CLI applications have very limited privileges or no privileges to access endpoints. These types of clients rely on the user who is accessing the application to drive what rights the application has. When a user is accessing a public application, if the user was issued an access token that's constructed from the user's privileges alone, that user would be able to access the endpoints as long as the user is authorized.

The onBehalfOf allowed operation enables you to generate such an access token for the OAuth Client application. When computing the identity domains specific scopes (scopes that begin with "urn:opc:idm:") to set in the access token, identity domains ignores the client's privileges and uses a scope equal to or less than the scope originally granted to the authorized user. So, only the user's privileges (admin roles, groups, and so on) in conjunction with the requested scopes are used to determine access. If the requested scope "urn:opc:idm:_myscopes_" is used, then all scopes that are granted to the user are returned.

Enabling the onBehalfOf Allowed Operation

Use the identity domains REST API to create or update an OAuth application, and specify onBehalfOfUser as an allowed operation. When you create an OAuth application using the identity domains UI, on the Authorization page, select the checkbox for the On behalf Of allowed operation. When users access the application, they can perform various functions based on their permissions.

Example

The example shows how to create an application and specify the onBehalfOfUser allowed operation (in bold in the example).

cat</tmp/OAuthClientApp.json << __EOF__
{
  "schemas": [
    "urn:ietf:params:scim:schemas:oracle:idcs:App"
  ],
  "displayName": "publicClientApp",
  "isOAuthClient": true,
  "description": "public client",
  "active": true,
  "clientType": "public",
  "basedOnTemplate": {
    "value": "CustomBrowserMobileTemplateId"
  },
  "redirectUris": [
    "http://example.com:9090/demoapp/return",
    "http://example.com:9090/IDCSPlayground"
  ],
  "logoutUri": "http://example.com:9090/demoapp/logout.jsp",
  "postLogoutRedirectUris": ["http://example.com:9090/demoapp/logout.jsp"],
  "allowedScopes": [
    {
      "fqs": "http://example.com/photos"
    },
    {
      "fqs": "http://example.com/presentations"
    },
    {
      "fqs": "http://example.com/documents"
    }
  ],
  "allowedOperations": [
    "onBehalfOfUser"   ],
  "allowedGrants": [
    "authorization_code",
    "implicit"
  ]
}
__EOF__
   
curl -X POST 
-H "Content-type: application/json" 
-H "Authorization: Bearer <access token value>" 
--data @/tmp/OAuthClientApp.json http://<domainURL>/admin/v1/Apps

Using the Audit Event APIs

Identity domains Audit Events REST endpoints enable you to get Audit logs covering significant events, changes, or actions. Using these APIs, you can integrate all Security Information and Event Management (SIEM), User and Entity Behavior Analytics (UEBA), and Cloud Access Security Broker (CASB) to poll Audit data.

Note

Identity domains AuditEvents and certain reports templates in the Reports APIs will stop returning new data after December 15, 2024. Instead, you can use the OCI Audit service to get this data. To view service change announcements for IAM, see IAM Service Change Announcements.

Audit events enable you to review the actions performed by members of your organization using details provided by the Audit logs, such as who performed the action and what the action was. Identity domains is the central point of control for all activities happening in the system. It generates audit data in response to all administrator and end-user operations, such as User Login, Application Access, Password Reset, User Profile Update, CRUD operations on Users, Group, Applications, and so on.

Note

Audit event-related dates and times use the Coordinated Universal Time (UTC) format: YYYY-MM-DDThh:mm:ss.mscZ. For example, 2022-03-24T10:24:24.022Z.

Comprehensive reports can be generated from many administrator and user activities, such as those on the left side of the diagram. Represented on the right side are examples of the historical user activity that you can capture and the statistics and analytics that you can generate by importing data into analytics tools.

Audit Examples

Audit examples are available to help get you up to speed. After you import the collection, type "audit" in the filter to find all the audit requests. Download the identity domains authentication use case examples collection and the global variables file from the idcs-rest-clients folder within the idm-samples GitHub repository and then import them into Postman.

Identity Domains Audit Events

This table provides Event IDs of some of the most crucial events in identity domains.

Event Category Event Event ID

Single Sign-On

User Logins Success

sso.session.create.success

Single Sign-On

User Logins Failure

sso.authentication.failure

Application Access Events

Application Access Success

sso.app.access.success

Application Access Events

Application Access Failure

sso.app.access.failure

Multifactor Authentication

Step-up authentication for User

sso.auth.factor.initiated

Multifactor Authentication

ByPass Code Creation

sso.bypasscode.create.success

Multifactor Authentication

ByPass Code Deletion

sso.bypasscode.delete.success

Self-Registration

User Self-Registration success

admin.me.register.success

Self-Service Access Request

Access Request Success

admin.myrequest.create.success

Notifications

Notification Delivery success

notification.delivery.success

Notifications

Notification Delivery Failure

notification.delivery.failure

Identity Bridge Sync

ID Bridge Sync Success

idbridge.sync.success

Identity Bridge Sync

ID Bridge Sync Failure

idbridge.sync.failure

Forgot/Reset Password

Password Reset success

admin.me.password.reset.success

Reset Password Initiated by Administrator

Password Reset success

admin.user.password.reset.success

Change Password

Password Change Success

admin.me.password.change.success

Change Password

Password Change Failure

admin.me.password.change.failure

User CRUD Operations

User Create Success

admin.user.create.success

User CRUD Operations

User Activate Success

admin.user.activated.success

User CRUD Operations

User Update Success

admin.user.update.success

User CRUD Operations

User Delete Success

admin.user.delete.success

Group CRUD Operations

Group Create Success

admin.group.create.success

Group CRUD Operations

Group Update Success

admin.group.update.success

Group CRUD Operations

Group Delete Success

admin.group.delete.success

Group CRUD Operations

Group Membership Assignment

admin.group.add.member.success

Group CRUD Operations

Group Membership Removal

admin.group.remove.member.success

Application CRUD Operations

Application Create

admin.app.create.success

Application CRUD Operations

Application Update

admin.app.update.success

Application CRUD Operations

Application Delete

admin.app.delete.success

User Provisioning

Successful User Provisioning

admin.account.create.success

User Provisioning

Unsuccessful User Provisioning

admin.account.delete.success

Event Resources

The following table describes crucial event resources.

Event Resource Description

eventID

Event ID as defined by the identity domains components

actorName

Username (login name) from the security context

actorDisplayName

User display name from the security context

actorId

User GUID from the security context

actorType

The actor type, either User or Client

ssoSessionId

Cloud SSO identifier

ssoIdentityProvider

SSO Identity Provider

ssoAuthFactor

The Authentication Factor used for authentication

ssoApplicationId

Application identifier GUID

ssoApplicationType

SSO Application Type: Application Type indicates whether the application is an OPC or a NonOPC application and whether the type is SAML, OAuth, or Secure Form Fill based on the protocol.

clientIp

IP address of the client application that's making the request

ssoUserAgent

User's device information

ssoPlatform

Platform used to perform authentication

ssoProtectedResource

Protected resource URI (Resource host, port, and context)

ssoMatchedSignOnPolicy

Matched Sign-On Policy, added in version18.1.2

Message

Message for event-specific success or failure

Timestamp

Timestamp of when the event occurred

Audit Schema

You can find the Audit Schema using the identity domains REST API. The Audit Schema contains all the information discussed in the tables of this use case.

Example Request

Perform a GET on the /Schemas endpoint using the AuditEvent schema.

GET <domainURL>>/admin/v1/Schemas/urn:ietf:params:scim:schemas:oracle:idcs:AuditEvent

Example Response Snapshot

The following is a snapshot of the response.

{
    "attributes": [
        {
            "caseExact": false,
            "description": "Unique URI of the schema",
            "idcsDisplayName": "ID",
            "idcsSearchable": true,
            "multiValued": false,
            "mutability": "readOnly",
            "name": "id",
            "required": true,
            "returned": "always",
            "type": "string",
            "uniqueness": "global"
        },
        {
            "caseExact": false,
            "description": "An identifier for the Resource as defined by the Service Consumer. The externalId may simplify identification of the Resource between Service Consumer and Service Provider by allowing the Consumer to refer to the Resource with its own identifier, obviating the need to store a local mapping between the local identifier of the Resource and the identifier used by the Service Provider. Each Resource MAY include a non-empty externalId value. The value of the externalId attribute is always issued by the Service Consumer and can never be specified by the Service Provider. The Service Provider MUST always interpret the externalId as scoped to the Service Consumer's tenant.",
            "idcsDisplayName": "External ID",
            "idcsSearchable": false,
            "multiValued": false,
            "mutability": "readWrite",
            "name": "externalId",
            "required": false,
            "returned": "default",
            "type": "string",
            "uniqueness": "none"
        },
        {
            "caseExact": true,
            "description": "Event correlation ID (ECID) correlating a chain of events as belonging to the same business operation (root task). ECID is generated when the request enters the IDCS web tier.",
            "idcsDisplayName": "Execution Context Id",
            "idcsSearchable": true,
            "multiValued": false,
            "mutability": "readWrite",
            "name": "ecId",
            "required": false,
            "returned": "default",
            "type": "string",
            "uniqueness": "none"
        },
        {
            "caseExact": true,
            "description": "Relationship Identifier (RID). This value indicates the position of a particular event/sub-operation within the tree of tasks that begins with the root task.",
            "idcsDisplayName": "Relationship Id",
            "idcsSearchable": true,
            "multiValued": false,
            "mutability": "readWrite",
            "name": "rId",
            "required": false,
            "returned": "default",
            "type": "string",
            "uniqueness": "none"
        },
        {
            "caseExact": false,
            "description": "Timestamp of when the event occurred, provided by the Event Manager (not supplied by clients)",
            "idcsDisplayName": "Timestamp",
            "idcsSearchable": true,
            "multiValued": false,
            "mutability": "readWrite",
            "name": "timestamp",
            "required": false,
            "returned": "default",
            "type": "dateTime",
            "uniqueness": "none"
        },