OAuth2orize - OAuth 2.0 Authorization Server Toolkit

1.12.0 · maintenance · verified Sun Apr 19

OAuth2orize is a Node.js toolkit designed for implementing OAuth 2.0 authorization servers. It provides a suite of modular middleware functions that allow developers to construct a server supporting various OAuth 2.0 grant types, such as authorization code, implicit, password, and client credentials, along with refresh token functionality. The library, currently at stable version 1.12.0, integrates seamlessly with Passport.js for user authentication, acting primarily as the authorization layer. Its architecture requires application-specific route handlers and persistent storage for clients, authorization codes, and access tokens, which are not provided out-of-the-box. Due to its long-standing stability and minimal recent updates (last published 2 years ago), it operates under a maintenance release cadence, indicating it's a mature project rather than one undergoing active feature development. A key differentiator is its highly pluggable middleware design, allowing granular control over the OAuth flow, though this also means more boilerplate compared to opinionated, full-stack solutions.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates a basic OAuth 2.0 authorization server setup using `oauth2orize` with Express and Passport, including authorization code grant and exchange. It includes mocked storage for clients, users, authorization codes, and access tokens to be runnable.

const express = require('express');
const oauth2orize = require('oauth2orize');
const passport = require('passport');
const BasicStrategy = require('passport-http').BasicStrategy;

// Mock database/storage for demonstration
const db = {
  clients: [{ id: 'client1', secret: 'secret1', redirectUri: 'http://localhost:3000/auth/example/callback' }],
  users: [{ id: 'user1', username: 'testuser', password: 'password' }],
  authorizationCodes: [],
  accessTokens: []
};

// Mock utility for UID generation
const utils = {
  uid: (len) => Math.random().toString(36).substring(2, 2 + len)
};

const app = express();
app.use(express.urlencoded({ extended: true })); // For parsing x-www-form-urlencoded
app.use(express.json()); // For parsing application/json
app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());

// Passport setup (simplified for example)
passport.use(new BasicStrategy(function(username, password, done) {
  const user = db.users.find(u => u.username === username && u.password === password);
  if (!user) { return done(null, false); }
  return done(null, user);
}));

passport.serializeUser(function(user, done) { done(null, user.id); });
passport.deserializeUser(function(id, done) {
  const user = db.users.find(u => u.id === id);
  done(null, user);
});

// Create OAuth 2.0 server
const server = oauth2orize.createServer();

// Register authorization code grant type
server.grant(oauth2orize.grant.code(function(client, redirectURI, user, ares, done) {
  const code = utils.uid(16);
  db.authorizationCodes.push({ code, clientId: client.id, redirectUri, userId: user.id, scope: ares.scope });
  done(null, code);
}));

// Register authorization code exchange type
server.exchange(oauth2orize.exchange.code(function(client, code, redirectURI, done) {
  const authCode = db.authorizationCodes.find(ac => ac.code === code && ac.clientId === client.id && ac.redirectUri === redirectURI);
  if (!authCode) { return done(null, false); }
  // Remove code after use (one-time use)
  db.authorizationCodes = db.authorizationCodes.filter(ac => ac.code !== code);

  const token = utils.uid(256);
  db.accessTokens.push({ token, userId: authCode.userId, clientId: authCode.clientId, scope: authCode.scope });
  done(null, token);
}));

// Authorization endpoint
app.get('/dialog/authorize',
  passport.authenticate('session'), // Ensure user is logged in via Passport session
  server.authorize(function(clientId, redirectURI, done) {
    const client = db.clients.find(c => c.id === clientId);
    if (!client) { return done(null, false); }
    if (client.redirectUri !== redirectURI) { return done(new Error('Invalid redirect URI'), false); }
    done(null, client, client.redirectUri);
  }),
  function(req, res) {
    // Render a consent dialog
    res.send(`
      <h1>Authorize ${req.oauth2.client.id} to access your account?</h1>
      <form action="/dialog/authorize/decision" method="POST">
        <input type="hidden" name="transaction_id" value="${req.oauth2.transactionID}">
        <input type="submit" value="Allow" name="allow">
        <input type="submit" value="Deny" name="deny">
      </form>
    `);
  }
);

// Decision endpoint
app.post('/dialog/authorize/decision',
  passport.authenticate('session'),
  server.decision()
);

// Token endpoint
app.post('/oauth/token',
  passport.authenticate(['basic', 'oauth2-client-password'], { session: false }),
  server.token(),
  server.errorHandler()
);

app.listen(3000, () => console.log('OAuth2orize server listening on port 3000'));

view raw JSON →