### Install oauth2-server Source: https://github.com/oauthjs/node-oauth2-server/blob/master/README.md Use npm to install the oauth2-server package into your project. ```bash npm install oauth2-server ``` -------------------------------- ### Run tests for oauth2-server Source: https://github.com/oauthjs/node-oauth2-server/blob/master/README.md Install project dependencies and execute the test suite. ```bash npm install npm test ``` -------------------------------- ### Instantiate OAuthError Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/oauth-error.rst Examples of creating OAuthError instances with various configurations. ```javascript const err = new OAuthError(); // err.message === 'Internal Server Error' // err.code === 500 // err.name === 'OAuthError' ``` ```javascript const err = new OAuthError('test', {name: 'test_error'}); // err.message === 'test' // err.code === 500 // err.name === 'test_error' ``` ```javascript const err = new OAuthError(undefined, {code: 404}); // err.message === 'Not Found' // err.code === 404 // err.name === 'OAuthError' ``` ```javascript const err = new OAuthError('test', {foo: 'bar', baz: 1234}); // err.message === 'test' // err.code === 500 // err.name === 'OAuthError' // err.foo === 'bar' // err.baz === 1234 ``` ```javascript const anotherError = new Error('test'); const err = new OAuthError(e); // err.message === 'test' // err.code === 500 // err.name === 'OAuthError' // err.inner === anotherError ``` -------------------------------- ### Implement an authenticate handler Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/oauth2-server.rst An example of an `authenticateHandler` object with a `handle` function. This handler is used to retrieve the authenticated user. It can be a simple object or leverage session data. ```javascript let authenticateHandler = { handle: function(request, response) { return /* get authenticated user */; } }; let authenticateHandler = { handle: function(request, response) { return request.session.user; } }; ``` -------------------------------- ### Instantiating InvalidArgumentError Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/invalid-argument-error.rst Example of creating a new instance of the error and verifying its default properties. ```javascript const err = new InvalidArgumentError(); // err.message === 'Internal Server Error' // err.code === 500 // err.name === 'invalid_argument' ``` -------------------------------- ### get(field) Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/response.rst Retrieves the value of a specific HTTP header field. ```APIDOC ## get(field) ### Description Returns the specified HTTP header field. The match is case-insensitive. ### Parameters #### Path Parameters - **field** (String) - Required - The header field name. ### Response - **value** (String|undefined) - The value of the header field or undefined if the field does not exist. ``` -------------------------------- ### Constructor: new OAuth2Server(options) Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/oauth2-server.rst Instantiates a new OAuth2Server instance using a provided model and optional configuration settings. ```APIDOC ## new OAuth2Server(options) ### Description Instantiates the OAuth2Server using the supplied model and optional configuration. ### Parameters #### Request Body - **options** (Object) - Required - Server options. - **options.model** (Object) - Required - The model implementation. ### Request Example { "model": "require('./model')", "allowBearerTokensInQueryString": true, "accessTokenLifetime": 14400 } ``` -------------------------------- ### Implement Model Functions with Asynchronous Patterns Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Demonstrates how to define model functions using promises, callbacks, generators, and async/await, and how to initialize the OAuth2Server instance. ```javascript const model = { // We support returning promises. getAccessToken: function() { return new Promise('works!'); }, // Or, calling a Node-style callback. getAuthorizationCode: function(done) { done(null, 'works!'); }, // Or, using generators. getClient: function*() { yield somethingAsync(); return 'works!'; }, // Or, async/wait (using Babel). getUser: async function() { await somethingAsync(); return 'works!'; } }; const OAuth2Server = require('oauth2-server'); let oauth = new OAuth2Server({model: model}); ``` -------------------------------- ### Initialize OAuth2Server Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/docs/getting-started.rst Create a new instance of the server by providing a model object. ```javascript const OAuth2Server = require('oauth2-server'); const oauth = new OAuth2Server({ model: require('./model') }); ``` -------------------------------- ### Getting an HTTP Header Field Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/request.rst Retrieve the value of a specified HTTP header field. The match is case-insensitive. ```javascript request.get(field); ``` -------------------------------- ### Request#get(field) Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/request.rst Retrieves the value of a specified HTTP header field. The header field matching is case-insensitive. ```APIDOC ## `get(field)` Returns the specified HTTP header field. The match is case-insensitive. ### Parameters #### Path Parameters - **field** (String) - Required - The header field name. ### Return value The value of the header field or ``undefined`` if the field does not exist. ``` -------------------------------- ### Implement getClient() Model Method Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Retrieves client information from the database for authentication and validation. Required for all grant types. ```javascript const model = { getClient: async function(clientId, clientSecret) { // Query your database for the client const client = await db.query( 'SELECT * FROM oauth_clients WHERE client_id = $1', [clientId] ); if (!client) return null; // Verify secret if provided (null for public clients) if (clientSecret && client.client_secret !== clientSecret) { return null; } return { id: client.client_id, redirectUris: client.redirect_uris, // Array of allowed redirect URIs grants: client.grants, // ['authorization_code', 'password', 'refresh_token'] accessTokenLifetime: client.access_token_lifetime || 3600, refreshTokenLifetime: client.refresh_token_lifetime || 1209600 }; } }; ``` -------------------------------- ### Import Response class Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/response.rst Initializes the Response class from the oauth2-server package. ```javascript const Response = require('oauth2-server').Response; ``` -------------------------------- ### new Response(options) Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/response.rst Instantiates a new Response object with headers and body data. ```APIDOC ## new Response(options) ### Description Instantiates a new Response object using the supplied options. ### Parameters #### Request Body - **options** (Object) - Required - Response options. - **options.headers** (Object) - Required - The response's HTTP header fields. - **options.body** (Object) - Optional - Key-value pairs of data to be submitted in the response body (default: {}). ### Response - **Response** (Instance) - A new Response instance. ``` -------------------------------- ### Disable Client Secret for Password Grant Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/oauth2-server.rst Use `options.requireClientAuthentication` to disable the client secret requirement for specific grant types. This example shows how to allow token requests using the password grant without a client secret. ```javascript let options = { // ... // Allow token requests using the password grant to not include a client_secret. requireClientAuthentication: {password: false} }; ``` -------------------------------- ### Instantiate OAuth2Server with Options Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/oauth2-server.rst Instantiate OAuth2Server with additional options such as allowing bearer tokens in the query string and setting the access token lifetime. ```javascript const oauth = new OAuth2Server({ model: require('./model'), allowBearerTokensInQueryString: true, accessTokenLifetime: 4 * 60 * 60 }); ``` -------------------------------- ### Get Client Information Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst This model function is required for all grant types. It retrieves client details using either a client ID or a combination of client ID and secret. It returns an object representing the client or a falsy value if not found. ```javascript getClient(clientId, clientSecret, [callback]) ``` -------------------------------- ### Model Function Signatures and Support Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Demonstrates the various ways model functions can be implemented, supporting promises, Node-style callbacks, ES6 generators, and async/await. ```APIDOC ## Model Function Signatures and Support ### Description Each model function supports promises, Node-style callbacks, ES6 generators, and async/await (using Babel). Promise support implies support for returning plain values where asynchronism is not required. ### Code Example ```javascript const model = { // Promise support getAccessToken: function() { return new Promise('works!'); }, // Node-style callback support getAuthorizationCode: function(done) { done(null, 'works!'); }, // Generator support getClient: function*() { yield somethingAsync(); return 'works!'; }, // Async/await support (using Babel) getUser: async function() { await somethingAsync(); return 'works!'; } }; const OAuth2Server = require('oauth2-server'); let oauth = new OAuth2Server({model: model}); ``` ### Notes Code examples on this page use promises. ``` -------------------------------- ### Instantiating a Request Object Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/request.rst Instantiate a new Request object using supplied options. All additional own properties are copied to the new Request object. Header field names are converted to lower case. ```javascript var request = new Request(req); ``` -------------------------------- ### Server Options Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/misc/migrating-v2-to-v3.rst Configuration options available when instantiating the OAuth service. Includes default values and changes in v3.0.0. ```APIDOC ## Server Options ### Description The following server options can be set when instantiating the OAuth service: * `addAcceptedScopesHeader`: **default true** Add the `X-Accepted-OAuth-Scopes` header with a list of scopes that will be accepted * `addAuthorizedScopesHeader`: **default true** Add the `X-OAuth-Scopes` header with a list of scopes that the user is authorized for * `allowBearerTokensInQueryString`: **default false** Determine if the bearer token can be included in the query string (i.e. `?access_token=`) for validation calls * `allowEmptyState`: **default false** If true, `state` can be empty or not passed. If false, `state` is required. * `authorizationCodeLifetime`: **default 300** Default number of seconds that the authorization code is active for * `accessTokenLifetime`: **default 3600** Default number of seconds that an access token is valid for * `refreshTokenLifetime`: **default 1209600** Default number of seconds that a refresh token is valid for * `allowExtendedTokenAttributes`: **default false** Allows additional attributes (such as `id_token`) to be included in token responses. * `requireClientAuthentication`: **default true for all grant types** Allow ability to set client/secret authentication to `false` for a specific grant type. ### Changed Behavior in v3.0.0 * `accessTokenLifetime` can no longer be set to `null` to indicate a non-expiring token. The recommend alternative is to set `accessTokenLifetime` to a high value. ### Removed in v3.0.0 * `grants`: **removed** (now returned by the `getClient` method). * `debug`: **removed** (not the responsibility of this module). * `clientIdRegex`: **removed** (the `getClient` method can return `undefined` or throw an error). * `passthroughErrors`: **removed** (not the responsibility of this module). * `continueAfterResponse`: **removed** (not the responsibility of this module). ``` -------------------------------- ### Instantiate OAuth2Server with Model Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/oauth2-server.rst Create a new OAuth2Server instance, providing the model object which defines the OAuth2 logic. ```javascript const oauth = new OAuth2Server({ model: require('./model') }); ``` -------------------------------- ### Implement getClient Model Function Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Retrieves a client object from the database. The returned object must include id, redirectUris, and grants. ```javascript function getClient(clientId, clientSecret) { // imaginary DB query let params = {client_id: clientId}; if (clientSecret) { params.client_secret = clientSecret; } db.queryClient(params) .then(function(client) { return { id: client.id, redirectUris: client.redirect_uris, grants: client.grants }; }); } ``` -------------------------------- ### Implement Custom Token Generation Methods Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Optional methods to customize the generation of access tokens, refresh tokens, and authorization codes. ```javascript const crypto = require('crypto'); const model = { generateAccessToken: async function(client, user, scope) { // Generate JWT or custom token format return crypto.randomBytes(32).toString('hex'); }, generateRefreshToken: async function(client, user, scope) { return crypto.randomBytes(32).toString('hex'); }, generateAuthorizationCode: async function(client, user, scope) { return crypto.randomBytes(16).toString('hex'); } }; ``` -------------------------------- ### Create Request and Response Objects Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/docs/getting-started.rst Instantiate Request and Response objects for handling incoming HTTP traffic. ```javascript const Request = OAuth2Server.Request; const Response = OAuth2Server.Response; let request = new Request({/*...*/}); let response = new Response({/*...*/}); ``` -------------------------------- ### Handle Request Objects Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Wrap framework-specific request objects or create them manually for testing purposes. ```javascript const Request = OAuth2Server.Request; // Create from Express request function middleware(req, res, next) { const request = new Request(req); // request.method, request.query, request.headers, request.body are available } // Create manually for testing const request = new Request({ method: 'POST', query: {}, headers: { 'Authorization': 'Bearer abc123token', 'Content-Type': 'application/x-www-form-urlencoded' }, body: { grant_type: 'password', username: 'johndoe', password: 'secret123' } }); // Access header values (case-insensitive) const authHeader = request.get('authorization'); const contentType = request.is('application/x-www-form-urlencoded'); ``` -------------------------------- ### Complete OAuth2 Server Model Implementation Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt This model provides all necessary and optional methods for handling OAuth2 grants. It requires a database connection and bcrypt for secure password comparisons. Use this as a blueprint for your OAuth2 server's data and logic layer. ```javascript const crypto = require('crypto'); const bcrypt = require('bcrypt'); const model = { // Required for all grants getClient: async function(clientId, clientSecret) { const client = await db.clients.findOne({ clientId }); if (!client) return null; if (clientSecret && !await bcrypt.compare(clientSecret, client.secretHash)) { return null; } return { id: client.clientId, redirectUris: client.redirectUris, grants: client.grants }; }, // Required for password grant getUser: async function(username, password) { const user = await db.users.findOne({ username }); if (!user || !await bcrypt.compare(password, user.passwordHash)) { return null; } return { id: user.id, username: user.username }; }, // Required for client_credentials grant getUserFromClient: async function(client) { return { id: client.id, isClient: true }; }, // Required for all grants saveToken: async function(token, client, user) { const savedToken = await db.tokens.create({ accessToken: token.accessToken, accessTokenExpiresAt: token.accessTokenExpiresAt, refreshToken: token.refreshToken, refreshTokenExpiresAt: token.refreshTokenExpiresAt, scope: token.scope, clientId: client.id, userId: user.id }); return { ...token, client: { id: client.id }, user: { id: user.id } }; }, // Required for authenticate() getAccessToken: async function(accessToken) { const token = await db.tokens.findOne({ accessToken }); if (!token) return null; return { accessToken: token.accessToken, accessTokenExpiresAt: token.accessTokenExpiresAt, scope: token.scope, client: { id: token.clientId }, user: { id: token.userId } }; }, // Required for refresh_token grant getRefreshToken: async function(refreshToken) { const token = await db.tokens.findOne({ refreshToken }); if (!token) return null; return { refreshToken: token.refreshToken, refreshTokenExpiresAt: token.refreshTokenExpiresAt, scope: token.scope, client: { id: token.clientId }, user: { id: token.userId } }; }, revokeToken: async function(token) { const result = await db.tokens.deleteOne({ refreshToken: token.refreshToken }); return result.deletedCount > 0; }, // Required for authorization_code grant saveAuthorizationCode: async function(code, client, user) { await db.authCodes.create({ ...code, clientId: client.id, userId: user.id }); return { ...code, client: { id: client.id }, user: { id: user.id } }; }, getAuthorizationCode: async function(authorizationCode) { const code = await db.authCodes.findOne({ authorizationCode }); if (!code) return null; return { code: code.authorizationCode, expiresAt: code.expiresAt, redirectUri: code.redirectUri, scope: code.scope, client: { id: code.clientId }, user: { id: code.userId } }; }, revokeAuthorizationCode: async function(code) { const result = await db.authCodes.deleteOne({ authorizationCode: code.code }); return result.deletedCount > 0; }, // Optional scope validation validateScope: async function(user, client, scope) { return scope || ''; }, verifyScope: async function(token, scope) { const required = scope.split(' '); const authorized = (token.scope || '').split(' '); return required.every(s => authorized.includes(s)); } }; module.exports = model; ``` -------------------------------- ### Complete Express.js OAuth2 Server Integration Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Sets up an Express server with token, authorization, and protected resource endpoints using oauth2-server. Requires a model implementation and body-parser middleware. ```javascript const express = require('express'); const bodyParser = require('body-parser'); const OAuth2Server = require('oauth2-server'); const Request = OAuth2Server.Request; const Response = OAuth2Server.Response; const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); const oauth = new OAuth2Server({ model: require('./model'), accessTokenLifetime: 3600, refreshTokenLifetime: 1209600 }); // Token endpoint - handles all grant types app.post('/oauth/token', (req, res, next) => { const request = new Request(req); const response = new Response(res); oauth.token(request, response) .then(token => { res.json(response.body); }) .catch(next); }); // Authorization endpoint app.get('/oauth/authorize', (req, res) => { // Render authorization form (user must be logged in) res.render('authorize', { query: req.query }); }); app.post('/oauth/authorize', (req, res, next) => { const request = new Request(req); const response = new Response(res); oauth.authorize(request, response, { authenticateHandler: { handle: (req) => req.session.user } }) .then(code => { res.redirect(response.headers.location); }) .catch(next); }); // Protected resource app.get('/api/me', (req, res, next) => { const request = new Request(req); const response = new Response(res); oauth.authenticate(request, response) .then(token => { res.json({ user: token.user }); }) .catch(next); }); app.listen(3000, () => console.log('OAuth2 server running on port 3000')); ``` -------------------------------- ### Request Constructor Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/request.rst Instantiates a new Request object using the supplied options. It can be used to convert native request objects (like Express's req) into the OAuth2 server's Request format. ```APIDOC ## `new Request(options)` Instantiates ``Request`` using the supplied options. ### Parameters #### Request Body - **options** (Object) - Required - Request options. - **options.method** (String) - The HTTP method of the request. - **options.query** (Object) - The request's query string parameters. - **options.headers** (Object) - The request's HTTP header fields. - **options.body** (Object) - Optional - Key-value pairs of data submitted in the request body. Defaults to `{}`. All additional own properties are copied to the new ``Request`` object as well. ### Remarks The names of HTTP header fields passed in as ``options.headers`` are converted to lower case. To convert `Express' request`_ to a ``Request`` simply pass ``req`` as ``options``: :: function(req, res, next) { var request = new Request(req); // ... } ``` -------------------------------- ### OAuthError Constructor Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/oauth-error.rst Details on how to instantiate the OAuthError class, including its arguments and default values. ```APIDOC ## new OAuthError(message, properties) ### Description Instantiates OAuthError. This class is intended to be used as a base class, and direct instantiation is not recommended. Use derived error types instead. ### Method `new OAuthError(message, properties)` ### Parameters #### Arguments - **message** (String|Error) - Optional - The error message or a nested exception. - **properties** (Object) - Optional - Additional properties to set on the error object. - **properties.code** (Object) - Optional - An HTTP status code associated with the error. Defaults to 500. - **properties.name** (String) - Optional - The name of the error. Defaults to the constructor's name if not provided. ### Return value A new instance of OAuthError. ### Remarks - By default, `code` is set to `500` and `message` to 'Internal Server Error'. - All additional properties passed in the `properties` object are copied to the error instance. - When wrapping an exception, the `message` is copied from the existing exception, and the `inner` property is set. ### Request Example ```javascript const err = new OAuthError(); // err.message === 'Internal Server Error' // err.code === 500 // err.name === 'OAuthError' const errWithMessageAndName = new OAuthError('test', { name: 'test_error' }); // errWithMessageAndName.message === 'test' // errWithMessageAndName.code === 500 // errWithMessageAndName.name === 'test_error' const errWithCode = new OAuthError(undefined, { code: 404 }); // errWithCode.message === 'Not Found' // errWithCode.code === 404 // errWithCode.name === 'OAuthError' const errWithCustomProperties = new OAuthError('test', { foo: 'bar', baz: 1234 }); // errWithCustomProperties.message === 'test' // errWithCustomProperties.code === 500 // errWithCustomProperties.name === 'OAuthError' // errWithCustomProperties.foo === 'bar' // errWithCustomProperties.baz === 1234 const anotherError = new Error('test'); const errWrappingException = new OAuthError(anotherError); // errWrappingException.message === 'test' // errWrappingException.code === 500 // errWrappingException.name === 'OAuthError' // errWrappingException.inner === anotherError ``` ``` -------------------------------- ### Instantiate UnsupportedResponseTypeError Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/unsupported-response-type-error.rst Create a new instance of the error. The default code is 400 and the name is 'unsupported_response_type'. ```javascript const err = new UnsupportedResponseTypeError(); // err.message === 'Bad Request' // err.code === 400 // err.name === 'unsupported_response_type' ``` -------------------------------- ### Implement getUser() Model Method Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Validates user credentials against a database. Required for the password grant type. ```javascript const bcrypt = require('bcrypt'); const model = { getUser: async function(username, password) { const user = await db.query( 'SELECT * FROM users WHERE username = $1', [username] ); if (!user) return null; const validPassword = await bcrypt.compare(password, user.password_hash); if (!validPassword) return null; return { id: user.id, username: user.username, email: user.email }; } }; ``` -------------------------------- ### Implement getUserFromClient() Model Method Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Returns the user associated with a client. Required for the client_credentials grant type. ```javascript const model = { getUserFromClient: async function(client) { // For service accounts, return the client as the user const serviceUser = await db.query( 'SELECT * FROM service_accounts WHERE client_id = $1', [client.id] ); return serviceUser || { id: client.id, isServiceAccount: true }; } }; ``` -------------------------------- ### Instantiate UnauthorizedClientError Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/unauthorized-client-error.rst Create a new instance of the error, which defaults to a 400 status code and 'unauthorized_client' name. ```javascript const err = new UnauthorizedClientError(); // err.message === 'Bad Request' // err.code === 400 // err.name === 'unauthorized_client' ``` -------------------------------- ### Implement saveToken() Model Method Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Persists access and refresh tokens to storage. Required for all grant types. ```javascript const model = { saveToken: async function(token, client, user) { // Save access token await db.query( `INSERT INTO oauth_access_tokens (access_token, expires_at, scope, client_id, user_id) VALUES ($1, $2, $3, $4, $5)`, [token.accessToken, token.accessTokenExpiresAt, token.scope, client.id, user.id] ); // Save refresh token if present if (token.refreshToken) { await db.query( `INSERT INTO oauth_refresh_tokens (refresh_token, expires_at, scope, client_id, user_id) VALUES ($1, $2, $3, $4, $5)`, [token.refreshToken, token.refreshTokenExpiresAt, token.scope, client.id, user.id] ); } return { accessToken: token.accessToken, accessTokenExpiresAt: token.accessTokenExpiresAt, refreshToken: token.refreshToken, refreshTokenExpiresAt: token.refreshTokenExpiresAt, scope: token.scope, client: { id: client.id }, user: { id: user.id } }; } }; ``` -------------------------------- ### Implement getAccessToken() Model Method Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Retrieves a stored access token along with its associated client and user. Required for authentication. ```javascript const model = { getAccessToken: async function(accessToken) { const token = await db.query( `SELECT t.*, c.*, u.* FROM oauth_access_tokens t JOIN oauth_clients c ON t.client_id = c.client_id JOIN users u ON t.user_id = u.id WHERE t.access_token = $1`, [accessToken] ); if (!token) return null; return { accessToken: token.access_token, accessTokenExpiresAt: new Date(token.expires_at), scope: token.scope, client: { id: token.client_id }, user: { id: token.user_id, username: token.username } }; } }; ``` -------------------------------- ### Implement getUser Model Function Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Retrieves a user based on credentials. Required when using the password grant type. ```javascript function getUser(username, password) { // imaginary DB query return db.queryUser({username: username, password: password}); } ``` -------------------------------- ### UnsupportedGrantTypeError Constructor Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/unsupported-grant-type-error.rst Instantiates a new UnsupportedGrantTypeError object. ```APIDOC ## Constructor: UnsupportedGrantTypeError ### Description Instantiates an UnsupportedGrantTypeError when the authorization grant type is not supported by the server. ### Parameters - **message** (String|Error) - Optional - Error message. - **properties** (Object) - Optional - Additional error properties. - **properties.code** (Number) - Optional - The HTTP status code, defaults to 400. - **properties.name** (String) - Optional - The error name, defaults to 'unsupported_grant_type'. ### Usage Example ```javascript const UnsupportedGrantTypeError = require('oauth2-server/lib/errors/unsupported-grant-type-error'); const err = new UnsupportedGrantTypeError(); ``` ``` -------------------------------- ### Instantiate ServerError Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/server-error.rst Create a new instance of ServerError, which defaults to a 503 status code. ```javascript const err = new ServerError(); // err.message === 'Service Unavailable Error' // err.code === 503 // err.name === 'server_error' ``` -------------------------------- ### Import ServerError Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/server-error.rst Import the ServerError class from the library. ```javascript const ServerError = require('oauth2-server/lib/errors/server-error'); ``` -------------------------------- ### Implement User Retrieval Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Implement the `getUserFromClient` function to retrieve user information based on the provided client object. This function is crucial for associating clients with users in your authentication flow. ```javascript function getUserFromClient(client) { // imaginary DB query return db.queryUser({id: client.user_id}); } ``` -------------------------------- ### Importing the Request Class Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/request.rst Import the Request class from the oauth2-server library. ```javascript const Request = require('oauth2-server').Request; ``` -------------------------------- ### Method: authenticate(request, response, [options], [callback]) Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/oauth2-server.rst Authenticates an incoming request by validating the access token against the configured model. ```APIDOC ## authenticate(request, response, [options], [callback]) ### Description Authenticates a request using the provided request and response objects. It validates scopes and token presence. ### Parameters #### Request Body - **request** (Object) - Required - The request object. - **response** (Object) - Required - The response object. - **options** (Object) - Optional - Handler options including scope, addAcceptedScopesHeader, addAuthorizedScopesHeader, and allowBearerTokensInQueryString. - **callback** (Function) - Optional - Node-style callback. ### Response #### Success Response (200) - **token** (Object) - The access token object returned from the model's getAccessToken method. #### Error Response - **error** (Object) - Rejects with an error derived from oauth-error, such as UnauthorizedRequestError. ``` -------------------------------- ### UnsupportedResponseTypeError Constructor Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/unsupported-response-type-error.rst Instantiates an UnsupportedResponseTypeError. This error is thrown when the authorization server does not support the requested response type for obtaining an authorization code. ```APIDOC ## new UnsupportedResponseTypeError(message, properties) ### Description Instantiates an ``UnsupportedResponseTypeError``. ### Method Constructor ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Arguments +-----------------------------------------------+--------------+-------------------------------------------------------------+ | Name | Type | Description | +===============================================+==============+=============================================================+ | [message=undefined] | String|Error | See :ref:`OAuthError#constructor`. | +-----------------------------------------------+--------------+-------------------------------------------------------------+ | [properties={}] | Object | See :ref:`OAuthError#constructor`. | +-----------------------------------------------+--------------+-------------------------------------------------------------+ | [properties.code=400] | Object | See :ref:`OAuthError#constructor`. | +-----------------------------------------------+--------------+-------------------------------------------------------------+ | [properties.name='unsupported_response_type'] | String | The error name used in responses generated from this error. | +-----------------------------------------------+--------------+-------------------------------------------------------------+ ### Return value A new instance of ``UnsupportedResponseTypeError``. ### Remarks ```javascript const err = new UnsupportedResponseTypeError(); // err.message === 'Bad Request' // err.code === 400 // err.name === 'unsupported_response_type' ``` ``` -------------------------------- ### Handle Response Objects Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Wrap framework-specific response objects to manage headers, status codes, and body content. ```javascript const Response = OAuth2Server.Response; // Create from Express response function middleware(req, res, next) { const response = new Response(res); } // Create manually const response = new Response({ headers: {} }); // Access and modify response response.set('X-Custom-Header', 'value'); const headerValue = response.get('X-Custom-Header'); response.status = 200; response.body = { success: true }; response.redirect('https://example.com/callback?code=abc123'); ``` -------------------------------- ### Model#generateAccessToken Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Details the `generateAccessToken` model function, which is invoked to create a new access token. It outlines the optional nature of this function and its arguments. ```APIDOC ## Model#generateAccessToken ### Description Invoked to generate a new access token. This model function is optional. If not implemented, a default handler is used that generates access tokens consisting of 40 characters in the range of `a..z0..9`. **Invoked during:** - `authorization_code` grant - `client_credentials` grant - `refresh_token` grant - `password` grant ### Arguments #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Parameters - **client** (Object) - Required - The client the access token is generated for. - **user** (Object) - Required - The user the access token is generated for. - **scope** (String) - Required - The scopes associated with the access token. Can be `null`. - **[callback]** (Function) - Optional - Node-style callback to be used instead of the returned `Promise`. ### Return Value A `String` to be used as access token. Access tokens must consist of characters inside the range `0x20..0x7E` (i.e. only printable US-ASCII characters). ### Remarks - `client` is the object previously obtained through `Model#getClient()`. - `user` is the user object previously obtained through `Model#getAuthorizationCode()` (authorization code grant), `Model#getUserFromClient()` (client credentials grant), `Model#getRefreshToken()` (refresh token grant) or `Model#getUser()` (password grant). ### Request Example N/A ### Response #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Generate Tokens Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/docs/getting-started.rst Use the token method to process token requests. ```javascript oauth.token(request, response) .then((token) => { // The resource owner granted the access request. }) .catch((err) => { // The request was invalid or not authorized. }); ``` -------------------------------- ### Import UnauthorizedClientError Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/unauthorized-client-error.rst Import the error class from the library to handle unauthorized client scenarios. ```javascript const UnauthorizedClientError = require('oauth2-server/lib/errors/unauthorized-client-error'); ``` -------------------------------- ### Implement saveToken model function Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Persists access and refresh tokens to a database. Requires returning a promise that resolves to the saved token object. ```javascript function saveToken(token, client, user) { // imaginary DB queries let fns = [ db.saveAccessToken({ access_token: token.accessToken, expires_at: token.accessTokenExpiresAt, scope: token.scope, client_id: client.id, user_id: user.id }), db.saveRefreshToken({ refresh_token: token.refreshToken, expires_at: token.refreshTokenExpiresAt, scope: token.scope, client_id: client.id, user_id: user.id }) ]; return Promise.all(fns); .spread(function(accessToken, refreshToken) { return { accessToken: accessToken.access_token, accessTokenExpiresAt: accessToken.expires_at, refreshToken: refreshToken.refresh_token, refreshTokenExpiresAt: refreshToken.expires_at, scope: accessToken.scope, client: {id: accessToken.client_id}, user: {id: accessToken.user_id} }; }); } ``` -------------------------------- ### Model Implementation - Custom Token Generation Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Optional methods to override default token and code generation logic. ```APIDOC ## generateAccessToken(client, user, scope) ### Description Generates a custom access token. ## generateRefreshToken(client, user, scope) ### Description Generates a custom refresh token. ## generateAuthorizationCode(client, user, scope) ### Description Generates a custom authorization code. ``` -------------------------------- ### Require OAuth2Server Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/oauth2-server.rst Import the OAuth2Server class from the node-oauth2-server library. ```javascript const OAuth2Server = require('oauth2-server'); ``` -------------------------------- ### Authenticate Requests Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/docs/getting-started.rst Use the authenticate method to verify the request and handle success or failure via promises. ```javascript oauth.authenticate(request, response) .then((token) => { // The request was successfully authenticated. }) .catch((err) => { // The request failed authentication. }); ``` -------------------------------- ### Instantiate AccessDeniedError Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/access-denied-error.rst Instantiate an AccessDeniedError. The default message is 'Bad Request', the default code is 400, and the default name is 'access_denied'. ```javascript const err = new AccessDeniedError(); // err.message === 'Bad Request' // err.code === 400 // err.name === 'access_denied' ``` -------------------------------- ### Implement Token Saving Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Implement the `saveToken` function to persist access and refresh tokens. This function is required for all grant types and is invoked when tokens need to be stored. ```javascript function saveToken(token, client, user, callback) { // ... implementation to save token to database ... return Promise.resolve(token); } ``` -------------------------------- ### Instantiate Response from Express Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/response.rst Converts an Express response object into an OAuth2 server Response instance. ```javascript function(req, res, next) { var response = new Response(res); // ... } ``` -------------------------------- ### Implement Token Issuance Endpoint Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Handles the token endpoint for all grant types, issuing access and refresh tokens. ```javascript const OAuth2Server = require('oauth2-server'); const Request = OAuth2Server.Request; const Response = OAuth2Server.Response; const oauth = new OAuth2Server({ model: require('./model') }); // Express handler for token endpoint function tokenHandler(req, res) { const request = new Request(req); const response = new Response(res); return oauth.token(request, response, { accessTokenLifetime: 3600, // 1 hour refreshTokenLifetime: 1209600, // 2 weeks allowExtendedTokenAttributes: false, requireClientAuthentication: { password: false, // Don't require client_secret for password grant authorization_code: true, client_credentials: true, refresh_token: true }, alwaysIssueNewRefreshToken: true }) .then(function(token) { // Token issued successfully res.json({ access_token: token.accessToken, token_type: 'Bearer', expires_in: 3600, refresh_token: token.refreshToken, scope: token.scope }); }) .catch(function(err) { res.status(err.code || 500).json({ error: err.name, error_description: err.message }); }); } app.post('/oauth/token', tokenHandler); ``` -------------------------------- ### Import InsufficientScopeError Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/insufficient-scope-error.rst Import the InsufficientScopeError class from the library. This is typically done at the beginning of a file where this error might be thrown. ```javascript const InsufficientScopeError = require('oauth2-server/lib/errors/insufficient-scope-error'); ``` -------------------------------- ### getClient(clientId, clientSecret) Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Retrieves a client using a client id or a client id/client secret combination. ```APIDOC ## getClient(clientId, clientSecret) ### Description Invoked to retrieve a client using a client id or a client id/client secret combination, depending on the grant type. This function is required for all grant types. ### Parameters #### Arguments - **clientId** (String) - Required - The client id of the client to retrieve. - **clientSecret** (String) - Required - The client secret of the client to retrieve. Can be null. - **callback** (Function) - Optional - Node-style callback to be used instead of the returned Promise. ### Response #### Success Response - **client** (Object) - An object representing the client and associated data, or a falsy value if no such client could be found. ``` -------------------------------- ### Client Credentials Grant Request Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Used for machine-to-machine authentication without user involvement. ```bash curl -X POST http://localhost:3000/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -u "client_id:client_secret" \ -d "grant_type=client_credentials" \ -d "scope=api" ``` ```javascript // Or with Basic auth in body const request = new Request({ method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, query: {}, body: { grant_type: 'client_credentials', client_id: 'my-client-id', client_secret: 'my-client-secret', scope: 'api' } }); ``` -------------------------------- ### getUser(username, password, [callback]) Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/model/spec.rst Retrieves a user using a username and password combination, required for the password grant. ```APIDOC ## getUser(username, password, [callback]) ### Description Invoked to retrieve a user using a username/password combination. This function is required if the password grant is used. ### Parameters #### Arguments - **username** (String) - Required - The username of the user to retrieve. - **password** (String) - Required - The user's password. - **[callback]** (Function) - Optional - Node-style callback to be used instead of the returned Promise. ### Response - **Object** - An object representing the user, or a falsy value if no such user could be found. ``` -------------------------------- ### Implement Authorization Code Grant Endpoint Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Handles the authorization endpoint for the authorization_code grant, including user authentication and redirecting after approval. ```javascript const OAuth2Server = require('oauth2-server'); const AccessDeniedError = require('oauth2-server/lib/errors/access-denied-error'); const oauth = new OAuth2Server({ model: require('./model') }); // Express handler for authorization endpoint function authorizeHandler(req, res) { const request = new Request(req); const response = new Response(res); // authenticateHandler retrieves the logged-in user const authenticateHandler = { handle: function(request, response) { // Return the authenticated user from session return req.session.user; } }; return oauth.authorize(request, response, { authenticateHandler: authenticateHandler, allowEmptyState: false, authorizationCodeLifetime: 300 // 5 minutes }) .then(function(code) { // Authorization code created successfully // Redirect to client with code // code.authorizationCode, code.expiresAt, code.client, code.user res.redirect(response.headers.location); }) .catch(function(err) { if (err instanceof AccessDeniedError) { // User denied the authorization request res.redirect(`${req.query.redirect_uri}?error=access_denied`); } else { res.status(err.code || 500).json({ error: err.name, error_description: err.message }); } }); } // Authorization page routes app.get('/oauth/authorize', (req, res) => { // Show authorization form to user res.render('authorize', { client_id: req.query.client_id, redirect_uri: req.query.redirect_uri, scope: req.query.scope, state: req.query.state }); }); app.post('/oauth/authorize', authorizeHandler); ``` -------------------------------- ### Implement Authorization Code Methods Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Required for the authorization_code grant. Handles saving, retrieving, and revoking authorization codes. ```javascript const model = { saveAuthorizationCode: async function(code, client, user) { await db.query( `INSERT INTO oauth_authorization_codes (authorization_code, expires_at, redirect_uri, scope, client_id, user_id) VALUES ($1, $2, $3, $4, $5, $6)`, [code.authorizationCode, code.expiresAt, code.redirectUri, code.scope, client.id, user.id] ); return { authorizationCode: code.authorizationCode, expiresAt: code.expiresAt, redirectUri: code.redirectUri, scope: code.scope, client: { id: client.id }, user: { id: user.id } }; }, getAuthorizationCode: async function(authorizationCode) { const code = await db.query( `SELECT * FROM oauth_authorization_codes WHERE authorization_code = $1`, [authorizationCode] ); if (!code) return null; return { code: code.authorization_code, expiresAt: new Date(code.expires_at), redirectUri: code.redirect_uri, scope: code.scope, client: { id: code.client_id }, user: { id: code.user_id } }; }, revokeAuthorizationCode: async function(code) { const result = await db.query( 'DELETE FROM oauth_authorization_codes WHERE authorization_code = $1', [code.code] ); return result.rowCount > 0; } }; ``` -------------------------------- ### Password Grant Request Source: https://context7.com/oauthjs/node-oauth2-server/llms.txt Exchanges user credentials directly for tokens, typically used for trusted first-party applications. ```bash curl -X POST http://localhost:3000/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=password" \ -d "client_id=my-client-id" \ -d "client_secret=my-client-secret" \ -d "username=johndoe" \ -d "password=secret123" \ -d "scope=read write" ``` ```javascript // Expected response { "access_token": "a1b2c3d4e5f6g7h8i9j0", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "z9y8x7w6v5u4t3s2r1q0", "scope": "read write" } ``` -------------------------------- ### UnauthorizedClientError Constructor Source: https://github.com/oauthjs/node-oauth2-server/blob/master/docs/api/errors/unauthorized-client-error.rst Instantiates an UnauthorizedClientError. This error is thrown when an authenticated client is not authorized to use the requested authorization grant type. ```APIDOC ## new UnauthorizedClientError(message, properties) ### Description Instantiates an ``UnauthorizedClientError``. ### Method Constructor ### Parameters #### Arguments - **message** (String|Error) - Optional - See :ref:`OAuthError#constructor`. - **properties** (Object) - Optional - See :ref:`OAuthError#constructor`. - **properties.code** (Object) - Optional - See :ref:`OAuthError#constructor`. Defaults to 400. - **properties.name** (String) - Optional - The error name used in responses generated from this error. Defaults to 'unauthorized_client'. ### Return value A new instance of ``UnauthorizedClientError``. ### Remarks ```javascript const err = new UnauthorizedClientError(); // err.message === 'Bad Request' // err.code === 400 // err.name === 'unauthorized_client' ``` ```