Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed Unresolvable cycle detected #1

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ca81e2c
changed error handler res.send to fix express deprecation warnings
thomasdashney Aug 30, 2014
edbbcaf
Correctly handle array of routes for a method
towynlin Oct 21, 2014
b53e9c9
Cleaner test style
towynlin Oct 21, 2014
06e42b4
Test that lockdown specifically adds authorise
towynlin Nov 15, 2014
dc43b17
Update docs for model function getAccessToken
bvinnerd Dec 2, 2014
202ae73
Update Readme.md
JimiHFord Dec 9, 2014
4852ef3
Merge pull request #127 from JimiHFord/patch-1
thomseddon Dec 9, 2014
39663d6
Fix generateToken docs. Fixes #103
thomseddon Dec 31, 2014
a5b3135
Update client_id regex docs. Closes #123
thomseddon Dec 31, 2014
0050abf
Expose user and client to generateToken.
thomseddon Dec 31, 2014
2e83943
Merge pull request #101 from thomasdashney/master
thomseddon Jan 2, 2015
4d4f248
Merge pull request #126 from bvinnerd/doc-fix-get-access-token
thomseddon Jan 2, 2015
aeee9f1
Merge pull request #119 from towynlin/fix/lockdown-express3
thomseddon Jan 2, 2015
9c4e9b1
Expose validated client for extended grant
thomseddon Jan 24, 2015
cd69ef6
Document redirect Uri. Closes #50
thomseddon Jan 24, 2015
b5862f0
Fix docs to use new body parser API
thomseddon Jan 26, 2015
0f9e5ed
Add simple Redis example
robinjmurphy Jan 4, 2015
5cf4504
Merge branch 'robinjmurphy-redis-example'
thomseddon Jan 26, 2015
c169c1b
Allow any valid URI for extension grants
thomseddon Jan 26, 2015
332cde3
Merge pull request #143 from thomseddon/fix/expose-validated-client-c…
thomseddon Jan 27, 2015
57a402e
Merge pull request #142 from thomseddon/feature/extension-grant-allow…
thomseddon Jan 27, 2015
c19719e
Set Cache-Control and Pragma Headers
thomseddon Jan 27, 2015
8ccc556
Merge pull request #148 from thomseddon/fix/set-cache-control-headers
thomseddon Feb 1, 2015
4f7899b
2.4.0
thomseddon Mar 11, 2015
28903c8
fixed Unresolvable cycle detected
Mar 20, 2015
f60a945
use params instead of body
Mar 22, 2015
1400159
Merge remote-tracking branch 'upstream-parent/master'
Mar 28, 2015
3884648
use restify error
Mar 31, 2015
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
17 changes: 17 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
## Changelog

### 2.4.0

- Set Cache-Control and Pragma headers
- Allow any valid URI for extension grants
- Expose `client` to `extendedGrant` and after via `req.oauth.client`
- Fix express depreciation warning for `res.send()`
- Expose `user` to `generateToken` and after via `req.user`
- Fix lockdown pattern for express 3

- Add redis example
- Fix docs to use new express bodyParser module
- Fix docs for `redirect_uri`
- Clarify docs for `clientIdRegex`
- Fix docs for missing `req` argument in `generateToken`
- Fix docs for `user`/`userId` `getAccessToken`
- Fix docs for argument order in `getRefreshToken`

### 2.3.0

