-
-
Notifications
You must be signed in to change notification settings - Fork 33
/
password-grant-type.js
133 lines (105 loc) 路 3.29 KB
/
password-grant-type.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
'use strict';
/**
* Module dependencies.
*/
var AbstractGrantType = require('./abstract-grant-type');
var InvalidArgumentError = require('../errors/invalid-argument-error');
var InvalidGrantError = require('../errors/invalid-grant-error');
var InvalidRequestError = require('../errors/invalid-request-error');
var Promise = require('bluebird');
var promisify = require('promisify-any').use(Promise);
var is = require('../validator/is');
var util = require('util');
/**
* Constructor.
*/
function PasswordGrantType(options) {
options = options || {};
if (!options.model) {
throw new InvalidArgumentError('Missing parameter: `model`');
}
if (!options.model.getUser) {
throw new InvalidArgumentError('Invalid argument: model does not implement `getUser()`');
}
if (!options.model.saveToken) {
throw new InvalidArgumentError('Invalid argument: model does not implement `saveToken()`');
}
AbstractGrantType.call(this, options);
}
/**
* Inherit prototype.
*/
util.inherits(PasswordGrantType, AbstractGrantType);
/**
* Retrieve the user from the model using a username/password combination.
*
* @see https://tools.ietf.org/html/rfc6749#section-4.3.2
*/
PasswordGrantType.prototype.handle = function(request, client) {
if (!request) {
throw new InvalidArgumentError('Missing parameter: `request`');
}
if (!client) {
throw new InvalidArgumentError('Missing parameter: `client`');
}
var scope = this.getScope(request);
return Promise.bind(this)
.then(function() {
return this.getUser(request);
})
.then(function(user) {
return this.saveToken(user, client, scope);
});
};
/**
* Get user using a username/password combination.
*/
PasswordGrantType.prototype.getUser = function(request) {
if (!request.body.username) {
throw new InvalidRequestError('Missing parameter: `username`');
}
if (!request.body.password) {
throw new InvalidRequestError('Missing parameter: `password`');
}
if (!is.uchar(request.body.username)) {
throw new InvalidRequestError('Invalid parameter: `username`');
}
if (!is.uchar(request.body.password)) {
throw new InvalidRequestError('Invalid parameter: `password`');
}
return promisify(this.model.getUser, 2).call(this.model, request.body.username, request.body.password)
.then(function(user) {
if (!user) {
throw new InvalidGrantError('Invalid grant: user credentials are invalid');
}
return user;
});
};
/**
* Save token.
*/
PasswordGrantType.prototype.saveToken = function(user, client, scope) {
var fns = [
this.validateScope(user, client, scope),
this.generateAccessToken(client, user, scope),
this.generateRefreshToken(client, user, scope),
this.getAccessTokenExpiresAt(),
this.getRefreshTokenExpiresAt()
];
return Promise.all(fns)
.bind(this)
.spread(function(scope, accessToken, refreshToken, accessTokenExpiresAt, refreshTokenExpiresAt) {
var token = {
accessToken: accessToken,
accessTokenExpiresAt: accessTokenExpiresAt,
refreshToken: refreshToken,
refreshTokenExpiresAt: refreshTokenExpiresAt,
scope: scope
};
return promisify(this.model.saveToken, 3).call(this.model, token, client, user);
});
};
/**
* Export constructor.
*/
module.exports = PasswordGrantType;