Authenticating with an External SAML Identity Provider

This use case discusses the steps to use Oracle Identity Cloud Service to authenticate using an external SAML Identity Provider (IdP).

Note:

Use this Authenticate API only if you're building your own end-to-end login experience by developing a custom sign-in application to be used by Oracle Identity Cloud Servcice.

Note:

This Authenticate API can't be used to integrate your applications with Oracle Identity Cloud Service for single sign-on purposes.

Note:

See the Oracle Identity Cloud Service Authentication API Postman collection for extensive authentication use case examples. Download the collection and the global variables file from the idcs-authn-api-rest-clients folder within GitHub and then import them into your preferred REST Client.
There are two steps in this use case. Each step contains request and response examples::

Step 1: Begin the Authentication Flow

A user opens a browser window to access a protected page.

In the background, the request to authenticate is intercepted by Oracle Identity Cloud Service and redirected to the /authorize endpoint. This begins the authentication process. Instead of presenting the default sign-in page, Oracle Identity Cloud Service responds by creating and submitting an HTML form that contains the loginCtx and signature parameters to the browser.

Note:

You must expose an endpoint to receive the form post and read the two parameter values.

Example HTML Form POST

The following is an example HTML Form POST that Oracle Identity Cloud Service returns to invoke the custom sign-in page:

<form name="autosubmit" id="autosubmit" action="<custom_ui_signin_URL>" method="POST" onload="submitform();">
     <input name="loginCtx" value="<obfuscated_loginctx_value>" />
     <input name="signature" value="signature_data" />
</form>
The browser receives the HTML code, which contains JavaScript to automatically submit the form to the custom sign-in page. Since the loginCtx parameter is based64 encrypted, the custom sign-in app must decrypt the loginCtx by doing the following:
  • Decode using a base64 decorder to get the encrypted binary data
  • Use the tenant name and generate a key for decryption
  • Decrypt the data using the key and binary data

Example Decryption Logic for Encrypted loginCtx in Java

The following is example decryption logic:

