Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 4.0.0

- bump minimal node to 16
- upgrade @node-oauth/oauth2-server to 5.1.0
- drop bluebird dependency
- upgrade all deps / dev-deps
- refactor all code to minimum es6
- use native async/await


## 3.0.0
- use @node-oauth/oauth2-server
- update all dependencies to latest
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2015 - Today Seegno and contributors
Copyright (c) 2015 - Today Node-OAuth contributors; Formerly: Seegno and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Complete, compliant and well tested module for implementing an OAuth2 Server/Pro

[![Tests](https://github.com/node-oauth/express-oauth-server/actions/workflows/tests.yml/badge.svg)](https://github.com/node-oauth/express-oauth-server/actions/workflows/tests.yml)
[![CodeQL](https://github.com/node-oauth/express-oauth-server/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/node-oauth/express-oauth-server/actions/workflows/github-code-scanning/codeql)
[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
[![npm Version](https://img.shields.io/npm/v/@node-oauth/express-oauth-server?label=version)](https://www.npmjs.com/package/@node-oauth/oauth2-server)
[![npm Downloads/Week](https://img.shields.io/npm/dw/@node-oauth/express-oauth-server)](https://www.npmjs.com/package/@node-oauth/oauth2-server)
![GitHub](https://img.shields.io/github/license/node-oauth/express-oauth-server)


Expand All @@ -24,11 +27,11 @@ expect the request body to be parsed already.
The following example uses `body-parser` but you may opt for an alternative library.

```js
var bodyParser = require('body-parser');
var express = require('express');
var OAuthServer = require('@node-oauth/express-oauth-server');
const bodyParser = require('body-parser');
const express = require('express');
const OAuthServer = require('@node-oauth/express-oauth-server');

var app = express();
const app = express();

app.oauth = new OAuthServer({
model: {}, // See https://github.com/node-oauth/node-oauth2-server for specification
Expand All @@ -48,18 +51,19 @@ app.listen(3000);
## Options

```
var options = {
const options = {
useErrorHandler: false,
continueMiddleware: false,
}
```
* `useErrorHandler`

- `useErrorHandler`
(_type: boolean_ default: false)

If false, an error response will be rendered by this component.
Set this value to true to allow your own express error handler to handle the error.

* `continueMiddleware`
- `continueMiddleware`
(_type: boolean default: false_)

The `authorize()` and `token()` middlewares will both render their
Expand All @@ -69,3 +73,7 @@ var options = {
**Note:** You cannot modify the response since the headers have already been sent.

`authenticate()` does not modify the response and will always call next()

## License

MIT, see
242 changes: 132 additions & 110 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,144 +1,166 @@
/**
* Module dependencies.
*/
const NodeOAuthServer = require('@node-oauth/oauth2-server');
const { Request, Response } = require('@node-oauth/oauth2-server');

const InvalidArgumentError = require('@node-oauth/oauth2-server/lib/errors/invalid-argument-error');
const NodeOAuthServer = require('@node-oauth/oauth2-server');
const Request = require('@node-oauth/oauth2-server').Request;
const Response = require('@node-oauth/oauth2-server').Response;
const UnauthorizedRequestError = require('@node-oauth/oauth2-server/lib/errors/unauthorized-request-error');

/**
*
*/
class ExpressOAuthServer {
constructor(options) {
this.options = options || {};

if (!this.options.model) {
/**
* @constructor
*/
constructor(options = {}) {
if (!options.model) {
throw new InvalidArgumentError('Missing parameter: `model`');
}
this.useErrorHandler = this.options.useErrorHandler === true;
this.continueMiddleware = this.options.continueMiddleware === true;

delete this.options.useErrorHandler;
delete this.options.continueMiddleware;
this.useErrorHandler = !!options.useErrorHandler;
delete options.useErrorHandler;

this.continueMiddleware = !!options.continueMiddleware;
delete options.continueMiddleware;

this.server = new NodeOAuthServer(this.options);
this.server = new NodeOAuthServer(options);
}

/**
* Authentication Middleware.
*
* Returns a middleware that will validate a token.
*
* (See: https://tools.ietf.org/html/rfc6749#section-7)
*/
authenticate(options) {
return async (req, res, next) => {
const request = new Request(req);
const response = new Response(res);
let token;
try {
token = await this.server.authenticate(request, response, options);
} catch (err) {
this._handleError(res, null, err, next);
return;
}
res.locals.oauth = { token };
return next();
}

/**
* Authentication Middleware.
*
* Returns a middleware that will validate a token.
*
* (See: https://tools.ietf.org/html/rfc6749#section-7)
*/

ExpressOAuthServer.prototype.authenticate = function(options) {
const fn = async function(req, res, next) {
const request = new Request(req);
const response = new Response(res);

let token

try {
token = await this.server.authenticate(request, response, options);
} catch (e) {
return handleError.call(this, e, req, res, null, next);
}
}

/**
* Authorization Middleware.
*
* Returns a middleware that will authorize a client to request tokens.
*
* (See: https://tools.ietf.org/html/rfc6749#section-3.1)
*/
authorize(options) {
return async (req, res, next) => {
const request = new Request(req);
const response = new Response(res);
let code;
try {
code = await this.server.authorize(request, response, options);
} catch (err) {
this._handleError(res, response, err, next);
return;
}
res.locals.oauth = { code };
if (this.continueMiddleware) {
next();
}
return this._handleResponse(req, res, response);
res.locals.oauth = { token };
next();
};
return fn.bind(this);
};

/**
* Authorization Middleware.
*
* Returns a middleware that will authorize a client to request tokens.
*
* (See: https://tools.ietf.org/html/rfc6749#section-3.1)
*/

ExpressOAuthServer.prototype.authorize = function(options) {
const fn = async function(req, res, next) {
const request = new Request(req);
const response = new Response(res);

let code

try {
code = await this.server.authorize(request, response, options);
} catch (e) {
return handleError.call(this, e, req, res, response, next);
}
}

res.locals.oauth = { code: code };
if (this.continueMiddleware) {
next();
}

/**
* Authorization Middleware.
*
* Returns a middleware that will authorize a client to request tokens.
*
* (See: https://tools.ietf.org/html/rfc6749#section-3.1)
*/
token(options) {
return async (req, res, next) => {
const request = new Request(req);
const response = new Response(res);
let token;
try {
token = await this.server.token(request, response, options);
} catch (err) {
this._handleError(res, response, err, next);
return;
}
res.locals.oauth = { token };
if (this.continueMiddleware) {
next();
}
return this._handleResponse(req, res, response);
return handleResponse.call(this, req, res, response);
};

return fn.bind(this);
};

/**
* Grant Middleware.
*
* Returns middleware that will grant tokens to valid requests.
*
* (See: https://tools.ietf.org/html/rfc6749#section-3.2)
*/

ExpressOAuthServer.prototype.token = function(options) {
const fn = async function(req, res, next) {
const request = new Request(req);
const response = new Response(res);

let token

try {
token = await this.server.token(request, response, options);
} catch (e) {
return handleError.call(this, e, req, res, response, next);
}
}

/**
* Grant Middleware.
*
* Returns middleware that will grant tokens to valid requests.
*
* (See: https://tools.ietf.org/html/rfc6749#section-3.2)
*/
_handleResponse(req, res, oauthResponse) {
if (oauthResponse.status === 302) {
const location = oauthResponse.headers.location;
delete oauthResponse.headers.location;
res.set(oauthResponse.headers);
res.redirect(location);
return;
res.locals.oauth = { token: token };
if (this.continueMiddleware) {
next();
}
res.set(oauthResponse.headers);
res.status(oauthResponse.status).send(oauthResponse.body);

return handleResponse.call(this, req, res, response);
};

return fn.bind(this);
};

/**
* Handle response.
*/
const handleResponse = function(req, res, response) {
if (response.status === 302) {
const location = response.headers.location;
delete response.headers.location;
res.set(response.headers);
res.redirect(location);
} else {
res.set(response.headers);
res.status(response.status).send(response.body);
}
};

/**
* Handles errors depending on the options of `this.useErrorHandler`.
* Either calls `next()` with the error (so the application can handle it), or returns immediately a response with the error.
*/
_handleError(res, oauthResponse, error, next) {
if (this.useErrorHandler) {
return next(error);
}
/**
* Handle error.
*/

if (oauthResponse) {
res.set(oauthResponse.headers);
const handleError = function(e, req, res, response, next) {
if (this.useErrorHandler === true) {
next(e);
} else {
if (response) {
res.set(response.headers);
}

res.status(error.code || 500);
res.status(e.code);

if (error instanceof UnauthorizedRequestError) {
if (e instanceof UnauthorizedRequestError) {
return res.send();
}

return res.send({ error: error.name, error_description: error.message });
res.send({ error: e.name, error_description: e.message });
}
}
};

/**
* Export constructor.
*/

module.exports = ExpressOAuthServer;
Loading