oauth2orize

repository·master·Indexed 26 days ago

https://github.com/jaredhanson/oauth2orize

An OAuth 2.0 authorization server toolkit for Node.js (version 1.12.0) that provides middleware to implement the OAuth 2.0 protocol. It is designed to work alongside authentication libraries like Passport.js and includes tools for creating servers, registering authorization grants, and managing token exchanges such as authorization code, client credentials, and password grants.

Tokens
7.3K
Snippets
17
Records
42
Agent score
86%

What's inside oauth2orize

  1. Implement API endpoints with bearer tokens

    master

    Once an access token is issued, protect your API routes using authentication middleware (e.g., passport-http-bearer) to validate the token provided in the request.

    app.get('/api/userinfo', 
      passport.authenticate('bearer', { session: false }),
      function(req, res) {
        res.json(req.user);
      });
  2. Implement the authorization endpoint

    master

    The authorization endpoint handles client requests for user permission. It typically involves:

    1. Authenticating the user (e.g., using connect-ensure-login).
    2. Using server.authorize() to validate the client and redirect URI.
    3. Rendering a UI for the user to approve or deny the request.
    4. Processing the user's decision using server.decision() middleware.
    // 1. The Authorization Request
    app.get('/dialog/authorize',
      login.ensureLoggedIn(),
      server.authorize(function(clientID, redirectURI, done) {
        Clients.findOne(clientID, function(err, client) {
          if (err) { return done(err); }
          if (!client) { return done(null, false); }
          if (client.redirectUri != redirectURI) { return done(null, false); }
          return done(null, client, client.redirectURI);
        });
      }),
      function(req, res) {
        res.render('dialog', { transactionID: req.oauth2.transactionID, 
                               user: req.user, client: req.oauth2.client });
      });
    
    // 2. The Decision Processing
    app.post('/dialog/authorize/decision',
       login.ensureLoggedIn(),
       server.decision());
  3. Implement the token endpoint

    master

    The token endpoint allows clients to exchange grants for access tokens. It should be protected by authentication middleware (like Passport strategies for Basic auth or client credentials) and use server.token() and server.errorHandler() middleware.

    app.post('/token',
      passport.authenticate(['basic', 'oauth2-client-password'], { session: false }),
      server.token(),
      server.errorHandler());
  4. Initialize the OAuth2orize Server

    master

    Create a new Server instance to manage OAuth 2.0 transactions. You can optionally provide a custom store in the options object to manage sessions. If no store is provided, it defaults to SessionStore.

    const Server = require('oauth2orize');
    const server = new Server({
      store: myCustomStore
    });
  5. Implement the Authorization Code Grant

    master

    To use the authorization code grant, you must provide an issue callback to oauth2orize.grant.code(). This callback is responsible for generating the authorization code after a user has approved the request.

    The issue Callback Signature

    The callback is invoked with the following arguments:

    • client: The client instance making the authorization request.
    • redirectURI: The redirect URI specified by the client (used as a verifier in the subsequent token exchange).
    • user: The authenticated user approving the request.
    • ares: An object containing additional parameters parsed from the user's decision (e.g., scope, duration of access).
    • done: A callback to issue the code. Signature: done(err, code).

    Implementation Example

    server.grant(oauth2orize.grant.code(function(client, redirectURI, user, ares, done) {
      // Your logic to create and store the authorization code
      AuthorizationCode.create(client.id, redirectURI, user.id, ares.scope, function(err, code) {
        if (err) { return done(err); }
        done(null, code);
      });
    }));
    server.grant(oauth2orize.grant.code(function(client, redirectURI, user, ares, done) {
      AuthorizationCode.create(client.id, redirectURI, user.id, ares.scope, function(err, code) {
        if (err) { return done(err); }
        done(null, code);
      });
    }));
  6. Configure client session serialization

    master

    Because OAuth 2.0 transactions involve multiple requests, you must register serialization and deserialization functions to persist client information in the session.

    server.serializeClient(function(client, done) {
      return done(null, client.id);
    });
    
    server.deserializeClient(function(id, done) {
      Clients.findOne(id, function(err, client) {
        return done(err, client);
      });
    });
  7. Register token exchanges

    master

    Exchanges allow a client to swap an authorization grant for an access token. Use server.exchange() with the appropriate exchange module, such as oauth2orize.exchange.code() for authorization codes.

    server.exchange(oauth2orize.exchange.code(function(client, code, redirectURI, done) {
      AuthorizationCode.findOne(code, function(err, code) {
        if (err) { return done(err); }
        if (client.id !== code.clientId) { return done(null, false); }
        if (redirectURI !== code.redirectUri) { return done(null, false); }
    
        var token = utils.uid(256);
        var at = new AccessToken(token, code.userId, code.clientId, code.scope);
        at.save(function(err) {
          if (err) { return done(err); }
          return done(null, token);
        });
      });
    }));
  8. Register authorization grants

    master

    Grants allow a client to obtain permission from a user. You must register a grant handler using server.grant(). For example, to support the authorization_code grant, use oauth2orize.grant.code().

    server.grant(oauth2orize.grant.code(function(client, redirectURI, user, ares, done) {
      var code = utils.uid(16);
    
      var ac = new AuthorizationCode(code, client.id, redirectURI, user.id, ares.scope);
      ac.save(function(err) {
        if (err) { return done(err); }
        return done(null, code);
      });
    }));
  9. Configure scope separators for Password Grant

    master

    By default, the password exchange middleware uses a space (' ') to separate scope values. To support multiple separators (e.g., allowing both spaces and commas for compatibility with different client libraries), pass an array to the scopeSeparator option.

    Note: The middleware will split the scope string based on the first matching separator found in the array, effectively creating a priority system.