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 re-authenticate.
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:
-
The user requests a protected resource.
-
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.
-
The web browser calls the URL.
-
The Oracle Identity Cloud Service Sign In page appears.
-
The user submits their Oracle Identity Cloud Service sign-in credentials.
-
After the user signs in, Oracle Identity Cloud Service creates a session for the user and issues an authorization code.
-
The web application makes a back-end (or server-to-server) call to exchange the authorization code for an access token.
-
Oracle Identity Cloud Service issues an access token and an id token.
-
A session is established, and the user is redirected to the Home page.
-
The Home page of the web application appears.
Use Case #2: Get Details About the User
The data flow happens this way:
-
The user requests the
/myProfile
resource. -
The web application uses Oracle Identity Cloud Service's SDK to validate the id token.
-
The data that returns from id token validation contains user's details in the format of a JSON object.
-
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 inside the Node.js SDK zip file that you download from
the Oracle Identity Cloud Service console. 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": "^8.2.1",
"jwk-to-pem": "^1.2.6",
"jws": "^3.1.5",
"lru": "^3.1.0",
"passport": "^0.4.0",
"promise": "^8.0.1",
"querystring": "^0.2.0",
"request": "^2.81.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",
"LogLevel":"INFO",
"ConsoleLog":"True"
}
};
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 Oracle Identity Cloud Service console. |
ClientSecret |
The value of the Client Secret that’s generated after you register the Node.js web application in the Oracle 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 |
ConsoleLog |
Enables SDK log. |
LogLevel |
Indicates the log level of the SDK. |
The application uses both the logoutSufix
and
redirectURL
attributes to avoid hard code these values. The SDK
doesn’t require them.
The Node.js application implements the /oauth/oracle
URL route. When
a user authenticates with Oracle Identity Cloud Service, the web browser makes a GET 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 and Id Token Values to set in the session.
req.session.access_token = result.access_token;
req.session.id_token = result.id_token;
res.cookie(config.IDCS_COOKIE_NAME, result.access_token);
res.header('idcs_user_assertion', 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, the browser
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 another protected URL: /myProfile
.
Any 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, as follows:
app.get("/myProfile", ensureAuthenticated, function(req,res){
//User Manager loaded with the configurations
var am = new IdcsAuthenticationManager(auth.oracle);
//Validating id token to acquire information such as UserID, DisplayName, list of groups and AppRoles assigned to the user.
am.validateIdToken(req.session['id_token'])
.then(function(idToken){
res.render('myProfile', {
layout: 'privateLayout',
title: 'My Profile',
user: req.user,
userInfo: JSON.stringify(idToken, null, 2)
});
}).catch(function(err1){
res.end(err1);
})
});
After initializing the IdcsAuthenticationManager
object,
the /myProfile
route's handler uses the SDK’s
IdcsAuthenticationManager.validateIdToken()
function to acquire
user information such as display name, user id, and the list of groups and application
roles assigned to the user. The JSON object is then parserd as string 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){
var id_token = req.session.id_token;
var logouturl = auth.oracle.AudienceServiceUrl + auth.oracle.logoutSufix + '?post_logout_redirect_uri=http%3A//localhost%3A3000&id_token_hint='+ id_token;
req.session.destroy(function(err) {
if(err) {
console.log(err);
} else {
req.logout();
res.clearCookie();
res.redirect(logouturl);
}
})
});
This route invalidates the application’s session, removes any object and cookie set previously, and then redirects the user’s web browser to Oracle Identity Cloud Service's OAuth log out URL.