Log in with username and certificates

Your client application will be authorized to access Responsys's REST APIs.

Instead of using a password, a server and a client certificate can be used for authenticating with a username. Logging in with certificates is based on the use of a digital certificate in accordance with the X.509 standard for public key infrastructure (PKI).

Before you can use this type of login in a client application, the Oracle Responsys account administrator must log in to the Oracle Responsys user interface and navigate to the admin console for managing users. From the console, the admin must enable the API user to use certificates, upload a digital certificate (client user public key), and download the Responsys API server digital certificate (server public key).

Performing this type of authentication requires two REST API calls, as described in the steps below. To see authentication with certificates illustrated, refer to the example script at the bottom of this topic.

  1. Authenticate server by sending the following REST request:

    Important Note: For security reasons you must pass username and password as parameters in the POST request body only with the correct content type ('Content-Type': 'application/x-www-form-urlencoded'). Therefore, you must NOT use the URL string for passing in the authentication credentials.

    Service URL: /rest/api/v1.3/auth/token

    Request Method: POST

    Request Header: Content-Type: application/x-www-form-urlencoded

    Request Body Parameters: Send the following in the message body, x-www-form-urlencoded:
    
    user_name=<USER_NAME>
    auth_type=server
    client_challenge=<CLIENT_CHALLENGE_VALUE>
    				

    For REST, the client_challenge value must be a plain random number and/or text string of your choice, which you must first convert to byte, and then Base64 encode the byte.

  2. You should receive the following response from the server. Decrypt (using the RSA algorithm) the encrypted clientChallenge using server certificate's public key (which you should have downloaded and stored on your system). If they match, proceed to the next step. If they don't match, please do not proceed with steps 3 and 4 below. Instead contact Oracle Support.
    Response:
    
    {
    	"authToken" : "<TEMP_AUTH_TOKEN>",
    	"serverChallenge" : "<BASE_64_ENCODED_SERVER_CHALLENGE>",
    	"clientChallenge" : "<ENCRYPTED_AND_THEN_BASE_64_ENCODED_CLIENT_CHALLENGE>"
    }
    				
  3. Log in with username and certificate by sending the following REST request (do the encryption using the public key from the Responsys server certificate):

    Service URL: /rest/api/v1.3/auth/token

    Request Method: POST

    Request Header:
    • Authorization: <TEMP_AUTH_TOKEN> (obtained from the response shown above)
    • Content-Type: application/x-www-form-urlencoded
    Request Body Parameters: Send the following in the message body, x-www-form-urlencoded:
    
    user_name=<USER_NAME>
    auth_type=client
    server_challenge=<SERVER_CHALLENGE_ENCRYPTED_USING_CLIENT_USER_PRIVATE_KEY>
    				
  4. You should receive the following response from the server. You can use this authentication token and endpoint until the token expires (3 hours from issue time) or until you refresh the token and receive a new one.
    Response:
    
    {
    	"authToken" : "<AUTH_TOKEN>",
    	"issuedAt" :  <TIMESTAMP>,
    	"endPoint" : "<ENDPOINT_URI>"            
    }
    				

Example: Authentication with Certificates