public static String decrypt(String tenantName, String attrName, String attrDecryptValue ) {
        String attrDecrypt = attrDecryptValue;
        final String SHA_256_ALG = "SHA-256";
        final String ENCRYPTION_ALG = "AES/CBC/PKCS5Padding";
        final String SECRET_KEY_ALG = "AES";
        String data = null;
        MessageDigest md = null;
        byte[] keyBytes = new byte[16];
        try {
            md = JCECryptoCache.getMessageDigestInstance(SHA_256_ALG);
            byte[] digest = md.digest(tenantName.toLowerCase().getBytes("UTF-8"));
            System.arraycopy(digest, 0, keyBytes, 0, 16);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            JCECryptoCache.releaseMessageDigestInstance(md);
        }
 
        // encrypt the data
        Cipher decipher = null;
        try {
            decipher = JCECryptoCache.getCipherInstance(ENCRYPTION_ALG);
            SecretKey secretKey = new SecretKeySpec(keyBytes, SECRET_KEY_ALG);
            decipher.init(Cipher.DECRYPT_MODE,
                    secretKey, new IvParameterSpec(new byte[16]));
            byte[] decryptedData = decipher.doFinal(Base64.getDecoder().decode(attrDecrypt.getBytes("UTF-8")));
            data = new String(decryptedData);
            System.out.println("" + data);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return data;
    }

Response Example

The response should be similar to the following example:

{
  "requestState": "TasNtIxDqWOfDKeTM",
  "nextOp": [
    "credSubmit",
    "chooseIDP"
  ],
  "nextAuthFactors": [
    "IDP",
    "USERNAME_PASSWORD"
  ],
  "status": "success",
  "ecId": "GmY95180000000000",
  "USERNAME_PASSWORD": {
    "credentials": [
      "username",
      "password"
    ]
  },
  "IDP": {
    "configuredIDPs": [
      {
        "iconUrl": "null",
        "idpName": "adc00peq",
        "idpType": "Saml"
      },
      {
        "idpId": "4bb89888feea4b00a0fab3a1a5627539",
        "idpName": "Google",
        "idpType": "Social"
      }
    ],
    "credentials": [
      "idpId",
      "idpType"
    ]
  }
}
The loginCtx parameter contains some important attributes:
  • requestState: The state of the authentication process. It needs to be used in future POSTs and GETs to Oracle Identity Cloud Service's Authentication API endpoints.
  • nextOp: The next operation the custom sign-in application must perform.
  • nextAuthFactors: The possible authentication factors the sign-in page must present.

The values of these attributes define which authentication factor, identity providers, and social providers are presented on the sign-in page. The sign-in page appears containing the decrypted values of the loginCtx parameter along with the access token. The sign-in page includes JavaScript that is used to perform AJAX calls to Oracle Identity Cloud Service.

Step 2: Select a SAML Identity Provider

The user selects the external SAML IdP that they want to use to authentication from the custom sign-in page that appears. The custom sign-in page must construct and then submit the required information for the selected IdP as an HTML FORM POST to the /sso/v1/sdk/idp endpoint. For this step, the following attributes must be included:
  • requestState: received in the Step 1 response
  • idpName: name of the IdP received in the Step 1 response
  • idpType: type of IdP received in the Step 1 response (in this example, it is SAML)
  • idpId: id of the IdP received in the Step 1 response
  • appName: name of the app that the client wants access to
  • clientID: client ID of the application the browser is attempting to access
  • authorization: parameter required for secure Idp

Example HTML Form POST Code to Select a SAML IdP

The following JavaScript example shows how to select the SAMlL IdP:
var addParamValues = function(myform, value, paramName) {
    if (value !== null && value !== 'undefined') {
        param = document.createElement("input");
        param.value = value;
        param.name = paramName;
        myform.appendChild(param);
    }
};
 
var chooseRemoteIDP = function(name, idpId, type) {
    var myform = document.createElement("form");
    myform.action = GlobalConfig.idcsBaseURL + "/sso/v1/sdk/secure/idp";
    myform.method = "post";
    <%
        Credentials creds = CredentialsList.getCredentials().get(attr);
        String clientId = creds.getId();
    %>
    var clientId = '<%=clientId%>';
    addParamValues(myform, name, "idpName");
    addParamValues(myform, type, "idpType");
    addParamValues(myform, idpId, "idpId");
    addParamValues(myform, clientId, "clientId");
    addParamValues(myform, authorization, "accesstoken")
    addParamValues(myform, GlobalConfig.requestState, "requestState");
    document.body.appendChild(myform);
    myform.submit();
};
 
var activateIdp = function(name, idpId) {
    chooseRemoteIDP(name, idpId, "SAML");
};
 
var activateSocialIdp = function(name, idpId) {         
    chooseRemoteIDP(name, idpId, "SOCIAL");
};

Request Example

The following is an example of the contents of the FORM POST to the /sso/v1/sdk/secure/idp endpoint:

requestState=value&idpName=value&idpType=SAML&idpId=value&appName=name&clientID=value&authorization=accesstoken

Response Example

The following example shows the contents of the response in standard HTTP format:

HTTP/1.1 302 See Other
Date: Tue, 30 Oct 2018 04:40:05 GMT
Content-Length: 0
Connection: keep-alive
Pragma: no-cache
Location: https://tenant-base-url/idp/sso (Example URL)
Set-cookie: ORA_OCIS_REQ_1=+fxgW2P7bgQayiki5P;Version=1;Path=/;Secure;HttpOnly
Expires: Sat, 01 Jan 2000 00:00:00 GMT
X-xss-protection: 1; mode=block
X-content-type-options: nosniff

Oracle Identity Cloud Service processes the request and redirects the browser to the selected external IdP for authentication and authorization. When the external IdP is finished, the browser is redirected to Oracle Identity Cloud Service. Oracle Identity Cloud Service validates the assertion response and checks if additional authentication such as MFA is required.

If additional authentication isn't required, then Oracle Identity Cloud Service creates the session and redirects the browser to the target URL. Or, Oracle Identity Cloud Service creates an HTML auto submit FORM POST to the custom sign-in page that contains the authnToken. The custom sign-in page then creates the session. See Creating a Session.