There are four articles in this series

  • Introduction to Passport
  • The Passport document is provider dependent
  • Passport Document (3) Basics & Summary Describes authentication policies
  • Passport log in, log out, and authorize operations

The following text begins

www.passportjs.org/docs/downlo… The original address

An overview of

Passport is the authentication middleware for NodeJS. His sole design purpose is to validate the request. Writing modular, encapsulated code is a virtue, so Passport dispatches everything but the validation request to the application for implementation. Separation of concerns makes code cleaner and maintainable, while also making Passport easy to integrate into your application.

Now Web applications, authentication comes in many forms. Traditionally, users log in using their user names and passwords. With the rise of social networking, using OAuth’s single sign-on to sites such as Facebook or Twitter has become a popular way to authenticate. Services that expose an API usually require token-based certificates to protect access.

Passport recognizes that each application has its own unique authentication requirements. Authentication mechanisms, also known as policies, are packaged into separate modules. The application can choose the policy to adopt without creating unnecessary dependencies.

Regardless of the complexity of authentication, code can remain complex.

app.post('/login', passport.authentication('local', {successRedirect: '/'.failureRedirect: '/login'}));
Copy the code

The installation

npm install passport
Copy the code

certification

The authentication request is as simple as calling passport.Authenticate () and specifying which policy to use. Authenticate () ‘s functional signature is standard Connect middleware, so it can be easily used as routing middleware in Express applications.

app.post('/login',
    passport.authenticate('local'),
    function(req, res) {
        // If this function is called, authentication is successful.
        // 'req.user' contains the user for authentication
        res.redirect('/user', + req.user.username); })Copy the code

By default, if authentication fails, Passport returns 401 Unauthorized and subsequent other routing handlers will not execute. If the authentication succeeds, the next handler will call and the req.user property will be set to the authentication user.

Note: When using routing policies, you must configure them in advance. Read on to configure TODO in detail.

redirect

Redirects are usually issued after the authentication request.

app.post('/login',
    passport.authenticate('local', {
        successRedirect: '/'.failureRedirect: '/login',}))Copy the code

In this case, the redirection option overrides the default behavior. If successfully authenticated, the user is redirected to the home page. If authentication fails, the user is redirected back to the login page to try again.

Instant Messages (Flash Messages)

Redirects are often combined with instant messaging to display user status information.

app.post('/login',
    passport.authenticate('local', {
        successRedirect: '/'.failureRedirect: '/login'.failureFlash: true}); ;Copy the code

Setting the failureFlash option to true instructs Passport to send the error message from the policy validation callback. This is usually the best approach, because the validation callback is the most accurate way to determine why authentication failed.

Alternatively, instant messaging can be customized.

passport.authenticate('local', {
    failureFlash: 'Invalid username or password. '
})
Copy the code

The successFlash option sends a success message upon successful authentication.

passport.authenticate('local', {
    successFlash: 'welcome! '
})
Copy the code

Note: The req.flash() function is required to use instant messaging. Express 2.x provides this functionality, but has removed it in Express 3.x. When using Express 3.x, it is recommended to use the connect-Flash middleware, which provides this capability.

Ban Sessions

After successful authorization, Passport establishes a persistent login session. This is useful in scenarios where users access Web applications through a browser. However, in other cases, session support is not required. For example, API servers typically require each request to carry credentials. In this case, session support can be safely disabled by setting the session option to false.

app.get('/api/users/me',
    passport.authenticate('basic', { session: false }),
    function(req, res) {
        res.json({id: req.user.id, username: req.user.username}); })Copy the code

Custom callback

If internal options are not sufficient to handle authentication requests, custom callbacks enable the application to handle both success and failure.

app.get('/login'.function(req, res, next){
    passport.authenticate('local'.function(err, user, info) {
        if(err) {
            return next(err);
        }
        if(! user) {return res.redirect('/login');
        }
        req.logIn(user, function(err) {
            if(err) {
                return next(err)
            }
            return res.redirect('/users' + user.username)
        })
    })(req, res, next);
})
Copy the code

In this example, note that authenticate() is called in the routing processor, not as the routing middleware. This gives callback permissions to req and RES objects through closures.

If authentication fails, user will be set to false. If an exception occurs, err will be set. An optional INFO parameter is passed, including additional details provided by the policy validation callback.

This callback can process the expected authentication results with the parameters provided. Note that when using custom callbacks, the application is required to establish the session (by calling req.login()) and send the response.

configuration

Using Passport for authentication requires three configurations:

Authentication policy 2. Application middleware 3. Session (optional)

strategy

Passport uses something called a policy to authenticate the request. Policy secondary authentication user name and password, using OAuth authorization authentication or using OpenID federation authentication.

A policy (or policies) used by the application must be configured before Passport authentication requests can be made.

Policies and their configuration are provided through the use() function. For example, the following example uses LocalStrategy for username and password authentication.

var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
    function(username, password, done) {
        User.findOne({ username: username }, function (err, user) {
            if (err) {return done(err)}
            if(! user) {return done(null.false, { message: 'Wrong username'})}if(! user.validPassword(password)) {return done(null.false, { message: 'Password error'})}return done(null, user)
        })
    }
))
Copy the code

