Skip to content

Commit b67f7bd

Browse files
authored
fix(logout): fix logout compatibility with passport >= 0.6.0 (#305)
- Starting passport 0.6.0, req#logout() is now an asynchronous function and adds a callback function as the last argument.
1 parent 0d0fc18 commit b67f7bd

File tree

5 files changed

+165
-29
lines changed

5 files changed

+165
-29
lines changed

README.md

Lines changed: 72 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
[![GithubForks][img-github-forks]][url-github-forks]
1313

1414
## Table of Contents
15+
1516
* [Summary](#summary)
1617
* [Requirements](#requirements)
1718
* [Migrating from v6 to v7](#migrating-from-v6-to-v7)
@@ -32,36 +33,43 @@ In addition, the SDK provides helper utilities centered around tokens and user p
3233
Read the [official documentation](https://cloud.ibm.com/docs/appid?topic=appid-getting-started) for information about getting started with IBM Cloud App ID Service.
3334

3435
## Requirements
36+
3537
* npm 6.+
3638
* node 12.+
3739
* passport.js 0.6.0+
3840

3941
## Migrating from v6 to v7
42+
4043
Breaking changes in passport.js require users to pass the `{ keepSessionInfo: true }` object to the middleware when protecting endpoints when using WebAppStrategy.
4144

4245
Old Usage (SDK v6):
43-
```
46+
47+
```js
4448
app.use(passport.authenticate(WebAppStrategy.STRATEGY_NAME));
4549
app.get(CALLBACK_URL, passport.authenticate(WebAppStrategy.STRATEGY_NAME));
4650
```
51+
4752
New Usage (SDK v7):
4853
In SDK version 7, when using webappStrategy, you need to pass { keepSessionInfo: true } to the passport.authenticate method. Update your code as follows:
4954

50-
```
55+
```js
5156
app.use(passport.authenticate(WebAppStrategy.STRATEGY_NAME, { keepSessionInfo: true }));
5257
app.get(CALLBACK_URL, passport.authenticate(WebAppStrategy.STRATEGY_NAME, { keepSessionInfo: true }));
5358
```
5459

5560
## Installation
56-
```
61+
62+
```shell
5763
npm install --save ibmcloud-appid
5864
```
5965

6066
## Example Usage
67+
6168
Below find two examples of using this SDK to protect APIs and Web applications. Both samples are available under `samples` folder in this repository.
6269

6370
Note that below examples are using additional npm modules. In order to install required npm modules run below commands in your node.js application.
64-
```
71+
72+
```shell
6573
npm install --save express
6674
npm install --save log4js
6775
npm install --save passport
@@ -70,6 +78,7 @@ npm install --save pug
7078
```
7179

7280
#### Protecting APIs using the APIStrategy
81+
7382
APIStrategy expects request to contain an Authorization header with valid access token and optionally identity token. See App ID docs for additional information. The expected header structure is `Authorization=Bearer {access_token} [{id_token}]`
7483

7584
In case of invalid/expired tokens the APIStrategy will return HTTP 401 with `Www-Authenticate=Bearer scope="{scope}" error="{error}"`. The `error` component is optional.
@@ -127,7 +136,9 @@ app.listen(port, function(){
127136
```
128137

129138
##### Protecting APIs using the APIStrategy: Access Control
139+
130140
Using access control, you can define the scopes that are required to access a specific endpoint.
141+
131142
```JavaScript
132143
app.get("/api/protected",
133144
passport.authenticate(APIStrategy.STRATEGY_NAME, {
@@ -139,11 +150,13 @@ app.get("/api/protected",
139150
}
140151
);
141152
```
153+
142154
The scope parameter defines the required scopes.
143155
The audience parameter is optional and should be set to the application clientId
144156
to guarantee the scopes are for the requested application.
145157

146158
#### Protecting web applications using WebAppStrategy
159+
147160
WebAppStrategy is based on the OAuth2 authorization_code grant flow and should be used for web applications that use browsers. The strategy provides tools to easily implement authentication and authorization flows. When WebAppStrategy provides mechanisms to detect unauthenticated attempts to access protected resources. The WebAppStrategy will automatically redirect user's browser to the authentication page. After successful authentication user will be taken back to the web application's callback URL (redirectUri), which will once again use WebAppStrategy to obtain access, identity and refresh tokens from App ID service. After obtaining these tokens the WebAppStrategy will store them in HTTP session under WebAppStrategy.AUTH_CONTEXT key. In a scalable cloud environment it is recommended to persist HTTP sessions in a scalable storage like Redis to ensure they're available across server app instances.
148161

149162
```JavaScript
@@ -236,8 +249,9 @@ app.get(CALLBACK_URL, passport.authenticate(WebAppStrategy.STRATEGY_NAME));
236249

237250
// Logout endpoint. Clears authentication information from session
238251
app.get(LOGOUT_URL, function(req, res){
239-
WebAppStrategy.logout(req);
240-
res.redirect(LANDING_PAGE_URL);
252+
WebAppStrategy.logout(req, () => {
253+
res.redirect(LANDING_PAGE_URL);
254+
});
241255
});
242256

243257
// Protected area. If current user is not authenticated - redirect to the login widget will be returned.
@@ -251,7 +265,9 @@ app.listen(process.env.PORT || 1234);
251265
```
252266

253267
##### Protecting web applications using WebAppStrategy: Access Control
268+
254269
Using access control, you can check which scopes exist on the request.
270+
255271
```JavaScript
256272
app.get("/protected", passport.authenticate(WebAppStrategy.STRATEGY_NAME), function(req, res){
257273
if(WebAppStrategy.hasScope(req, "read write")){
@@ -262,12 +278,15 @@ app.get("/protected", passport.authenticate(WebAppStrategy.STRATEGY_NAME), funct
262278
}
263279
});
264280
```
281+
265282
Use WebAppStrategy's hasScope method to check if a given request has some specific scopes.
266283

267284
#### Anonymous login
285+
268286
WebAppStrategy allows users to login to your web application anonymously, meaning without requiring any credentials. After successful login the anonymous user access token will be persisted in HTTP session, making it available as long as HTTP session is kept alive. Once HTTP session is destroyed or expired the anonymous user access token will be destroyed as well.
269287

270288
To allow anonymous login for a particular URL use two configuration properties as shown on a code snippet below:
289+
271290
* `allowAnonymousLogin` - set this value to true if you want to allow your users to login anonymously when accessing this endpoint. If this property is set to true no authentication will be required. The default value of this property is `false`, therefore you must set it explicitly to allow anonymous login.
272291
* `allowCreateNewAnonymousUser` - By default a new anonymous user will be created every time this method is invoked unless there's an existing anonymous access_token stored in the current HTTP session. In some cases you want to explicitly control whether you want to automatically create new anonymous user or not. Set this property to `false` if you want to disable automatic creation of new anonymous users. The default value of this property is `true`.
273292

@@ -285,6 +304,7 @@ app.get(LOGIN_ANON_URL, passport.authenticate(WebAppStrategy.STRATEGY_NAME, {
285304
As mentioned previously the anonymous access_token, identity_token and refresh_token (optional) will be automatically persisted in HTTP session by App ID SDK. You can retrieve them from HTTP session via same mechanisms as regular tokens. Access and identity tokens will be kept in HTTP session and will be used until either them or HTTP session expires.
286305

287306
### Refresh Token
307+
288308
Refresh Token may be used to acquire new access and identity tokens without the need to re-authenticate. Refresh Token is usually configured to have longer expiration than access token. Refresh Token is optional and can be configured in your App ID Dashboard.
289309

290310
After a successful login, in addition to access_token and identity_token, a refresh_token will be persisted in the HTTP session as well.
@@ -317,16 +337,16 @@ const TokenManager = require('ibmcloud-appid').TokenManager(config);
317337
```
318338

319339
### Custom Identity
340+
320341
App ID's custom identity flow enables developers to utilize their own authorization protocols, while still leveraging App ID's capabilities. Instead of managing the entirety of the authorization flow, App ID's custom identity flow allows clients to leverage their own authorization protocol to authenticate and authorize their users and then provides a framework for exchanging verified authentication data securely for App ID tokens.
321342

322343
To utilize the custom identity flow, the user must first register a public key in PEM form using the App ID Dashboard. The user must generate a signed JWT using any open source library and then the user can then use `TokenManager.getCustomIdentityTokens(jwsTokenString, scopes)` to exchange the token for access and identity tokens. `getCustomIdentityTokens()` is an asynchronous function that returns the access token and identity token. These tokens can be stored in the HTTP session for future use. `custom-identity-app-sample-server.js` contains an example of using the Token Manager.
323344

324345
Refer to the [documentation on custom identity](https://cloud.ibm.com/docs/appid?topic=appid-custom-identity) for more details on how to implement App ID's custom identity flow in your application.
325346

326-
327347
### Application Identity and Authorization
328348

329-
In case you want to call protected APIs from applications or clients that are non-interactive (i.e., there is no user involved), you can use the App ID application identity and authorization flow to secure your applications.
349+
In case you want to call protected APIs from applications or clients that are non-interactive (i.e., there is no user involved), you can use the App ID application identity and authorization flow to secure your applications.
330350

331351
App ID application authorization implements the OAuth2.0 Client Credentials grant.
332352

@@ -362,9 +382,11 @@ async function getAppIdentityToken() {
362382
}
363383
}
364384
```
385+
365386
For more detailed information on using the application identity and authorization flow, refer to the [App ID documentation](https://cloud.ibm.com/docs/appid?topic=appid-app).
366387

367388
### Manage User Profile
389+
368390
Using the App ID UserProfileManager, you are able to create, delete, and retrieve user profile attributes as well as get additional info about a user.
369391

370392
```javascript
@@ -403,74 +425,95 @@ userProfileManager.getUserInfo(accessToken, identityToken).then(function (userIn
403425
});
404426

405427
```
428+
406429
## Cloud Directory
430+
407431
Make sure to that Cloud Directory identity provider set to **ON** in the App ID dashboard and that you've included a callback endpoint.
408432

409433
### Login using resource owner password flow
434+
410435
WebAppStrategy allows users to login to your web application using username/password.
411436
After successful login, the user access token will be persisted in HTTP session, making it available as long as HTTP session is kept alive. Once HTTP session is destroyed or expired the user access token will be destroyed as well.
412437
To allow login using username/password add to your app a post route that will be called with the username and password parameters.
438+
413439
```javascript
414440
app.post("/form/submit", bodyParser.urlencoded({extended: false}), passport.authenticate(WebAppStrategy.STRATEGY_NAME, {
415441
successRedirect: LANDING_PAGE_URL,
416442
failureRedirect: ROP_LOGIN_PAGE_URL,
417443
failureFlash : true // allow flash messages
418444
}));
419445
```
446+
420447
* `successRedirect` - set this value to the url you want the user to be redirected after successful authentication, default: the original request url. (in this example:"/form/submit")
421448
* `failureRedirect` - set this value to the url you want the user to be redirected in case authentication fails, default: the original request url. (in this example:"/form/submit")
422449
* `failureFlash` - set this value to true if you want to receive the error message that returned from cloud directory service, default: false
423450

424451
Note:
452+
425453
1. If you submitting the request using a html form, use [body-parser](https://www.npmjs.com/package/body-parser) middleware.
426454
2. Use [connect-flash](https://www.npmjs.com/package/connect-flash) for getting the returned error message. see the web-app-sample-server.js.
427455

428456
### Sign up
457+
429458
Pass WebAppStrategy "show" property and set it to WebAppStrategy.SIGN_UP, will launch the App ID sign up form.
459+
430460
```javascript
431461
app.get("/sign_up", passport.authenticate(WebAppStrategy.STRATEGY_NAME, {
432462
successRedirect: LANDING_PAGE_URL,
433463
show: WebAppStrategy.SIGN_UP
434464
}));
435465
```
466+
436467
Note:
468+
437469
1. If your Cloud directory setting ***Allow users to sign-in without email verification** is set to **No**, the process will end without retrieving App ID access and id tokens.
438470
2. Be sure to set **Allow users to sign up and reset their password" to **ON**, in the settings for Cloud Directory.
439471

440-
441472
### Forgot Password
473+
442474
Pass WebAppStrategy "show" property and set it to WebAppStrategy.FORGOT_PASSWORD, will launch the App ID forgot password from.
475+
443476
```javascript
444477
app.get("/forgot_password", passport.authenticate(WebAppStrategy.STRATEGY_NAME, {
445478
successRedirect: LANDING_PAGE_URL,
446479
show: WebAppStrategy.FORGOT_PASSWORD
447480
}));
448481
```
482+
449483
Note:
484+
450485
1. This process will end without retrieving App ID access and id tokens.
451486
2. Make sure to set "Allow users to sign up and reset their password" and "Forgot password email" to ON, in Cloud Directory settings that are in the App ID dashboard.
452487

453488
### Change Details
489+
454490
Pass WebAppStrategy "show" property and set it to WebAppStrategy.CHANGE_DETAILS, will launch the App ID change details from.
491+
455492
```javascript
456493
app.get("/change_details", passport.authenticate(WebAppStrategy.STRATEGY_NAME, {
457494
successRedirect: LANDING_PAGE_URL,
458495
show: WebAppStrategy.CHANGE_DETAILS
459496
}));
460497
```
498+
461499
Note:
500+
462501
1. This call requires that the user is authenticated with Cloud directory identity provider.
463502
2. Make sure to set "Allow users to sign up and reset their password" to ON, in Cloud Directory settings that are in the App ID dashboard.
464503

465504
### Change Password
505+
466506
Pass WebAppStrategy "show" property and set it to WebAppStrategy.CHANGE_PASSWORD, will launch the App ID change password from.
507+
467508
```javascript
468509
app.get("/change_password", passport.authenticate(WebAppStrategy.STRATEGY_NAME, {
469510
successRedirect: LANDING_PAGE_URL,
470511
show: WebAppStrategy.CHANGE_PASSWORD
471512
}));
472513
```
514+
473515
Note:
516+
474517
1. This call requires that the user is authenticated with Cloud directory identity provider.
475518
2. Make sure to set "Allow users to sign up and reset their password" to ON, in Cloud Directory settings that are in App ID dashboard.
476519

@@ -501,8 +544,9 @@ The self service manger exposed the following APIs, each API can get 'iamToken'
501544
You must supply 'iamApikey' to the selfServiceManager otherwise you must supply the 'iamToken' to each of the selfServiceManager APIs.
502545

503546
#### Sign-up
547+
504548
Sign up a new user.
505-
userData is a JSON object with the user SCIM profile (https://tools.ietf.org/html/rfc7643#page-35).
549+
userData is a JSON object with the user SCIM profile (<https://tools.ietf.org/html/rfc7643#page-35>).
506550
language currently unused, default to 'en'.
507551

508552
```javascript
@@ -515,6 +559,7 @@ selfServiceManager.signUp(userData, language, iamToken).then(function (user) {
515559
```
516560

517561
#### Forgot Password
562+
518563
Forgot password flow.
519564
email is the user email that request the forgot password request.
520565
language currently unused, default to 'en'.
@@ -529,6 +574,7 @@ selfServiceManager.forgotPassword(email, language, iamToken).then(function (user
529574
```
530575

531576
#### Resend Notification
577+
532578
Resend notification.
533579
uuid is the Cloud Directory user uuid.
534580
templateName is the template to be send.
@@ -542,7 +588,9 @@ selfServiceManager.resendNotification(uuid, templateName, language, iamToken).th
542588
});
543589
}
544590
```
591+
545592
#### Get Sign-up confirmation result
593+
546594
Get the stored result for the sign up confirmation.
547595
This should be called to verify the authenticity of the sign up verification.
548596
context is a random string that will be supply by App ID, for authenticity purposes.
@@ -556,7 +604,9 @@ selfServiceManager.getSignUpConfirmationResult(context, iamToken).then(function
556604
});
557605
}
558606
```
607+
559608
#### Get Forgot password confirmation result
609+
560610
Get the stored result for the forgot password confirmation.
561611
This should be called to verify the authenticity of the forgot password request.
562612
context is a random string that will be supply by App ID, for authenticity purposes.
@@ -570,7 +620,9 @@ selfServiceManager.getForgotPasswordConfirmationResult(ucontext, iamToken).then(
570620
});
571621
}
572622
```
623+
573624
#### Set User new password
625+
574626
Change the user passowrd.
575627
uuid is the Cloud Directory user uuid.
576628
newPassword the new password to be set.
@@ -585,7 +637,9 @@ selfServiceManager.setUserNewPassword(uuid, newPassword, language, changedIpAddr
585637
});
586638
}
587639
```
640+
588641
#### Get user details
642+
589643
Gets the stored details of the Cloud directory user.
590644
uuid is the Cloud Directory user uuid.
591645

@@ -597,10 +651,12 @@ selfServiceManager.getUserDetails(uuid, iamToken).then(function (user) {
597651
});
598652
}
599653
```
654+
600655
#### Update user details
656+
601657
update the user details.
602658
uuid is the Cloud Directory user uuid.
603-
userData is a JSON object with the updated user SCIM profile (https://tools.ietf.org/html/rfc7643#page-35).
659+
userData is a JSON object with the updated user SCIM profile (<https://tools.ietf.org/html/rfc7643#page-35>).
604660

605661
```javascript
606662
selfServiceManager.updateUserDetails(uuid, userData, iamToken).then(function (user) {
@@ -612,15 +668,18 @@ selfServiceManager.updateUserDetails(uuid, userData, iamToken).then(function (us
612668
```
613669

614670
### Logging
671+
615672
This SDK uses the log4js package for logging. By default the logging level is set to `info`. To create your own logging configuration for your application, add a log4js.json file and set the `process.env.LOG4JS_CONFIG` environment variable to your json file.
616673

617-
To learn more about log4js, visit the documentation here (https://log4js-node.github.io/log4js-node/).
674+
To learn more about log4js, visit the documentation here (<https://log4js-node.github.io/log4js-node/>).
618675

619676
## Got Questions?
677+
620678
Join us on [Slack](https://www.ibm.com/cloud/blog/announcements/get-help-with-ibm-cloud-app-id-related-questions-on-slack) and chat with our dev team.
621679

622680
### License
623-
This package contains code licensed under the Apache License, Version 2.0 (the "License"). You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 and may also view the License in the LICENSE file within this package.
681+
682+
This package contains code licensed under the Apache License, Version 2.0 (the "License"). You may obtain a copy of the License at <http://www.apache.org/licenses/LICENSE-2.0> and may also view the License in the LICENSE file within this package.
624683

625684
[img-ibmcloud-powered]: https://img.shields.io/badge/ibm%20cloud-powered-blue.svg
626685
[url-ibmcloud]: https://www.ibm.com/cloud/

0 commit comments

Comments
 (0)