Skip to content

Commit d97a674

Browse files
authored
Merge pull request #464 from adieuadieu/implicit-grant-support
Implicit grant flow v3 (rebased #271)
2 parents 2e200d8 + 5fbb487 commit d97a674

17 files changed

+999
-326
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ The *oauth2-server* module is framework-agnostic but there are several officiall
2020

2121
## Features
2222

23-
- Supports `authorization_code`, `client_credentials`, `refresh_token` and `password` grant, as well as *extension grants*, with scopes.
23+
- Supports `authorization_code`, `client_credentials`, `refresh_token`, `implicit` and `password` grant, as well as *extension grants*, with scopes.
2424
- Can be used with *promises*, *Node-style callbacks*, *ES6 generators* and *async*/*await* (using [Babel](https://babeljs.io)).
2525
- Fully [RFC 6749](https://tools.ietf.org/html/rfc6749.html) and [RFC 6750](https://tools.ietf.org/html/rfc6750.html) compliant.
2626
- Implicitly supports any form of storage, e.g. *PostgreSQL*, *MySQL*, *MongoDB*, *Redis*, etc.

docs/api/oauth2-server.rst

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -128,25 +128,27 @@ Authorizes a token request.
128128

129129
**Arguments:**
130130

131-
+-----------------------------------------+-----------------+-----------------------------------------------------------------------------+
132-
| Name | Type | Description |
133-
+=========================================+=================+=============================================================================+
134-
| request | :doc:`request` | Request object. |
135-
+-----------------------------------------+-----------------+-----------------------------------------------------------------------------+
136-
| [request.query.allowed=undefined] | String | ``'false'`` to deny the authorization request (see remarks section). |
137-
+-----------------------------------------+-----------------+-----------------------------------------------------------------------------+
138-
| response | :doc:`response` | Response object. |
139-
+-----------------------------------------+-----------------+-----------------------------------------------------------------------------+
140-
| [options={}] | Object | Handler options. |
141-
+-----------------------------------------+-----------------+-----------------------------------------------------------------------------+
142-
| [options.authenticateHandler=undefined] | Object | The authenticate handler (see remarks section). |
143-
+-----------------------------------------+-----------------+-----------------------------------------------------------------------------+
144-
| [options.allowEmptyState=false] | Boolean | Allow clients to specify an empty ``state``. |
145-
+-----------------------------------------+-----------------+-----------------------------------------------------------------------------+
146-
| [options.authorizationCodeLifetime=300] | Number | Lifetime of generated authorization codes in seconds (default = 5 minutes). |
147-
+-----------------------------------------+-----------------+-----------------------------------------------------------------------------+
148-
| [callback=undefined] | Function | Node-style callback to be used instead of the returned ``Promise``. |
149-
+-----------------------------------------+-----------------+-----------------------------------------------------------------------------+
131+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
132+
| Name | Type | Description |
133+
+=========================================+=================+================================================================================+
134+
| request | :doc:`request` | Request object. |
135+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
136+
| [request.query.allowed=undefined] | String | ``'false'`` to deny the authorization request (see remarks section). |
137+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
138+
| response | :doc:`response` | Response object. |
139+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
140+
| [options={}] | Object | Handler options. |
141+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
142+
| [options.authenticateHandler=undefined] | Object | The authenticate handler (see remarks section). |
143+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
144+
| [options.allowEmptyState=false] | Boolean | Allow clients to specify an empty ``state``. |
145+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
146+
| [options.authorizationCodeLifetime=300] | Number | Lifetime of generated authorization codes in seconds (default = 5 minutes). |
147+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
148+
| [options.accessTokenLifetime=3600] | Number | Lifetime of generated implicit grant access token in seconds (default = 1 hr). |
149+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
150+
| [callback=undefined] | Function | Node-style callback to be used instead of the returned ``Promise``. |
151+
+-----------------------------------------+-----------------+--------------------------------------------------------------------------------+
150152

151153
**Return value:**
152154

docs/model/overview.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ Model functions used by the client credentials grant:
5858
- :ref:`Model#getUserFromClient`
5959
- :ref:`Model#saveToken`
6060
- :ref:`Model#validateScope`
61+
--------
62+
63+
.. _ImplicitGrant:
64+
65+
Implicit Grant
66+
------------------------
67+
68+
See :rfc:`Section 4.2 of RFC 6749 <6749#section-4.2>`.
69+
70+
An implicit grant is used to obtain access tokens optimised for public clients known to operate a particular redirection URI. Usually used for browser-based clients implemented in JavaScript.
71+
72+
Model functions used by the implicit grant:
73+
74+
- :ref:`Model#generateAccessToken`
75+
- :ref:`Model#getClient`
76+
- :ref:`Model#saveToken`
77+
- :ref:`Model#validateScope`
6178

6279
--------
6380

docs/model/spec.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ This model function is **required** for all grant types.
399399

400400
- ``authorization_code`` grant
401401
- ``client_credentials`` grant
402+
- ``implicit`` grant
402403
- ``refresh_token`` grant
403404
- ``password`` grant
404405

@@ -553,6 +554,7 @@ This model function is **required** for all grant types.
553554

554555
- ``authorization_code`` grant
555556
- ``client_credentials`` grant
557+
- ``implicit`` grant
556558
- ``refresh_token`` grant
557559
- ``password`` grant
558560

@@ -865,6 +867,7 @@ This model function is **optional**. If not implemented, any scope is accepted.
865867

866868
- ``authorization_code`` grant
867869
- ``client_credentials`` grant
870+
- ``implicit`` grant
868871
- ``password`` grant
869872

870873
**Arguments:**
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
'use strict';
2+
3+
/**
4+
* Module dependencies.
5+
*/
6+
7+
var AbstractGrantType = require('./abstract-grant-type');
8+
var InvalidArgumentError = require('../errors/invalid-argument-error');
9+
var Promise = require('bluebird');
10+
var promisify = require('promisify-any').use(Promise);
11+
var util = require('util');
12+
13+
/**
14+
* Constructor.
15+
*/
16+
17+
function ImplicitGrantType(options) {
18+
options = options || {};
19+
20+
if (!options.model) {
21+
throw new InvalidArgumentError('Missing parameter: `model`');
22+
}
23+
24+
if (!options.model.saveToken) {
25+
throw new InvalidArgumentError('Invalid argument: model does not implement `saveToken()`');
26+
}
27+
28+
if (!options.user) {
29+
throw new InvalidArgumentError('Missing parameter: `user`');
30+
}
31+
32+
this.scope = options.scope;
33+
this.user = options.user;
34+
35+
AbstractGrantType.call(this, options);
36+
}
37+
38+
/**
39+
* Inherit prototype.
40+
*/
41+
42+
util.inherits(ImplicitGrantType, AbstractGrantType);
43+
44+
/**
45+
* Handle implicit token grant.
46+
*/
47+
48+
ImplicitGrantType.prototype.handle = function(request, client) {
49+
if (!request) {
50+
throw new InvalidArgumentError('Missing parameter: `request`');
51+
}
52+
53+
if (!client) {
54+
throw new InvalidArgumentError('Missing parameter: `client`');
55+
}
56+
57+
return this.saveToken(this.user, client, this.scope);
58+
};
59+
60+
/**
61+
* Save token.
62+
*/
63+
64+
ImplicitGrantType.prototype.saveToken = function(user, client, scope) {
65+
var fns = [
66+
this.validateScope(user, client, scope),
67+
this.generateAccessToken(client, user, scope),
68+
this.getAccessTokenExpiresAt()
69+
];
70+
71+
return Promise.all(fns)
72+
.bind(this)
73+
.spread(function(scope, accessToken, accessTokenExpiresAt) {
74+
var token = {
75+
accessToken: accessToken,
76+
accessTokenExpiresAt: accessTokenExpiresAt,
77+
scope: scope
78+
};
79+
80+
return promisify(this.model.saveToken, 3).call(this.model, token, client, user);
81+
});
82+
};
83+
84+
/**
85+
* Export constructor.
86+
*/
87+
88+
module.exports = ImplicitGrantType;

0 commit comments

Comments
 (0)