- Support "state" param for auth_code grant type
Expand Down
18 changes: 11 additions & 7 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Note: As no model was actually implemented here, delving any deeper, i.e. passin
- grant types you wish to support, currently the module supports `password` and `refresh_token`
- Default: `[]`
- *function|boolean* **debug**
- If `true` errors will be logged to console. You may also pass a custom function, in which case that function will be called with the error as it's first argument
- If `true` errors will be logged to console. You may also pass a custom function, in which case that function will be called with the error as its first argument
- Default: `false`
- *number* **accessTokenLifetime**
- Life of access tokens in seconds
Expand All @@ -69,8 +69,8 @@ Note: As no model was actually implemented here, delving any deeper, i.e. passin
- Life of auth codes in seconds
- Default: `30`
- *regexp* **clientIdRegex**
- Regex to match auth codes against before checking model
- Default: `/^[a-z0-9-_]{3,40}$/i`
- Regex to sanity check client id against before checking model. Note: the default just matches common `client_id` structures, change as needed
- Default: `/^[a-z0-9-_]{3,40}$/i`
- *boolean* **passthroughErrors**
- If true, **non grant** errors will not be handled internally (so you can ensure a consistent format with the rest of your api)
- *boolean* **continueAfterResponse**
Expand All @@ -97,8 +97,9 @@ Note: see https://github.com/thomseddon/node-oauth2-server/tree/master/examples/
- *date* **expires**
- The date when it expires
- `null` to indicate the token **never expires**
- *string|number* **userId**
- The user id (saved in req.user.id)
- *mixed* **user** *or* *string|number* **userId**
- If a `user` key exists, this is saved as `req.user`
- Otherwise a `userId` key must exist, which is saved in `req.user.id`

#### getClient (clientId, clientSecret, callback)
- *string* **clientId**
Expand All @@ -112,6 +113,7 @@ Note: see https://github.com/thomseddon/node-oauth2-server/tree/master/examples/
- Saved in `req.client`
- Must contain the following keys:
- *string* **clientId**
- *string* **redirectUri** (`authorization_code` grant type only)

#### grantTypeAllowed (clientId, grantType, callback)
- *string* **clientId**
Expand Down Expand Up @@ -247,9 +249,11 @@ The spec does not actually require that you revoke the old token - hence this is

### Optional

#### generateToken (type, callback)
#### generateToken (type, req, callback)
- *string* **type**
- `accessToken` or `refreshToken`
- *object* **req**
- The current express request
- *function* **callback (error, token)**
- *mixed* **error**
- Truthy to indicate an error
Expand All @@ -262,7 +266,7 @@ The spec does not actually require that you revoke the old token - hence this is

