Learn About Authentication Between Node.js Applications and Oracle Identity Cloud Service

You’re ready to learn about authentication between Node.js web applications and Oracle Identity Cloud Service. This includes understanding the following:

  • The three-legged authentication flow that Oracle Identity Cloud Service supports for the Node.js SDK

  • Use cases for using an SDK with a Node.js application to authenticate with Oracle Identity Cloud Service

  • Methods and functions of the Node.js SDK

Learn About Three-Legged Authentication Flows

Oracle Identity Cloud Service supports the three-legged authentication flow for the Node.js SDK. In this flow, users interact directly with Oracle Identity Cloud Service. After a user signs in, Oracle Identity Cloud Service issues an authorization code that the SDK exchanges for a user access token. The Node.js web application uses this access token to grant users access to the protected resources in the application. The three-legged flow uses the authorization code grant type.

For increased security, Oracle recommends that you use the three-legged flow to integrate your Node.js web applications with Oracle Identity Cloud Service for authentication. By using the authorization code grant type, you can also access other applications that are protected by Oracle Identity Cloud Service without having to reauthenticate.

Learn About the Primary Use Cases for Using an SDK with a Node.js Application

The Node.js web application implements two use cases: one for authenticating users, and the other for accessing detailed information about the logged-in user.

The following data flow diagrams illustrate the flow of events, calls, and responses between the web browser, the web application, and Oracle Identity Cloud Service for each use case.

Use Case #1: Authenticate a User

The data flow happens this way:

  1. The user requests a protected resource.

  2. The authentication module uses the SDK to generate a request-authorization-code URL for Oracle Identity Cloud Service and send this URL as a redirect response to the web browser.

  3. The web browser calls the URL.

  4. The Oracle Identity Cloud Service Sign In page appears.

  5. The user submits their Oracle Identity Cloud Service sign-in credentials.

  6. After the user signs in, Oracle Identity Cloud Service creates a session for the user and issues an authorization code.

  7. The web application makes a back-end (or server-to-server) call to exchange the authorization code for a user access token.

  8. Oracle Identity Cloud Service issues the access token.

  9. A session is established, and the user is redirected to the Home page.

  10. The Home page of the web application appears.

Use Case #2: Get Details About the User

The data flow happens this way:

  1. The user requests the /myProfile resource.

  2. The web application calls Oracle Identity Cloud Service using the SDK, which uses the access token that’s stored in the user session as a parameter.

  3. The user's details are sent to the web application as a JSON object.

  4. The My Profile page renders the JSON object as HTML content.

Learn About Methods and Functions

The Node.js SDK is a Node.js passport strategy that you add to your Node.js modules folder. This SDK is also based on Node.js promises. All third-party dependencies that the Node.js SDK needs are defined in the SDK’s package.json file. You need to use at least this set of modules in your Node.js web application.

"dependencies": {
    "async": "^2.1.2",
    "bunyan": "^1.8.5",
    "cache-manager": "^2.2.0",
    "json-web-token": "^2.1.3",
    "jsonwebtoken": "^7.1.9",
    "jwk-to-pem": "^1.2.6",
    "jws": "^3.1.4",
    "lru": "^3.1.0",
    "passport": "^0.3.2",
    "promise": "^7.1.1",
    "querystring": "^0.2.0",
    "request": "^2.79.0",
    "rsa-pem-to-jwk": "^1.1.3",
    "util": "^0.10.3"
  },

A Node.js web application was developed using the Node.js express and express-handlebars modules, which implements URL routes in the form of an app.get() function for each URL.

The Node.js SDK requires a JSON variable that’s loaded with Oracle Identity Cloud Service connection information. The Node.js web application uses the ids variable to store this information:

var ids = {
    oracle: {
         "ClientId": '123456789abcdefghij',
         "ClientSecret": 'abcde-12345-zyxvu-98765-qwerty',
         "ClientTenant": 'idcs-abcd1234',
         "IDCSHost": 'https://%tenant%.identity.oraclecloud.com',
         "AudienceServiceUrl" : 'https://idcs-abcd1234.identity.oraclecloud.com',
         "TokenIssuer": 'https://identity.oraclecloud.com/',
         "scope": 'urn:opc:idm:t.user.me openid',
         "logoutSufix": '/oauth2/v1/userlogout',
         "redirectURL": 'http://localhost:3000/callback'
    }
};
 
module.exports = ids;

Below is a brief explanation of each required attribute for this SDK:

Name Description
ClientId The value of the Client ID that’s generated after you register the Node.js web application in the Identity Cloud Service console.
ClientSecret The value of the Client Secret that’s generated after you register the Node.js web application in the Identity Cloud Service console.
ClientTenant The domain prefix of your Oracle Identity Cloud Service instance. This prefix is usually similar to idcs-abcd1234.
IDCSHost The domain suffix of your Oracle Identity Cloud Service instance. At runtime, the %tenant% placeholder is replaced by the value of the ClientTenant attribute.
AudienceServiceUrl The fully-qualified domain name URL of your Oracle Identity Cloud Service instance.
TokenIssuer For this attribute, Oracle recommends that you keep the value https://identity.oraclecloud.com/.
scope

The scope controls the data that the application can access or process on behalf of the Oracle Identity Cloud Service user.

If the application uses the SDK to authenticate a user, then the scope is openid. If the application uses the SDK to get details about the user, then the scope is urn:opc:idm:t.user.me openid.

