Authenticating with User Name and Password and MFA and Return an OTP
This use case provides a step-by-step example of using the Oracle Identity Cloud Service Authentication API to authenticate with a user's credentials and Multi-Factor Authentication (MFA) and to return an encrypted OTP in the response.
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 Service.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 AUTHN-API Return Passcode.postman_collection.json collection and the global variables file from the idcs-authn-api-rest-clients folder within GitHub and then import them into Postman.Oracle Identity Cloud Service can be configured to send a time-based one-time passcode (OTP) to directly to a user for authentication or have the passcode encrypted and sent to the consuming client who can then send it to the user for authentication.
For example, administrators can configure Oracle Identity Cloud Service to send time-based one-time passcodes (OTP) to the Oracle Mobile Authenticator (OMA) app or email the OTPs to the user's primary email address. In both cases, Oracle Identity Cloud Service generates the OTP, sends it directly to the user and the user enters the code for authentication. To understand how to set these options using REST, see Authentication Factor Enrollment With Factor Verification - SMS and Authentication Factor Enrollment With Factor Verification - Email.
-
Step 1: Create a CustomUI Application
-
Step 2: Generate a Key Pair a Self-Signed Certificate
-
Step 3: Configure the Application to Return the OTP in the Response
-
Step 4: Request the OTP
Note:
These steps assume that MFA is enabled and a sign-on policy is created for MFA. See Configuring Multi-Factor Authentication Settings.Encryption and Decryption
This implementation uses the following specification to encrypt and decrypt the OTP code received. See PKCS #1: RSA Cryptography Specifications, Version 2.0, section 7.1 RSAES-OAEP.
OTP Decryption Code
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package decryption;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;
/**
*
* @author <author>
*/
public class DecryptOtpCode {
private static Key getPrivateKey(String privateKeyPEM) throws Exception {
byte[] encoded = Base64.getDecoder().decode(privateKeyPEM);
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
return kf.generatePrivate(keySpec);
}
public static void main(String args[]) {
String value = "<encrypted_value>";
String privatekey =
"<pem_privatekey_data>";
try {
Cipher cipherInstance =
Cipher.getInstance("RSA/ECB/OAEPwithSHA1andMGF1Padding");
CertificateFactory factory = CertificateFactory.getInstance("X.509");
byte [] decoded = Base64.getDecoder().decode(value);
PrivateKey pKey = (PrivateKey)getPrivateKey(privatekey);
cipherInstance.init(Cipher.DECRYPT_MODE, pKey);
byte[] decrypted = cipherInstance.doFinal(decoded);
System.out.println("Decrypted text is " + new String(decrypted));
} catch (Exception e) {
//Unable to encrypt the content. Default to send the otp to user
//no error or exception thrown.
e.printStackTrace();
}
}
}
Step 1: Create a CustomUI Application
See Add Applications for more information about custom applications.
Step 2: Generate a Key Pair a Self-Signed Certificate
- Use the following command to generate a private key.
[ req ] encrypt_key = no default_bits = 2048 default_md = sha256 utf8 = yes string_mask = utf8only prompt = no distinguished_name = user_dn [ user_dn ] 0.organizationName = "Oracle" organizationalUnitName = "OCI" commonName = "OtpClient"
-
Use the following command to generate a self-signed certificate.
#generate self signed client certificate openssl genrsa -out OtpClient.key 2048 openssl req -new -x509 -days 10000 -key OtpClient.key -out OtpClient.crt -subj "/CN=Root CA/C=IN/ST=KarnatakaCalifornia/L=Bangalore/O=Oracle" -config otp-client.conf openssl pkcs8 -topk8 -inform PEM -in OtpClient.key -out OtpClientX509Format.key -nocrypt
Step 3: Configure the Application to Return the OTP in the Response
- In the Identity Cloud Service console, expand the Navigation Drawer, click Applications, CustomUI application, Configuration, and then Client Configuration.
- Import the self-signed certificate in the Trusted Client Certificate and Save the configuration.
Step 4: Request the OTP
Attribute | Supported Values / Sample Values | Multi-Valued | Usage Details |
---|---|---|---|
userFlowControlledByExternalClient |
true / false | false |
Set this option to
and the OTP will be returned in the response in the encrypted format specified.
Note: The certificate used for encryption is uploaded to the application in advance and is referred using the |
x5t | String / X509 SHA-1 Certificate Thumbprint | When specified, the service uses this uploaded certificate to encrypt the OTP data. Note: The "x5t" attribute should match the uploaded certificate. |
{
"op": "credSubmit",
"credentials": {
"username": "test.user",
"password": "Welcome@1"
},
"userFlowControlledByExternalClient": true,
"x5t": "<certificate thumbprint>",
"requestState": "{{requestState}}"
}
Attribute | Supported Values / Sample Values | Multi-Valued | Usage Details |
---|---|---|---|
otp |
Map
|
false | When present in the response, the attribute contains the encrypted OTP with following details.
|
Response Example
{
"otp": {
"value": "IMsNO+rqNCw==",
"alg": "RSAES-OAEP",
"x5t": "<certificate thumbprint>"
},
"status": "success",
"ecId": "Ft^OD161000000000",
"displayName": "+91XXXXXXXX013",
"nextAuthFactors": [
"SMS"
],
"SMS": {
"credentials": [
"otpCode"
]
},
"nextOp": [
"credSubmit",
"getBackupFactors",
"resendCode"
],
"scenario": "AUTHENTICATION",
"requestState": "FrrACc",
"trustedDeviceSettings": {
"trustDurationInDays": 15
}
}