X

Best Practices from Oracle Development's A‑Team

Authentication and User Propagation for API Calls

Olaf Heimburger
A-Team Cloud Solution Architect

Introduction

Many of the modern computer applications use a technology that is as old as the Roman Empire: this technology is user identitification by user name and pass word. It is used at the front end, the user interfaces, as well as the back end when computer applications exchange information between each other. It is a well-understood technology with well-understood benefits and issues. The biggest issues are password and identity theft or simpler ones like password distribution or password expiry. The simpler problems can lead to the bigger ones: one expired or not updated password can break a big infrastructure and one stolen password can lead into a big data breach. The first happen regularly, say every 90 days, but the second can happen unnoticed for a small or larger period.

To prevent these problems and better protect your architecture from failure or data leakage a better technology is required that allows authentication with better confidence, more security, and better usability. This approach should be flexible and support user propagation, even if the application does not have any knowledge of the user's credentials.

Background

When a user starts working with an application, she authenticates herself, for example by providing her username and password. When the information she provided is correct the application grants access and allows her to work with it. Within the application her identity is well-known, but the authentication details, i.e., the credentials, are usually not present or stored in the application. When the application needs to call out to a partner application which requires the user identity, the challenge starts. The current application knows the user identity but does not have the full authentication details which are required to authenticate with the partner application. To allow the application to get access to the partner application, we need a way to authenticate the user with this partner application without knowing the authentication details. We basically need to obtain access to the partner application on the users behalf.

Many APIs support the usage of JSON Web Token (JWT) for Authentication and Authorization in the HTTP Authorization header as a Bearer token. The JWT is a signed JSON payload with data (claims), that can include username, target, and scopes required by the application API. Trusting such a token requires that the application and the partner application share the knowledge of theses four value: username, target, scope, and public signing certificate. To prevent any modification of the token before it arrives at the partner application, a public key encryption signing procedure is used: the application signs it using its private key and the partner application verifies the token using the public signing certificate of the private key. Once the signature is verified, the target, the scope, and the username are verified. Only when these four values match the expected values will the partner application grant access for the API call.

The creation of a JWT is an easy task and supported by many library packages for nearly every computer language of choice (see References for a starting point). These libraries must support setting the values for the required claims and also signing of the JWT.

One word of caution: In a public key encryption, the public key certificate will expire after some period, too. But this is less harmful than an expired password. An expired password which is not updated will, at every usage, result in a locked account, which stops the work of every partner application, while a missing certificate update will only break the partner application that hasn't been updated.

Good Token Practice

A good token will include this information:

  • User identity – The user identity is included. This is the sub and prn claim.
  • The target audienece – The token is issued for a specific partner application or audience, the aud clain.
  • A scope – Applications may require specific work scopes, the scope.
  • A valid signature – The token is signed and the signature is included and can be verified by the public signing certificate.
While the target audience and scope are defined by the partner application, the username and the signing certificate are shared between both applications.

The partner application must verify the JWT by verifying the signature, checking the audience and the scope and finding a matching user from its own identity store. When these conditions are met, the partner application can proceed servicing the call.

IDCS Assertion Grant Type Flow

The IDCS Assertion Grant Type Flow is an authorization flow that allows to use an existing trust relationship as an assertion and without direct user approval at the OAuth 2.0 Authorization Server. This OAuth 2.0 flow consists of two steps:

  1. Request an OAuth 2.0 Access Token as JWT by providing a user assertion.
  2. IDCS Authorization Server returns the access token.

To request the Access Token a call like this one is used:
curl -i -H 'Authorization: Basic <base64Encoded clientid:secret>' -H 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' --request POST https://tenant-id.identity.oraclecloud.com/oauth2/v1/token -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=<Base64 encoded user-assertion-value>&scope=<scope value>' The important parts of this call are:

  • Base64-encoded client id and client secret – This is the established trust relationship. In IDCS a Confidential Application is configured and provides the client credentials to connect to.
  • URL https://tenant-id.identity.oraclecloud.com/oauth2/v1/token – The IDCS URL that returns the access token.
  • The Grant Type – This requires the value "urn:ietf:params:oauth:grant-type:jwt-bearer" in URL-encoded form.
  • User Assertion – A JWT token issued by the caller which includes the requested username and audience.
  • Scope – The scope requested for the API call.

Create a Signing Key Pair

The creation of a Signing Key Pair is a programming language specific process. It can be an easy self-signed private key or a fully authorized key with a certificate from a well-known Certification Authority. As a example we show a typical process using the JVM keytool.

  • Create a self-signed key pair valid for one year:keytool -genkey -keyalg RSA -alias <your_alias> -keystore <keystore_file> -storepass <password> -validity 365 -keysize 2048
  • Export the public key used for signing the JWT assertion:keytool -exportcert -alias <your_alias> -file <filename> -keystore <keystore_file> -storepass <password>

Configuring IDCS

In IDCS we have to configure a Confidential Application and install the Signing Certificate in IDCS:

  1. Create the Confidential Application – This can be easily done in the Applications part of IDCS (for details see IDCS Confidential Client Creation). It is important to configure the signing certificate and add the partner application audience with the required scope.




    Please note that the Scope value of the Resource is a combination of the audience (specified in the aud claim) and the scope (specified in the call URL).
  2. Although we have configured the signing certificate in the Confidential Application, IDCS requires to configure the signing certificate as a Trusted Partner Certificate, too.

Create the User Assertion

A JWT is a Base64-encoded three part token (each part separated by a dot character ('.')): Header.Payload.Signature. The User Assertion itself is a JWT issued by the caller where the Payload has the following claims: Payload = { "sub": "<user_name>", "aud": [ "https://identity.oraclecloud.com/" ], "iss": "<issuer_id>", "exp": <token_lifetime>, "prn": "<user_name>", "iat": <time_issued>, "jti": "<unique JWT ID>" } When creating this JWT, we set the sub and prn claim to the username. The aud claim must include the IDCS audience https://identity.oracle.com/. The time stamp for the time issued (iat claim) is the time when the JWT has been created and the lifetime (exp claim) specifies how long the JWT is valid. This time frame can be quite small but should take some network latency into account. A value of 1-2 minutes is reasonable. The jti claim should be created by the JWT library you use to create and sign the JWT. The issuer value (iss claim) must be the client id taken from the IDCS Confidential Application!

To sign the JWT a private-public key pair is needed. This can be a self-signed or signed by a certificate authority, it must be a valid key pair and the public key certificate still valid and not expired. A good practice is to include this in a key management process and do the needed steps to update the certificate when needed.

Request an OAuth 2.0 Access Token from IDCS

Once we have the user assertion, we can call IDCS to request the Access Token, for example using curl: curl -i -H 'Authorization: Basic <base64Encoded clientid:secret>' -H 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' --request POST https://tenant-id.identity.oraclecloud.com/oauth2/v1/token -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=<Base64 encoded user-assertion-value>&scope=<scope value>'

The result of the call is a JSON object of this format. { "access_token": "ey....", "token_type": "Bearer", "expires_in": 3600 } The access_token value holds the access token which must be used in the HTTP Authorization header for an API service call. Authorization: Bearer ey....

Summary

This article explained how to use the IDCS Assertion Grant flow to create an JWT access token for a specified user and application. This flow can be used reliably in many ways with any programming language or library. The Oracle Fusion Middleware stack supports many ways to implement this flow ranging from plain Java code as a Java EE Servlet, a Java Microprofile Code, using the Oracle Web Service Manager client library, or providing the security settings of a partner application in Oracle SOA Suite.

References

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha

Recent Content