Validation callback

This example introduces an important concept. The policy requires something called a callback. The purpose of the validation callback is to find the user who has a set of credentials.

When Passport authenticates a request, it parses the credentials in the request. The credentials are then used as arguments to call the callback function, in this case username and password. If the credentials are valid, the callback function calls Done to pass the authenticated user’s information into Passport.

return done(null, user);
Copy the code

If the authentication fails (in this case, for example, with an incorrect password), the done function should pass false instead of user information to indicate that the authentication failed.

return done(null.false);
Copy the code

Additional messages can be provided to indicate the cause of the failure. This is useful for displaying instant messages to prompt the user to try again.

return done(null.false, { message: 'Password error' });
Copy the code

Finally, when an exception occurs while validating credentials (for example, the database service is unavailable), done should be called in normal Node operations to pass in an error message.

return done(err);
Copy the code

Note that it is important to distinguish between two situations in which failure can occur. The latter is a server exception in which err is set to a non-null value. It is also natural for authentication to fail when the server is running properly. Verify that err contains NULL and pass the details using the last parameter.

The validation callback delegates Passport without database support. Applications can decide how to store user information without any assumptions imposed by the validation layer.

The middleware

In Connect or Express-based applications, the passport needs to be initialized using the passport. Initialize () middleware. If your application uses a persistent login Session, the pasper.session () middleware will also need to use it.

app.configure(function() {
    app.use(express.static('public'));
    app.use(express.cookieParser());
    app.use(express.bodyParser());
    app.use(express.session({ secret: 'keyboard cat' }));
    app.use(passport.initialize());
    app.use(passport.session());
    app.use(app.router);
})
Copy the code

Note that enabling session support is completely optional, although it is recommended for most applications. If enabled, be sure to use session() before passport. Session () to ensure that login sessions are stored in the correct order.

In Express 4.x, Connect middleware is no longer included in the Express core module, and app.configure() has been removed. The same middleware can be found in the NPM module.

var session = require('express-session'),
    bodyParser = require('body-parser');

app.use(express.static('public'));
app.use(session({ secret: 'cats' }));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(passport.initialize());
app.use(passport.session());
Copy the code
Sessions session

In a regular Web application, credentials used to authenticate a user are sent only on a login request. If authentication is successful, a session is established and maintained by setting cookies in the browser.

Each subsequent request will no longer contain credentials, but will have a unique cookie to confirm the session. To support login sessions, Passport serializes and deserializes user instances through sessions.

passport.serializeUser(function(user, done) {
    done(null, user.id);
})

passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) { done(err, user); })})Copy the code

In this example, only the user ID is serialized into the session to keep the amount of data stored in the session small. This ID will be used to find the user stored in req.user when subsequent requests arrive.

Serialization and deserialization logic is provided by the application, allowing the application to select an appropriate database and/or object Mapper without the authentication layer imposing it.

User name and password

The most widely used way for websites to authenticate users is through a username and password. This mechanism is supported by providing the Passport -local module.

The installation

npm install passport-local
Copy the code

configuration

var passport = require('passport'),
    LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
    function(username, password, done) {
        User.findOne({ username: username }, function(err, user) {
            if(err) {
                return done(err)
            }
            if(! user) {return done(null.false, { message: 'Wrong username. '})}if(! user.validPassword(password)) {return done(null.false, { message: 'Password error. '})}return done(null, user); }})))Copy the code

The local authentication callback accepts username and password arguments, which are submitted via the application’s login form.

The form

A form on a Web page that allows users to enter their credentials and log in.

<form action="/login" method="post">
    <div>
        <label>Username:</label>
        <input type="text" name="username"/>
    </div>
    <div>
        <label>Password:</label>
        <input type="password" name="password"/>
    </div>
    <div>
        <input type="submit" value="Log In"/>
    </div>
</form>
Copy the code

routing

The login form is submitted to the server via POST. Use the Authenticate function of the local policy to process the login request.

app.post('/login',
    passport.authenticate('local', {
        successRedirect: '/'.failureRedirect: '/login'.failureFlash: true}))Copy the code

Setting the failureFlash option to true indicates that Passport uses the Message option provided by the validation callback to send an error message. This is useful for prompting the user to try again.

parameter

By default, LocalStrategy expects to find credentials named username and Password in the parameters. If your site would prefer a different field name, there are options available to change the default value.