The application uses both the logoutSufix and redirectURL attributes. The SDK doesn’t require them.

The Node.js application implements the /oauth/oracle URL route. When a user decides to authenticate with Oracle Identity Cloud Service, the web browser makes a request to this URL. This route uses the SDK to generate Oracle Identity Cloud Service's authorization URL.

//Loading the configurations
var auth = require('./auth.js');
 
//Route for /oauth/oracle
app.get("/auth/oracle", function(req, res){
    //Authentication Manager loaded with the configurations.
    am = new IdcsAuthenticationManager(auth.oracle);
    //Using Authentication Manager to generate the Authorization Code URL, passing the
    //application's callback URL as parameter, along with code value and code parameter.
    am.getAuthorizationCodeUrl(auth.oracle.redirectURL, auth.oracle.scope, "1234", "code")
        .then(function(authZurl){
            //Redirecting the browser to the Oracle Identity Cloud Service Authorization URL.
            res.redirect(authZurl);
        }).catch(function(err){
            res.end(err);
        })
});

This function loads the JSON parameters to a variable, initializes an authentication manager, and uses the IdcsAuthenticationManager.getAuthorizationCodeUrl() function of the Node.js SDK to generate the authorization code URL. This function uses promise to either redirect the user's web browser when the authorization code URL is generated or to render an error in the browser.

The following parameters are used to generate the authorization code URL:

Name Description
auth.oracle.redirectURL After a user signs in, Oracle Identity Cloud Service redirects the user’s web browser to this URL. This URL must match the one you’ll configure for the trusted application in the Identity Cloud Service console. See Register the Node.js Application for more information about specifying a redirect URL for the Node.js web application.
auth.oracle.scope The OAuth or OpenID Connect scope of authentication. This application requires only openid authentication.
state The OAuth protocol defines this parameter. The sample Node.js web application uses this code to check whether communication can be established to Oracle Identity Cloud Service. For this example, the value for this parameter is 1234.
response_type The parameter required by the authorization code grant type. For this example, the value for this parameter is code.

After the user signs in, Oracle Identity Cloud Service redirects the user’s web browser to a callback URL, which the developer must implement. The Node.js web application uses the /callback route to handle this request.

//Route for /callback
app.get("/callback", function(req,res){
    //Authentication Manager loaded with the configurations.
    var am = new IdcsAuthenticationManager(auth.oracle);
    //Getting the authorization code from the "code" parameter
    var authZcode = req.query.code;
    //Using the Authentication Manager to exchange the Authorization Code to an Access Token.
    am.authorizationCode(authZcode)
        .then(function(result){
            //Getting the Access Token Value.
            res.cookie(config.IDCS_COOKIE_NAME, result.access_token);
            res.redirect('/auth.html');
        }).catch(function(err){
            res.end(err);
        })
});

The Node.js application uses the authorization code to request an access token. The access token is stored as a cookie, which is then sent to the web browser for future use.

The IdcsAuthenticationManager.authorizationCode() function of the Node.js SDK also uses promise (a then-catch statement) to set the access token as a cookie, and to redirect the browser to the /auth.html page.

The Node.js SDK is based on the Node.js passport framework. Therefore, you have to forward the access token as a header variable to the /auth URL handler, and use the passport.authenticate() method with the Oracle Identity Cloud Service Strategy Name as a parameter:

//Uses passport to create a User Session in Node.js.
//Passport sets a user attribute in the request as a json object.
app.get('/auth', passport.authenticate(config.IDCS_STRATEGY_NAME, {}), function(req, res) {
   res.redirect('/home');
});

After the passport.authenticate() method creates the application's session, the function redirects the user’s web browser to a protected URL in the /home application. In addition to /home, the Node.js web application has three other protected URLs: /appDetails, /userInfo, and /myProfile.

Each protected URL needs to check whether the user's session was created previously. The following function is used by each app.get() function for these URLs.

function ensureAuthenticated(req, res, next) {
   if (req.isAuthenticated()) {
      return next();
   }
   res.redirect('/login')
}

The Node.js application handles the /myProfile route and gets information set in the session by the passport.authenticate() method, as follows:

app.get("/myProfile", ensureAuthenticated, function(req,res){
   //User Manager loaded with the configurations
   var um = new IdcsUserManager(auth.oracle);
   //Using the user id in the request attribute to render the user json in the screen.
   um.getUser(req.user.id)
      .then(function(user){
         res.render('myProfile', {
         layout: 'privateLayout',
         title: 'My Profile',
         user: req.user,
         userInfo: JSON.stringify(user, null, 2)
         });
      }).catch(function(err1){
         res.end(err1);
      })
});

After initializing the UserManager object, the /myProfile route's handler uses the SDK’s IdcsUserManager.getUser() function to get a JSON object that represents the user profile. The application sends the JSON object to the myProfile.handlebars file for rendering in the web browser.

To sign the user out from single sign-on between the application and Oracle Identity Cloud Service, the Node.js web application implements the /logout route, as follows:

app.get('/logout', function(req, res){
   req.logout();
   res.clearCookie();
   res.redirect(auth.oracle.IDCSHost + auth.oracle.logoutSufix);
});

This route invalidates the application’s session, removes any cookies set previously, and then redirects the user’s web browser to Oracle Identity Cloud Service's OAuth log out URL. This URL is set up in the JSON configuration object.