From f7d375c1996e77897fea53558ca3d8d9c3f333aa Mon Sep 17 00:00:00 2001 From: Cemre MENGU Date: Mon, 19 Mar 2018 11:52:50 +0300 Subject: [PATCH 1/5] Added passport tutorial en documentation --- docs/source/en/tutorials/passport.md | 283 ++++++++++++++++++++++++++- 1 file changed, 282 insertions(+), 1 deletion(-) diff --git a/docs/source/en/tutorials/passport.md b/docs/source/en/tutorials/passport.md index 0fab88450d..8125bcb155 100644 --- a/docs/source/en/tutorials/passport.md +++ b/docs/source/en/tutorials/passport.md @@ -1 +1,282 @@ -this document is still waiting for translation, see [Chinese Version](/zh-cn/tutorials/passport.html) \ No newline at end of file +## Title: Passport + +** "Login authentication" ** is a common business scenario, including "account password login method" and "third-party unified login." + +Among them, we often use the latter, such as Google, GitHub, QQ unified login, which are based on [OAuth](https://oauth.net/2/) specification. + +[Passport](http://www.passportjs.org/) is a highly scalable authentication middleware that supports the `Strategy` of `Github` ,`Twitter`,`Facebook`, and other well-known service vendors. It also supports login and authorization verification via account passwords. + +Egg provides an [egg-passport](https://github.com/eggjs/egg-passport) plugin on top of it, encapsulating general logic such as callback processing after initialization and authentication success, allowing the developer to use Passport with just a few API calls. + +The execution sequence of [Passport](http://www.passportjs.org/) is as follows: + +* User access page +* Check Session +* Intercept the login authentication login page +* Strategy Authentication +* Checksum storage of user information +* Serialize user information to Session +* Jump to the specified page + +## Using egg-passport + +Below, we will use GitHub login as an example to demonstrate how to use it. + +### Installation + +```bash +$ npm i --save egg-passport +$ npm i --save egg-passport-github +``` + +For more plugins, see [GitHub Topic - egg-passport](https://github.com/topics/egg-passport) . + +### Configuration + +**Enabling the plugin:** + +```js +// config/plugin.js +Exports.passport = { + Enable: true, + Package: 'egg-passport' +}; + +exports.passportGithub = { + Enable: true, + Package: 'egg-passport-github' +}; +``` + +**Configuration:** + +Note: The [egg-passport](https://github.com/eggjs/egg-passport) standardizes the configuration fields, which are unified as `key` and `secret`. + +```js +// config/default.js +config.passportGithub = { + Key: 'your_clientID', + Secret: 'your_clientSecret' +}; +``` + +**note:** + +* Create a [GitHub OAuth App](https://github.com/settings/applications/new) to get the `clientID` and `clientSecret` information. +* Specify a `callbackURL`, such as `http://127.0.0.1:7001/passport/github/callback` +   - You need to update to the corresponding domain name when deploying online +   - The path is configured via `options.callbackURL`, which defaults to `/passport/${strategy}/callback` + +### Mounting Routes + +```js +// app/router.js +Module.exports = app => { +  Const { router, controller } = app; + +  // Mount the authentication route +  App.passport.mount('github'); + +  // The mount above is syntactic sugar, which is equivalent to +  // const github = app.passport.authenticate('github', {}); +  // router.get('/passport/github', github); +  // router.get('/passport/github/callback', github); +} +``` + +### User Information Processing + +Then we also need: + +* When logging in for the first time, you generally need to put user information into the repository and record the Session. +* In the second login, the user information obtained from OAuth or Session, and the database is read to get the complete user information. + +```js +// app.js +Module.exports = app => { +  App.passport.verify(async (ctx, user) => { +    // Check user +    Assert(user.provider, 'user.provider should exists'); +    Assert(user.id, 'user.id should exists'); + +    // Find user information from the database +    // +    // Authorization Table +    // column | desc +    // --- | -- +    // provider | provider name, like github, twitter, facebook, weibo and so on +    // uid | provider unique id +    // user_id | current application user id +    Const auth = await ctx.model.Authorization.findOne({ +      Uid: user.id, +      Provider: user.provider, +    }); +    Const existsUser = await ctx.model.User.findOne({ id: auth.user_id }); +    If (existsUser) { +      Return existsUser; +    } +    // Call service to register a new user +    Const newUser = await ctx.service.user.register(user); +    Return newUser; +  }); + +  // Serialize and store the user information into session. Generally, only a few fields need to be streamlined/saved. +  app.passport.serializeUser(async (ctx, user) => { +  // process user +  // ... +  // return user; +  }); + +  // Deserialize the user information from the session, check the database to get the complete information +  app.passport.deserializeUser(async (ctx, user) => { +  // process user +  // ... +  // return user; +  }); +}; +``` + +At this point, we have completed all the configurations. For a complete example, see: [eggjs/examples/passport](https://github.com/eggjs/examples/tree/master/passport) + +### API + +[egg-passport](https://github.com/eggjs/egg-passport) provides the following extensions: + +* `ctx.user` - Get currently logged in user information +* `ctx.isAuthenticated()` - Check if the request is authorized +* `ctx.login(user, [options])` - Start a login session for the user +* `ctx.logout()` - Exit and clear user information from session +* `ctx.session.returnTo=` - Set redirect address after success before jumping to authentication + +The API also provides: + +* `app.passport.verify(async (ctx, user) => {})` - Check user +* `app.passport.serializeUser(async (ctx, user) => {})` - Serialize user information into session +* `app.passport.deserializeUser(async (ctx, user) => {})` - Deserialize user information from the session +* `app.passport.authenticate(strategy, options)` - Generate the specified authentication middleware +   - `options.successRedirect` - specifies the redirect address after successful authentication +   - `options.loginURL` - jump login address, defaults to `/passport/${strategy}` +   - `options.callbackURL` - callback address after authorization, defaults to `/passport/${strategy}/callback` +* `app.passport.mount(strategy, options)` - Syntactic sugar for developers to configure routing + +## Using Passport Ecosystem + +[Passport](http://www.passportjs.org/) has many middleware and it is impossible to carry out secondary packaging. +Next, let's look at how to use Passport middleware directly in the framework. +We will use [passport-local](https://github.com/jaredhanson/passport-local) for "account password login" as an example: + +### Installation + +```bash +$ npm i --save passport-local +``` + +### Configuration + +```js +// app.js +Const LocalStrategy = require('passport-local').Strategy; + +Module.exports = app => { +  // Mount strategy +  App.passport.use(new LocalStrategy({ +    passReqToCallback: true, +  }, (req, username, password, done) => { +    // format user +    Const user = { +      Provider: 'local', +      Username, +      Password, +    }; +    Debug('%s %s get user: %j', req.method, req.url, user); +    app.passport.doVerify(req, user, done); +  })); + +  // Process user information +  App.passport.verify(async (ctx, user) => {}); +  app.passport.serializeUser(async (ctx, user) => {}); +  app.passport.deserializeUser(async (ctx, user) => {}); +}; +``` + +### Mounting Routes + +```js +// app/router.js +Module.exports = app => { +  Const { router, controller } = app; +  Router.get('/', controller.home.index); + +  // Callback page after successful authentication +  Router.get('/authCallback', controller.home.authCallback); + +  // Render login page, user input account password +  Router.get('/login', controller.home.login); +  // Login verification +  Router.post('/login', app.passport.authenticate('local', { successRedirect: '/authCallback' })); +}; +``` + +## How to develop an egg-passport plugin + +In the previous section, we learned how to use a Passport middleware in the framework. We can further package it as a plugin and give back to the community. + +**initialization:** + +```bash +$ egg-init --type=plugin egg-passport-local +``` + +**Configure dependencies in `package.json`:** + +```json +{ + "name": "egg-passport-local", + "version": "1.0.0", + "eggPlugin": { + "name": "passportLocal", + "dependencies": ["passport"] + }, + "dependencies": { + "passport-local": "^1.0.0" + } +} +``` + +**Configuration:** + +```js +// {plugin_root}/config/config.default.js +// https://github.com/jaredhanson/passport-local +exports.passportLocal = {}; +``` + +Note: [egg-passport](https://github.com/eggjs/egg-passport) standardizes the configuration fields, which are unified as `key` and `secret`, so if the corresponding Passport middleware attribute names are inconsistent, the developer should perform the conversion. + +**Register the passport middleware:** + +```js +// {plugin_root}/app.js +Const LocalStrategy = require('passport-local').Strategy; + +Module.exports = app => { +  Const config = app.config.passportLocal; +  config.passReqToCallback = true; + +  App.passport.use(new LocalStrategy(config, (req, username, password, done) => { +    // Cleans up the data returned by the Passport plugin and returns the User object +    Const user = { +      Provider: 'local', +      Username, +      Password, +    }; +    // This does not process application-level logic and passes it to app.passport.verify for unified processing. +    app.passport.doVerify(req, user, done); +  })); +}; +``` + +[passport]: http://www.passportjs.org/ +[egg-passport]: https://github.com/eggjs/egg-passport +[passport-local]: https://github.com/jaredhanson/passport-local +[eggjs/examples/passport]: https://github.com/eggjs/examples/tree/master/passport From ea38866a8414115a3b08ec4cbb5b84a4f644bba2 Mon Sep 17 00:00:00 2001 From: Cemre MENGU Date: Mon, 19 Mar 2018 12:32:39 +0300 Subject: [PATCH 2/5] fixed bold header --- docs/source/en/tutorials/passport.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/en/tutorials/passport.md b/docs/source/en/tutorials/passport.md index 8125bcb155..3066540202 100644 --- a/docs/source/en/tutorials/passport.md +++ b/docs/source/en/tutorials/passport.md @@ -1,6 +1,6 @@ ## Title: Passport -** "Login authentication" ** is a common business scenario, including "account password login method" and "third-party unified login." +**`Login authentication`** is a common business scenario, including "account password login method" and "third-party unified login". Among them, we often use the latter, such as Google, GitHub, QQ unified login, which are based on [OAuth](https://oauth.net/2/) specification. From a212b1d5228114dca2d421745ce806341f694fc3 Mon Sep 17 00:00:00 2001 From: Cemre MENGU Date: Wed, 4 Apr 2018 19:22:39 +0300 Subject: [PATCH 3/5] Updated according to comments --- docs/source/en/tutorials/passport.md | 119 ++++++++++++------------ docs/source/zh-cn/tutorials/passport.md | 6 +- 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/docs/source/en/tutorials/passport.md b/docs/source/en/tutorials/passport.md index 3066540202..c0956da82e 100644 --- a/docs/source/en/tutorials/passport.md +++ b/docs/source/en/tutorials/passport.md @@ -1,20 +1,20 @@ ## Title: Passport -**`Login authentication`** is a common business scenario, including "account password login method" and "third-party unified login". +**`Login authentication`** is a common business scenario, including "account password login" and "third-party unified login". Among them, we often use the latter, such as Google, GitHub, QQ unified login, which are based on [OAuth](https://oauth.net/2/) specification. -[Passport](http://www.passportjs.org/) is a highly scalable authentication middleware that supports the `Strategy` of `Github` ,`Twitter`,`Facebook`, and other well-known service vendors. It also supports login and authorization verification via account passwords. +[Passport](http://www.passportjs.org/) is a highly scalable authentication middleware that supports the `Strategy` of `Github` ,`Twitter`,`Facebook`, and other well-known service vendors. It also supports login authorization verification. -Egg provides an [egg-passport](https://github.com/eggjs/egg-passport) plugin on top of it, encapsulating general logic such as callback processing after initialization and authentication success, allowing the developer to use Passport with just a few API calls. +Egg provides an [egg-passport](https://github.com/eggjs/egg-passport) plugin which encapsulates general logic such as callback processing after initialization and the success of authentication so that the developers can use Passport with just a few API calls. The execution sequence of [Passport](http://www.passportjs.org/) is as follows: -* User access page +* User accesses page * Check Session -* Intercept the login authentication login page +* Intercept and jump to authentication login page * Strategy Authentication -* Checksum storage of user information +* Check and store user information * Serialize user information to Session * Jump to the specified page @@ -37,14 +37,14 @@ For more plugins, see [GitHub Topic - egg-passport](https://github.com/topics/eg ```js // config/plugin.js -Exports.passport = { - Enable: true, - Package: 'egg-passport' +module.exports.passport = { + enable: true, + package: 'egg-passport' }; -exports.passportGithub = { - Enable: true, - Package: 'egg-passport-github' +module.exports.passportGithub = { + enable: true, + package: 'egg-passport-github' }; ``` @@ -55,14 +55,14 @@ Note: The [egg-passport](https://github.com/eggjs/egg-passport) standardizes the ```js // config/default.js config.passportGithub = { - Key: 'your_clientID', - Secret: 'your_clientSecret' + key: 'your_clientID', + secret: 'your_clientSecret' }; ``` **note:** -* Create a [GitHub OAuth App](https://github.com/settings/applications/new) to get the `clientID` and `clientSecret` information. +* Create a [GitHub OAuth Apps](https://github.com/settings/applications/new) to get the `clientID` and `clientSecret` information. * Specify a `callbackURL`, such as `http://127.0.0.1:7001/passport/github/callback`   - You need to update to the corresponding domain name when deploying online   - The path is configured via `options.callbackURL`, which defaults to `/passport/${strategy}/callback` @@ -71,11 +71,11 @@ config.passportGithub = { ```js // app/router.js -Module.exports = app => { -  Const { router, controller } = app; +module.exports = app => { +  const { router, controller } = app;   // Mount the authentication route -  App.passport.mount('github'); +  app.passport.mount('github');   // The mount above is syntactic sugar, which is equivalent to   // const github = app.passport.authenticate('github', {}); @@ -88,16 +88,16 @@ Module.exports = app => { Then we also need: -* When logging in for the first time, you generally need to put user information into the repository and record the Session. +* When signing in for the first time, you generally need to put user information into the repository and record the Session. * In the second login, the user information obtained from OAuth or Session, and the database is read to get the complete user information. ```js // app.js -Module.exports = app => { -  App.passport.verify(async (ctx, user) => { +module.exports = app => { +  app.passport.verify(async (ctx, user) => {     // Check user -    Assert(user.provider, 'user.provider should exists'); -    Assert(user.id, 'user.id should exists'); +    assert(user.provider, 'user.provider should exists'); +    assert(user.id, 'user.id should exists');     // Find user information from the database     // @@ -107,17 +107,17 @@ Module.exports = app => {     // provider | provider name, like github, twitter, facebook, weibo and so on     // uid | provider unique id     // user_id | current application user id -    Const auth = await ctx.model.Authorization.findOne({ -      Uid: user.id, -      Provider: user.provider, +    const auth = await ctx.model.Authorization.findOne({ +      uid: user.id, +      provider: user.provider,     }); -    Const existsUser = await ctx.model.User.findOne({ id: auth.user_id }); -    If (existsUser) { -      Return existsUser; +    const existsUser = await ctx.model.User.findOne({ id: auth.user_id }); +    if (existsUser) { +      return existsUser;     }     // Call service to register a new user -    Const newUser = await ctx.service.user.register(user); -    Return newUser; +    const newUser = await ctx.service.user.register(user); +    return newUser;   });   // Serialize and store the user information into session. Generally, only a few fields need to be streamlined/saved. @@ -142,13 +142,13 @@ At this point, we have completed all the configurations. For a complete example, [egg-passport](https://github.com/eggjs/egg-passport) provides the following extensions: -* `ctx.user` - Get currently logged in user information +* `ctx.user` - Get current logged in user information * `ctx.isAuthenticated()` - Check if the request is authorized * `ctx.login(user, [options])` - Start a login session for the user * `ctx.logout()` - Exit and clear user information from session -* `ctx.session.returnTo=` - Set redirect address after success before jumping to authentication +* `ctx.session.returnTo=` - Set redirect address after authentication page success -The API also provides: +The API also be provided for: * `app.passport.verify(async (ctx, user) => {})` - Check user * `app.passport.serializeUser(async (ctx, user) => {})` - Serialize user information into session @@ -161,7 +161,7 @@ The API also provides: ## Using Passport Ecosystem -[Passport](http://www.passportjs.org/) has many middleware and it is impossible to carry out secondary packaging. +[Passport](http://www.passportjs.org/) has many middleware and it is impossible to have the second encapsulation. Next, let's look at how to use Passport middleware directly in the framework. We will use [passport-local](https://github.com/jaredhanson/passport-local) for "account password login" as an example: @@ -175,25 +175,25 @@ $ npm i --save passport-local ```js // app.js -Const LocalStrategy = require('passport-local').Strategy; +const LocalStrategy = require('passport-local').Strategy; -Module.exports = app => { +module.exports = app => {   // Mount strategy -  App.passport.use(new LocalStrategy({ +  app.passport.use(new LocalStrategy({     passReqToCallback: true,   }, (req, username, password, done) => {     // format user -    Const user = { -      Provider: 'local', -      Username, -      Password, +    const user = { +      provider: 'local', +      username, +      password,     }; -    Debug('%s %s get user: %j', req.method, req.url, user); +    debug('%s %s get user: %j', req.method, req.url, user);     app.passport.doVerify(req, user, done);   }));   // Process user information -  App.passport.verify(async (ctx, user) => {}); +  app.passport.verify(async (ctx, user) => {});   app.passport.serializeUser(async (ctx, user) => {});   app.passport.deserializeUser(async (ctx, user) => {}); }; @@ -203,23 +203,23 @@ Module.exports = app => { ```js // app/router.js -Module.exports = app => { -  Const { router, controller } = app; -  Router.get('/', controller.home.index); +module.exports = app => { +  const { router, controller } = app; +  router.get('/', controller.home.index);   // Callback page after successful authentication -  Router.get('/authCallback', controller.home.authCallback); +  router.get('/authCallback', controller.home.authCallback); -  // Render login page, user input account password -  Router.get('/login', controller.home.login); +  // Render login page, user inputs account password +  router.get('/login', controller.home.login);   // Login verification -  Router.post('/login', app.passport.authenticate('local', { successRedirect: '/authCallback' })); +  router.post('/login', app.passport.authenticate('local', { successRedirect: '/authCallback' })); }; ``` ## How to develop an egg-passport plugin -In the previous section, we learned how to use a Passport middleware in the framework. We can further package it as a plugin and give back to the community. +In the previous section, we learned how to use a Passport middleware in the framework. We can further encapsulate it as a plugin and give back to the community. **initialization:** @@ -248,24 +248,25 @@ $ egg-init --type=plugin egg-passport-local ```js // {plugin_root}/config/config.default.js // https://github.com/jaredhanson/passport-local -exports.passportLocal = {}; +module.exports.passportLocal = { +}; ``` -Note: [egg-passport](https://github.com/eggjs/egg-passport) standardizes the configuration fields, which are unified as `key` and `secret`, so if the corresponding Passport middleware attribute names are inconsistent, the developer should perform the conversion. +Note: [egg-passport](https://github.com/eggjs/egg-passport) standardizes the configuration fields, which are unified as `key` and `secret`, so if the corresponding Passport middleware attribute names are inconsistent, the developer should do the conversion. **Register the passport middleware:** ```js // {plugin_root}/app.js -Const LocalStrategy = require('passport-local').Strategy; +const LocalStrategy = require('passport-local').Strategy; -Module.exports = app => { -  Const config = app.config.passportLocal; +module.exports = app => { +  const config = app.config.passportLocal;   config.passReqToCallback = true; -  App.passport.use(new LocalStrategy(config, (req, username, password, done) => { +  app.passport.use(new LocalStrategy(config, (req, username, password, done) => {     // Cleans up the data returned by the Passport plugin and returns the User object -    Const user = { +    const user = {       Provider: 'local',       Username,       Password, diff --git a/docs/source/zh-cn/tutorials/passport.md b/docs/source/zh-cn/tutorials/passport.md index 21d1a543b6..cde5b3527a 100644 --- a/docs/source/zh-cn/tutorials/passport.md +++ b/docs/source/zh-cn/tutorials/passport.md @@ -37,12 +37,12 @@ $ npm i --save egg-passport-github ```js // config/plugin.js -exports.passport = { +module.exports.passport = { enable: true, package: 'egg-passport', }; -exports.passportGithub = { +module.exports.passportGithub = { enable: true, package: 'egg-passport-github', }; @@ -253,7 +253,7 @@ $ egg-init --type=plugin egg-passport-local ```js // {plugin_root}/config/config.default.js // https://github.com/jaredhanson/passport-local -exports.passportLocal = { +module.exports.passportLocal = { }; ``` From f792b68a3f96c35783ab3bfcf56cfb18d33b5bfe Mon Sep 17 00:00:00 2001 From: Cemre MENGU Date: Mon, 9 Apr 2018 10:08:21 +0300 Subject: [PATCH 4/5] updated according to comments --- docs/source/en/tutorials/passport.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/en/tutorials/passport.md b/docs/source/en/tutorials/passport.md index c0956da82e..874c153382 100644 --- a/docs/source/en/tutorials/passport.md +++ b/docs/source/en/tutorials/passport.md @@ -4,7 +4,7 @@ Among them, we often use the latter, such as Google, GitHub, QQ unified login, which are based on [OAuth](https://oauth.net/2/) specification. -[Passport](http://www.passportjs.org/) is a highly scalable authentication middleware that supports the `Strategy` of `Github` ,`Twitter`,`Facebook`, and other well-known service vendors. It also supports login authorization verification. +[Passport](http://www.passportjs.org/) is a highly scalable authentication middleware that supports the `Strategy` of `Github` ,`Twitter`,`Facebook`, and other well-known service vendors. It also supports login authorization verification via account passwords. Egg provides an [egg-passport](https://github.com/eggjs/egg-passport) plugin which encapsulates general logic such as callback processing after initialization and the success of authentication so that the developers can use Passport with just a few API calls. @@ -248,7 +248,7 @@ $ egg-init --type=plugin egg-passport-local ```js // {plugin_root}/config/config.default.js // https://github.com/jaredhanson/passport-local -module.exports.passportLocal = { +exports.passportLocal = { }; ``` @@ -267,9 +267,9 @@ module.exports = app => {   app.passport.use(new LocalStrategy(config, (req, username, password, done) => {     // Cleans up the data returned by the Passport plugin and returns the User object     const user = { -      Provider: 'local', -      Username, -      Password, +      provider: 'local', +      username, +      password,     };     // This does not process application-level logic and passes it to app.passport.verify for unified processing.     app.passport.doVerify(req, user, done); From 61b6d320d07738efaa7f5f603d163c46ee945d8d Mon Sep 17 00:00:00 2001 From: Cemre MENGU Date: Mon, 9 Apr 2018 10:29:26 +0300 Subject: [PATCH 5/5] fix ch version --- docs/source/zh-cn/tutorials/passport.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/zh-cn/tutorials/passport.md b/docs/source/zh-cn/tutorials/passport.md index cde5b3527a..2b66ac03cd 100644 --- a/docs/source/zh-cn/tutorials/passport.md +++ b/docs/source/zh-cn/tutorials/passport.md @@ -253,7 +253,7 @@ $ egg-init --type=plugin egg-passport-local ```js // {plugin_root}/config/config.default.js // https://github.com/jaredhanson/passport-local -module.exports.passportLocal = { +exports.passportLocal = { }; ```