passport.use(new LocalStrategy({
    usernameField: 'email'.passwordField: 'passwd',},function(username, password, done) {
    // ...}))Copy the code

OpenID

OpenID is an open standard for federated authentication. When accessing a site, the user logs in using OpenID. Users are authenticated by their choice of the OpenID provider, which issues an assertion to confirm the user’s identity. The site validates this assertion to get the user to log in.

OpenID support is provided through the Passport – OpenID module.

The installation

npm install passport-openid
Copy the code

configuration

When using OpenID, the return address and domain must be set. ReturnURL is the address to which the user is redirected after authentication with the OpenID provider. Realm indicates the part of the URL space where validation is valid. Usually it will be the root URL of the site.

var passport = require('passport'),
    OpenIDStrategy = require('passport-openid').Strategy;

passport.use(new OpenIDStrategy({
    returnURL: 'http://www.example.com/auth/openid/return'.realm: 'http://www.example.com/'
},
function(identifier, done) {
    User.findOrCreate({openId: identifier}, function(err, user) { done(err, user); }})))Copy the code

The validation callback for OpenID authentication accepts an identifier parameter that contains the user’s declaration identifier.

The form

A form for the Web page that allows the user to enter OpenID and then log in.

<form action="/auth/openid" method="post">
    <div>
        <label>OpenID:</label>
        <input type="text" name="openid_identifier"/><br/>
    </div>
    <div>
        <input type="submit" value="Sign In"/>
    </div>
</form>
Copy the code

routing

Two routes are required for OpenID authentication. The first route accepts the OpenId identifier included in the form submission. During authentication, the user will be redirected to the OpenID provider. The second route is the URL that the user will return after authentication with the OpenID provider.

// Accept the OpenID id and redirect the user to the OpenID provider for authentication. When done, the provider redirects the user to the application:
// /auth/openid/return
app.post('/auth/openid', passport.authenticate('openid'));

// The OpenID provider has redirected the user to the application.
// Complete the authentication process by validating assertions. If valid, the user logs in.
// Otherwise, the authentication fails.
app.get('/auth/openid/return', 
    passport.authenticate('openid', {
        successRedirect: '/'.failureRedirect: '/login',}))Copy the code

Personal Data exchange

OpenID can optionally be set to retrieve the personal information of an authenticated user. The profile exchange is enabled by setting the Profile option to true.

passport.use(new OpenIDStrategy({
    returnURL: 'http://www.example.com/auth/openid/return'.realm: 'http://www.example.com/'.profile: true
},
function(identifier, profile, done) {
    // ...}))Copy the code

When profile exchange is enabled, the validation callback function signs up to receive additional profile parameters, including the user profile provided by the OpenID provider; Learn more from the User Profile.

OAuth

OAuth is a standard protocol that allows users to license apis to websites, desktop applications, or mobile applications. Once authorized, the authorized application can use the API on behalf of the user. OAuth has also become a popular delegation mechanism.

OAuth comes in two main forms, both of which are widely deployed.

The original version of OAuth was developed as an open standard by a loosely knit group of Web developers. They developed OAuth 1.0, which was replaced by OAuth 1.0a. This work is now being standardized by IEFT as RFC 5849.

Recent work, focused on defining OAuth 2.0, has been undertaken by the Web Licensing Protocol Working Group. As a result of long standardization efforts, providers have begun to deploy implementations that conform to various drafts, each with slightly different semantics.

Thankfully, Passport insulates the application from the complexity of handling OAuth variants. In many cases, providers for a particular policy can be used. Rather than the generic strategy described below. This reduces the configuration required and accommodates the specific quirks of any provider. Check Facebook, Twitter, or a list of providers for preferred usage.

OAuth support is achieved through the Passport – OAuth module

The installation

npm install passport-oauth
Copy the code

The 1.0

OAuth 1.0 is a multi-step proxy authentication policy. First, you need to get the request token. The user is then redirected to the service provider for authorization. Finally, after authorization, the user is redirected back to the application and requests tokens that can be exchanged for access tokens. Applications requesting access (called consumers) are identified by consumer Key and consumer Secret.

configuration

Key, secret, and endpoints are defined as options when using the generic OAuth policy.

var passport = require('passport'),
    OAuthStrategy = require('passport-oauth').OAuthStrategy;

passport.use('provider'.new OAuthStrategy({
    requestTokenURL: 'https://www.provider.com/oauth/request_token'.accessTokenURL: 'https://www.provider.com/oauth/access_token'.userAuthorizationURL: 'https://www.provider.com/oauth/authorize'.consumerKey: '123-456-789'.consumerSecret: 'shhh-its-a-secret'.callbackURL: 'https://www.example.com/auth/provider/callback'
},
function(token, tokenSecret, profile, done) { User.findOrCreate(... .function(err, user) { done(err, user); }})))Copy the code

Validation callbacks based on OAuth policies accept token, tokenSecret, and Profile parameters. Token is an access token, and tokenSecret is its corresponding secret key. Profiles contain user personal information provided by service providers. Learn more from the User Profile.

routing

OAuth authentication requires two routes. The first route initiates an OAuth exchange and redirects the user to the service provider. The second route is a URL to which the user is redirected after the provider authenticates.

// Redirect the user to the OAuth provider for authentication. When the certification is complete,
// The provider redirects the user back to the application:
// /auth/provider/callback
app.get('/auth/provider', passport.authenticate('provider'));

// The OAuth provider has redirected the user back to the application.
// End the authentication process by obtaining an access token. If authorized, the user logs in.
// Otherwise, the authentication fails.
app.get('/auth/provider/callback',
    passport.authenticate('provider', {
        successRedirect: '/'.failureRedirect: '/login'}))Copy the code

link

A link or button can be placed on a web page that, when clicked, will begin the authentication process.

<a href="/auth/provider">Log in using the OAuth provider</a>
Copy the code

The 2.0

OAuth 2.0 is the successor to OAuth 1.0 and is designed to overcome the known shortcomings of earlier versions. The certification process is essentially the same. The user is first redirected to the service provider for authorization. After authorization, the user is redirected back to the application with a code that can obtain access token. The application requesting access (as a client) is identified by an ID and a secret key.

configuration

When using the generic OAuth 2.0 policy, client ID, Client Secret, and endpoints are defined as options.

var passport = require('passport'),
    OAuth2Strategy = require('passport-oauth').OAuth2Strategy;

passport.use('provider'.new OAuth2Strategy({
    authorizationURL: ' '.tokenURL: ' '.clientID: ' '.clientSecret: ' '.callbackURL: ' ',},function(accessToken, refreshToken, profile, done) { User.findOrCreate(... .function(err, user) { done(err, user); }})))Copy the code

The validation callback based on the OAuth 2.0 policy accepts accessToken, refreshToken, and profile parameters. RefreshToken can be used to obtain a new access token, or undefined if the provider does not issue a refreshToken. The profile will contain the user’s personal information provided by the service provider. Check out the User Profile for more information.

routing

OAuth 2.0 authentication requires two routes. The first route redirects the user to the service provider. The second route is a URL that the user is redirected to after authentication at the provider.

// Redirect users to OAuth 2.0 authentication providers.
// When authentication is complete, the provider redirects the user back to the application:
// /auth/provider/callback
app.get('/auth/provider', passport.authenticate('provider'));

The OAuth 2.0 provider has redirected the user to the application.
// Complete the authentication process by trying to obtain an access token.
// If authorized, the user logs in.
// Otherwise, the authentication fails.
app.get('/auth/provider/callback', 
    passport.authenticate('provider', {
        successRedirect: '/'.failureRedirect: '/login',}))Copy the code

scope

When requesting access using OAuth 2.0, the scope of the access is controlled by the Scope option.

app.get('/auth/provider',
    passport.authenticate('provider', { scope: 'email'}))Copy the code

The ability to define multiple scopes using arrays.

app.get('/auth/provider',
    passport.authenticate('provider', { scope: ['email'.'sms']}))Copy the code

The value of the scope option is provider specific. Refer to the provider documentation for details about the scope of the support.

link

A link or button on a Web page that, when clicked, can begin the authentication process.

<a href="/auth/provider"> use request2.0Provider login </a>Copy the code

User Personal Information

Personal information is usually available when authenticated using third-party services such as Facebook or Twitter. Each service tends to encode this information in a different way. Passport standardizes personal information as much as possible for easier integration.

The normalized personal information conforms to the contact pattern established by [Joseph Smarr][schema-author]. The following table summarizes the public fields available.

provider {String}

Provider, user authentication place (Facebook, Twitter, etc.).

id {String}

The unique identity of the user, typically generated by the service provider.

displayName {String}

User name, suitable for display

name {Object}

FamilyName The user’s family name, or “last name” in most Western languages.

GivenName The given name of the user, or “first name” in most Western languages.

MiddleName Middle name of the user.

emails {Array} [n]

Value {String} Specifies the email address of the address.

Type {String} Email address type (home, work, etc.).

photos {Array} [n]

Value {String} Image address

Note that not all of the above fields are available from every service provider. Some providers may contain additional information not listed here. Refer to your specific provider’s documentation for more details.

reference

  • Developer.mozilla.org/zh-CN/docs/… function signature

Thank you for reading

Thank you for reading here, the translation of the bad place, please also give advice. I hope you can enjoy my content. Thank you again. By llccing li