## Extension Grants
You can support extension/custom grants by implementing the extendedGrant method as outlined above.
Any requests that begin with http(s):// (as [defined in the spec](http://tools.ietf.org/html/rfc6749#section-4.5)) will be passed to it for you to handle.
Any grant type that is a valid URI will be passed to it for you to handle (as [defined in the spec](http://tools.ietf.org/html/rfc6749#section-4.5)).
You can access the grant type via the first argument and you should pass back supported as `false` if you do not support it to ensure a consistent (and compliant) response.

## Example using the `password` grant type
Expand Down
4 changes: 3 additions & 1 deletion examples/dynamodb/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ var express = require('express'),

var app = express();

app.use(bodyParser());
app.use(bodyParser.urlencoded({ extended: true }));

app.use(bodyParser.json());

app.oauth = oauthserver({
model: require('./model'),
Expand Down
4 changes: 3 additions & 1 deletion examples/postgresql/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ var express = require('express'),

var app = express();

app.use(bodyParser());
app.use(bodyParser.urlencoded({ extended: true }));

app.use(bodyParser.json());

app.oauth = oauthserver({
model: require('./model'),
Expand Down
19 changes: 19 additions & 0 deletions examples/redis/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Redis Example

A simple example with support for `password` and `refresh_token` grants using [Redis](http://redis.io/). You'll need [node-redis](https://github.com/mranney/node_redis) installed.

## Usage

```js
app.oauth = oauthserver({
model: require('./model'),
grants: ['password', 'refresh_token'],
debug: true
});
```

## Data model

The example makes use of a simple data model where clients, tokens, refresh tokens and users are stored as [hashes](http://redis.io/topics/data-types#hashes). The allowed grants for each client are stored in a [set](http://redis.io/topics/data-types#sets) `clients:{id}:grant_types`. This allows grants to be added or removed dynamically. To simplify the user lookup users are identified by their username and not by a separate ID. Passwords are stored in the clear for simplicity, but in practice these should be hashed using a library like [bcrypt](https://github.com/ncb000gt/node.bcrypt.js).

To inject some test data you can run the `testData.js` script in this directory. This will create a client with the ID `client` and secret `secret` and create a single user with the username `username` and password `password`.
33 changes: 33 additions & 0 deletions examples/redis/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
var express = require('express'),
bodyParser = require('body-parser'),
oauthserver = require('../../'); // Would be: 'oauth2-server'

var app = express();

app.use(bodyParser.urlencoded({ extended: true }));

app.use(bodyParser.json());

app.oauth = oauthserver({
model: require('./model'),
grants: ['password', 'refresh_token'],
debug: true
});

// Handle token grant requests
app.all('/oauth/token', app.oauth.grant());

app.get('/secret', app.oauth.authorise(), function (req, res) {
// Will require a valid access_token
res.send('Secret area');
});

app.get('/public', function (req, res) {
// Does not require an access_token
res.send('Public area');
});

// Error handling
app.use(app.oauth.errorHandler());

app.listen(3000);
90 changes: 90 additions & 0 deletions examples/redis/model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
var model = module.exports,
util = require('util'),
redis = require('redis');

var db = redis.createClient();

var keys = {
token: 'tokens:%s',
client: 'clients:%s',
refreshToken: 'refresh_tokens:%s',
grantTypes: 'clients:%s:grant_types',
user: 'users:%s'
};

model.getAccessToken = function (bearerToken, callback) {
db.hgetall(util.format(keys.token, bearerToken), function (err, token) {
if (err) return callback(err);

if (!token) return callback();

callback(null, {
accessToken: token.accessToken,
clientId: token.clientId,
expires: token.expires ? new Date(token.expires) : null,
userId: token.userId
});
});
};

model.getClient = function (clientId, clientSecret, callback) {
db.hgetall(util.format(keys.client, clientId), function (err, client) {
if (err) return callback(err);

if (!client || client.clientSecret !== clientSecret) return callback();

callback(null, {
clientId: client.clientId,
clientSecret: client.clientSecret
});
});
};

model.getRefreshToken = function (bearerToken, callback) {
db.hgetall(util.format(keys.refreshToken, bearerToken), function (err, token) {
if (err) return callback(err);

if (!token) return callback();

callback(null, {
refreshToken: token.accessToken,
clientId: token.clientId,
expires: token.expires ? new Date(token.expires) : null,
userId: token.userId
});
});
};

model.grantTypeAllowed = function (clientId, grantType, callback) {
db.sismember(util.format(keys.grantTypes, clientId), grantType, callback);
};

model.saveAccessToken = function (accessToken, clientId, expires, user, callback) {
db.hmset(util.format(keys.token, accessToken), {
accessToken: accessToken,
clientId: clientId,
expires: expires ? expires.toISOString() : null,
userId: user.id
}, callback);
};

model.saveRefreshToken = function (refreshToken, clientId, expires, user, callback) {
db.hmset(util.format(keys.refreshToken, refreshToken), {
refreshToken: refreshToken,
clientId: clientId,
expires: expires ? expires.toISOString() : null,
userId: user.id
}, callback);
};

model.getUser = function (username, password, callback) {
db.hgetall(util.format(keys.user, username), function (err, user) {
if (err) return callback(err);

if (!user || password !== user.password) return callback();

callback(null, {
id: username
});
});
};
27 changes: 27 additions & 0 deletions examples/redis/testData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#! /usr/bin/env node

var db = require('redis').createClient();

db.multi()
.hmset('users:username', {
id: 'username',
username: 'username',
password: 'password'
})
.hmset('clients:client', {
clientId: 'client',
clientSecret: 'secret'
})
.sadd('clients:client:grant_types', [
'password',
'refresh_token'
])
.exec(function (errs) {
if (errs) {
console.error(errs[0].message);
return process.exit(1);
}

console.log('Client and user added successfully');
process.exit();
});
Loading