copyright | lastupdated | keywords | subcollection | ||
---|---|---|---|---|---|
|
2019-12-09 |
web apps, nodejs, node, javascript, protected resource, authorization flow, front end, frontend, app security, authentication |
appid |
{:external: target="_blank" .external} {:shortdesc: .shortdesc} {:screen: .screen} {:pre: .pre} {:table: .aria-labeledby="caption"} {:codeblock: .codeblock} {:tip: .tip} {:note: .note} {:important: .important} {:deprecated: .deprecated} {:download: .download}
{: #web-node}
With {{site.data.keyword.appid_short_notm}}, you can easily protect your Node.js front-end web applications. With this guide, you can quickly get a simple authentication flow up and running in less than 20 minutes. {: shortdesc}
Check out the following diagram to see the Authorization Code OAuth 2.0 workflow.
{: caption="Figure 1. Node.js application flow" caption-side="bottom"}
- A user attempts to gain access to your protected web application but they are unauthorized.
- Your application redirects the user to {{site.data.keyword.appid_short_notm}}.
- {{site.data.keyword.appid_short_notm}} shows a sign in screen that the user can use to authenticate.
- They input their credentials such as a username and password. App ID validates the credentials.
- {{site.data.keyword.appid_short_notm}} redirects the user back to your application with a grant code.
- By using the grant code, your application makes a request to {{site.data.keyword.appid_short_notm}} to ensure that the user is validated. For more information about obtaining access tokens, see Obtaining tokens.
- {{site.data.keyword.appid_short_notm}} returns access and identity tokens for the validated user.
- The user is then granted access to your application.
{: #web-node-video}
Check out the following video to see how you can use {{site.data.keyword.appid_short_notm}} to protect a simple Node.js web application. All of the information that is covered in the video can also be found in written form on this page.
Don't have an app that you can try out the flow with? No problem! {{site.data.keyword.appid_short_notm}} provides a simple Node.js web sample app{: external}.
<iframe class="embed-responsive-item" id="appid-web-node" title="About {{site.data.keyword.appid_short_notm}} Node.js applications" type="text/html" width="640" height="390" src="//www.youtube.com/embed/6roa1ZOvwtw?rel=0" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>{: #web-node-before}
Before you get started with {{site.data.keyword.appid_short_notm}} in your Node.js web applications you must have the following prerequisites. {: shortdesc}
- An instance of the {{site.data.keyword.appid_short_notm}} service{: external}
- The IBM Cloud CLI
- NPM version 4+{: external}
- Node version 6+{: external}
This SDK uses the log4js
package for logging. By default, the logging level is set to info
. To create your own logging configuration, add a log4js.json
file and set the process.env.LOG4JS_CONFIG
environment variable to your JSON file.
{: note}
{: #node-web-redirect-uri}
A redirect URI is the callback endpoint of your app. During the sign in flow, {{site.data.keyword.appid_short_notm}} validates the URIs before allowing clients to participate in the authorization workflow which helps to prevent phishing attacks and grant code leakage. By registering your URI, you're telling {{site.data.keyword.appid_short_notm}} that the URI is trusted and it's OK to redirect your users. {: shortdesc}
-
Click Manage Authentications > Authentication Settings.
-
In the Add web redirect URI field, type the URI. Each URI should begin with
http://
orhttps://
and must include the full path, including any query parameters for the redirect to be successful. -
Click the + symbol in the Add web redirect URIs box.
-
Repeat steps one through three until all possible URIs are added to your list.
{: #node-web-credentials}
You can obtain your credentials in one of two ways. {: shortdesc}
-
By navigating to the Applications tab of the {{site.data.keyword.appid_short_notm}} dashboard. If you don't already have one, you can click Add application to create a new one.
-
By making a POST request to the
/management/v4/{tenantId}/applications
endpoint.Request format:
curl -X POST \ https://us-south.appid.cloud.ibm.com/management/v4/39a37f57-a227-4bfe-a044-93b6e6060b61/applications/ \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer IAM_TOKEN' \ -d '{"name": "ApplicationName"}'
{: codeblock}
Example response:
{ "clientId": "xxxxx-34a4-4c5e-b34d-d12cc811c86d", "tenantId": "xxxxx-9b1f-433e-9d46-0a5521f2b1c4", "secret": "ZDk5YWZkYmYt*******", "name": "app1", "oAuthServerUrl": "https://us-south.appid.cloud.ibm.com/oauth/v4/xxxxx-9b1f-433e-9d46-0a5521f2b1c4", "profilesUrl": "https://us-south.appid.cloud.ibm.com", "discoveryEndpoint": "https://us-south.appid.cloud.ibm.com/oauth/v4/xxxxxx-9b1f-433e-9d46-0a5521f2b1c4/.well-known/openid-configuration" }
{: screen}
{: #web-node-install}
The easiest way to work with {{site.data.keyword.appid_short_notm}} is to take advantage of the Node.JS SDK. {: shortdesc}
-
By using the command line, change into the directory that contains your Node.js application.
-
Install the following NPM requirements.
npm install --save express express-session passport log4js pug
{: codeblock}
-
Install the {{site.data.keyword.appid_short_notm}} service.
npm install --save ibmcloud-appid
{: codeblock}
-
Add the following requirements to your
server.js
file.const express = require('express'); // https://www.npmjs.com/package/express const log4js = require('log4js'); // https://www.npmjs.com/package/log4js const session = require('express-session'); // https://www.npmjs.com/package/express-session const passport = require('passport'); // https://www.npmjs.com/package/passport const WebAppStrategy = require('ibmcloud-appid').WebAppStrategy; // https://www.npmjs.com/package/ibmcloud-appid
{: shortdesc}
-
Set up your application to use express-session middleware by using the credentials that you obtained in step 1. You can choose to format your redirect URI in one of two ways. Manually, by using a new
WebAppStrategy({redirectUri: "...."})
or by setting the value as an environment variable as shown in the example code.const app = express(); const logger = log4js.getLogger("testApp"); app.use(session({ secret: '123456', resave: true, saveUninitialized: true })); app.use(passport.initialize()); app.use(passport.session()); passport.serializeUser((user, cb) => cb(null, user)); passport.deserializeUser((user, cb) => cb(null, user)); passport.use(new WebAppStrategy({ tenantId: "<tenant_ID>", clientId: "<client_ID>", secret: "<secret>", oauthServerUrl: "<OAuth_Server_URL>", redirectUri: "<redirect_URI>" }));
{: codeblock}
You must configure the middleware with the proper session storage for production environments. For more information see the express.js docs. {: note}
{: #node-web-protect}
Now that you have {{site.data.keyword.appid_short_notm}} installed, you're ready to protect your application. You can choose to protect your entire application or only specific resources by defining a web app strategy. {: shortdesc}
-
Configure the callback endpoint. The callback finishes the authorization process by retrieving access and identity tokens from App ID and redirecting the user to one of the following locations:
- The original URL of the request that triggered the authentication, as persisted in the HTTP session as
WebAppStrategy.ORIGINAL_URL
. - Specifying a redirect in the event of a successful authentication.
- The application root (
/
) as shown in the next step.
app.get(CALLBACK_URL, passport.authenticate(WebAppStrategy.STRATEGY_NAME));
{: codeblock}
- The original URL of the request that triggered the authentication, as persisted in the HTTP session as
-
Set a sign in endpoint that always redirects a browser to the Login Widget. Be sure to add a success redirect option so that you don't end up in an endless authentication loop.
app.get('/appid/login', passport.authenticate(WebAppStrategy.STRATEGY_NAME, { successRedirect: '/', forceLogin: true }));
{: codeblock}
-
Configure sign out. When a user signs out of your application, all of their authentication information is cleared from that session. In order to interact with your application they will need to sign in again.
app.get('/appid/logout', function(req, res){ webappstrategy.logout(req); res.redirect('/'); });
{: shortdesc}
{: #node-web-user-info}
You can pull information that is provided by your identity providers to personalize your app experience. {: shortdesc}
-
Configure your application to obtain user information.
protected
is a place holder variable that you can change to match the endpoint for your application.app.get("/protected_resource", passport.authenticate(WebAppStrategy.STRATEGY_NAME), function(req, res){ res.json(req.user); });
{: codeblock}
For example, in the sample application you can see how to obtain the users name to personalize your application.
app.get('/api/user', (req, res) => { // console.log(req.session[WebAppStrategy.AUTH_CONTEXT]); res.json({ user: { name: req.user.name } }); });
{: codeblock}
{: #node-web-test}
To test your authorization configuration, navigate to the URL that your server is listening on as defined in your application. Try signing in, try signing out. Ensure that the configuration is working as you expected.
When you're ready to move to the next step, you can try enabling multifactor authentication for Cloud Directory or adding custom attributes to further personalize your app.