| 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234 |
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
49x
1x
1x
49x
49x
49x
22x
22x
20x
22x
20x
22x
22x
22x
1x
49x
1x
1x
49x
27x
27x
1x
1x
1x
49x
49x
1x
1x
49x
1x
49x
1x
49x
1x
49x
45x
20x
20x
25x
4x
4x
| /*!
Copyright 2014-2017 OCAD university
Licensed under the New BSD license. You may not use this file except in
compliance with this License.
The research leading to these results has received funding from the European Union's
Seventh Framework Programme (FP7/2007-2013) under grant agreement no. 289016.
You may obtain a copy of the License at
https://github.com/GPII/universal/blob/master/LICENSE.txt
*/
"use strict";
var bodyParser = require("body-parser");
var oauth2orize = require("oauth2orize");
var passportModule = require("passport");
var ClientPasswordStrategy = require("passport-oauth2-client-password").Strategy;
var fluid = require("infusion");
require("../../gpii-oauth2-datastore");
require("../../gpii-oauth2-utilities");
require("./AuthorizationService");
require("./AuthGrantFinder");
require("./ClientService");
require("./CodeGenerator");
var gpii = fluid.registerNamespace("gpii");
// gpii.oauth2.oauth2orizeServer
// -----------------------------
gpii.oauth2.createOauth2orizeServer = function () {
return oauth2orize.createServer();
};
fluid.defaults("gpii.oauth2.oauth2orizeServer", {
gradeNames: ["fluid.component"],
members: {
oauth2orizeServer: {
expander: {
func: "gpii.oauth2.createOauth2orizeServer"
}
}
},
listeners: {
onCreate: {
listener: "gpii.oauth2.oauth2orizeServer.listenOauth2orize",
args: ["{that}.oauth2orizeServer", "{clientService}", "{authorizationService}"]
}
}
});
gpii.oauth2.oauth2orizeServer.listenOauth2orize = function (oauth2orizeServer, clientService, authorizationService) {
oauth2orizeServer.serializeClient(function (client, done) {
return done(null, client.id);
});
oauth2orizeServer.deserializeClient(function (id, done) {
var clientPromise = clientService.getClientById(id);
gpii.oauth2.oauth2orizeServer.promiseToDone(clientPromise, done);
});
oauth2orizeServer.exchange(oauth2orize.exchange.password(function (client, username, password, scope, done) {
var passwordPromise = authorizationService.grantGpiiAppInstallationAuthorization(username, client.id);
var authorizationMapper = function (authorization) {
return authorization.accessToken;
};
var paramsMapper = function (params) {
// extra parameters to be included in the `oauth2orizeServer` response except `accessToken`
return fluid.censorKeys(params, "accessToken");
};
var authorizationPromise = fluid.promise.map(passwordPromise, authorizationMapper);
var paramsPromise = fluid.promise.map(passwordPromise, paramsMapper);
gpii.oauth2.oauth2orizeServer.promiseToDone(authorizationPromise, done, paramsPromise);
}));
};
// gpii.oauth2.passport
// --------------------
gpii.oauth2.createPassport = function () {
return new passportModule.Passport();
};
fluid.defaults("gpii.oauth2.passport", {
gradeNames: ["fluid.component"],
members: {
passport: {
expander: {
func: "gpii.oauth2.createPassport"
}
}
},
listeners: {
onCreate: {
listener: "gpii.oauth2.passport.listenPassport",
args: ["{that}.passport", "{clientService}"]
}
}
});
// TODO what name here?
gpii.oauth2.passport.listenPassport = function (passport, clientService) {
// ClientPasswordStrategy reads the client_id and client_secret from the
// request body. Can also use a BasicStrategy for HTTP Basic authentication.
passport.use(new ClientPasswordStrategy(
function (oauth2ClientId, oauth2ClientSecret, done) {
var clientPromise = clientService.authenticateClient(oauth2ClientId, oauth2ClientSecret);
gpii.oauth2.oauth2orizeServer.promiseToDone(clientPromise, done);
}
));
};
// gpii.oauth2.authServer
// ----------------------
// An empty grade to guide resolution of IoC expressions onto a suitable gpii.oauth2.dataStore
fluid.defaults("gpii.oauth2.dataStoreHolder", {
gradeNames: ["fluid.component"]
});
fluid.defaults("gpii.oauth2.authServer", {
gradeNames: ["fluid.component", "gpii.oauth2.dataStoreHolder"],
members: {
expressApp: {
expander: {
func: "gpii.oauth2.createExpressApp"
}
}
},
components: {
oauth2orizeServer: {
type: "gpii.oauth2.oauth2orizeServer"
},
passport: {
type: "gpii.oauth2.passport"
},
dataStore: {
type: "gpii.oauth2.dataStore" // variants here
},
authorizationService: {
type: "gpii.oauth2.authorizationService",
options: {
components: {
dataStore: "{gpii.oauth2.dataStoreHolder}.dataStore"
}
}
},
clientService: {
type: "gpii.oauth2.clientService",
options: {
components: {
dataStore: "{gpii.oauth2.dataStoreHolder}.dataStore"
}
}
}
},
events: {
onContributeRouteHandlers: null
},
listeners: {
onContributeRouteHandlers: {
listener: "gpii.oauth2.authServer.contributeRouteHandlers",
args: ["{that}", "{that}.oauth2orizeServer.oauth2orizeServer",
"{that}.passport.passport"]
},
"onCreate.registerBodyParser": "gpii.oauth2.authServer.registerBodyParser"
}
});
gpii.oauth2.authServer.registerBodyParser = function (that) {
that.expressApp.use(gpii.oauth2.jsonBodyParser());
that.expressApp.use(gpii.oauth2.urlencodedBodyParser());
};
fluid.defaults("gpii.oauth2.authServer.standalone", {
gradeNames: ["gpii.oauth2.authServer"],
listeners: {
"onCreate.onContributeRouteHandlers": {
priority: "after:registerBodyParser",
func: "{that}.events.onContributeRouteHandlers.fire"
}
}
});
gpii.oauth2.jsonBodyParser = function () {
return bodyParser.json();
};
gpii.oauth2.urlencodedBodyParser = function () {
return bodyParser.urlencoded({ extended: true });
};
gpii.oauth2.authServer.contributeRouteHandlers = function (that, oauth2orizeServer, passport) {
that.expressApp.post("/access_token",
passport.authenticate("oauth2-client-password", { session: false }),
oauth2orizeServer.token()
);
};
/*
* An utility function to parse a promise object to determine whether to grant or reject an authorization. The grant occurs in the promise resolve callback while
* the reject occurs in the promise reject callback.
* @param promise {Promise} The promise object to determine the grant or reject an authorization.
* @param done {Function} The oauth2orizeServer endpoint function to grant or reject when a client requests authorization.
* @param paramsPromise {Object} Contains additional parameters to be included in the success response.
* See [oauth2orize in github](https://github.com/jaredhanson/oauth2orize) for more information
* @return The result of invoking done() within the promise callback. At the promise onResolve, done() is called with the resolved value as its parameter,
* and the resolved value of paramsPromise as the additional parameter.
* At the promise onReject, done() is called with the error.
*/
gpii.oauth2.oauth2orizeServer.promiseToDone = function (promise, done, paramsPromise) {
promise.then(function (data) {
if (paramsPromise) {
paramsPromise.then(function (params) {
done(null, data, null, params);
});
} else {
done(null, data);
}
}, function (error) {
var responseError = new oauth2orize.OAuth2Error(error.msg, null, null, error.statusCode);
done(responseError, false);
});
};
|