The following example snippet illustrates the process for authentication with username and certificates.


	private void loginWithCertificate() {

        String username = getUserInput("Username : ");
        byte[] clientChallengeBytes = String.valueOf(new Random().nextLong()).getBytes();
        String encodedClientChallenge = Base64.encodeBase64URLSafeString(clientChallengeBytes);

        MultiValueMap<String, String> requestParams = new LinkedMultiValueMap<String, String>();
        requestParams.add("user_name", username);
        requestParams.add("auth_type", "server");
        requestParams.add("client_challenge", encodedClientChallenge);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(
                requestParams, headers);

        ServerChallengeResponse challengeResponse = null;
        try {
            challengeResponse = invokeApiWithPost(RestApi.LOGIN_CERT_SVR, requestEntity,
                    ServerChallengeResponse.class);
        }
        catch (RestServiceException e) {
            sop("************************************");
            sop("Authenticate Server Failed");
            sop("************************************");
            sop("Error Code: " + e.getError().toString() + "\r\nError: "
                    + e.getError().getErrorMessage() + "\r\nDetail : " + e.getMessage());
            return;
        }

        byte[] encryptedClientChallengeBytes = Base64.decodeBase64(challengeResponse
                .getClientChallenge());
        byte[] serverChallengeBytes = Base64.decodeBase64(challengeResponse.getServerChallenge());

        String serverCertName = getUserInput("Enter the name & location of the server certificate : ");
        File certFile = new File(serverCertName);
        if (!certFile.exists()) {
            sop("Server certificate doesn't exist in that location");
            return;
        }

        X509Certificate serverCertificate = null;

        try {
            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
            serverCertificate = (X509Certificate) certFactory
                    .generateCertificate(new FileInputStream(certFile));

            Cipher decryptCipher = Cipher.getInstance("RSA");
            decryptCipher.init(Cipher.DECRYPT_MODE, serverCertificate.getPublicKey());
            byte[] decryptedClientChallengeBytes = decryptCipher
                    .doFinal(encryptedClientChallengeBytes);

            // Compare the clientChallenge with decryptedClientChallenge.
            boolean serverValidated = Arrays.equals(clientChallengeBytes,
                    decryptedClientChallengeBytes);

            if (serverValidated) {
                sop("Server response validation 'PASSED' ... proceeding further to login to REST service");
            }
            else {
                sop("Server response validation 'FAILED'");
                return;
            }
        }
        catch (Exception e) {
            sop("Could not process with the ceritificate : " + e.getMessage());
            return;
        }
        // Get the private key of the client certificate
        PrivateKey privateKey = getPrivateKeyForClientCertificate();
        if (privateKey == null) {
            sop("Couldn't get private key from the client certificate");
            return;
        }

        byte[] encryptedServerChallengeBytes = null;

        try {
            Cipher encryptCipher = Cipher.getInstance("RSA");
            encryptCipher.init(Cipher.ENCRYPT_MODE, privateKey);
            encryptedServerChallengeBytes = encryptCipher.doFinal(serverChallengeBytes);
        }
        catch (Exception e) {
            sop("Couldn't encrypt server challenge : " + e.getMessage());
            return;
        }

        requestParams = new LinkedMultiValueMap<String, String>();
        requestParams.add("user_name", username);
        requestParams.add("auth_type", "client");
        requestParams.add("server_challenge",
                Base64.encodeBase64URLSafeString(encryptedServerChallengeBytes));

        headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Authorization", challengeResponse.getAuthToken());

        requestEntity = new HttpEntity<MultiValueMap<String, String>>(requestParams, headers);

        LoginResponse loginResponse = null;
        try {
            loginResponse = invokeApiWithPost(RestApi.LOGIN_CERT_CL, requestEntity,
                    LoginResponse.class);
        }
        catch (RestServiceException e) {
            sop("************************************");
            sop("Login with ceritficate : FAILED");
            sop("************************************");
            sop("Error Code: " + e.getError().toString() + "\r\nError: "
                    + e.getError().getErrorMessage() + "\r\nDetail : " + e.getMessage());
        }

        if (loginResponse != null) {
            String restEndPoint = loginResponse.getEndPoint();
            if (!isEmpty(restEndPoint)) {
                sop("************************************");
                sop("Login with ceritficate : PASSED");
                sop("************************************");
                this.svcEndPoint = restEndPoint;
                this.token = loginResponse.getAuthToken();
            }
            else {
                sop("************************************");
                sop("Login with user/pwd : FAILED");
                sop("************************************");
                sop("Error: RestEndPoint has not been defined for this ARG."
                        + "Please check REST API settings in PodConfig.ini.");
            }
        }
    }