forked from nodeSolidServer/node-solid-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth-request.js
More file actions
234 lines (193 loc) · 5.82 KB
/
auth-request.js
File metadata and controls
234 lines (193 loc) · 5.82 KB
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
'use strict'
/* eslint-disable node/no-deprecated-api */
const url = require('url')
const debug = require('./../debug').authentication
const IDToken = require('@solid/oidc-op/src/IDToken')
/**
* Hidden form fields from the login page that must be passed through to the
* Authentication request.
*
* @type {Array<string>}
*/
const AUTH_QUERY_PARAMS = ['response_type', 'display', 'scope',
'client_id', 'redirect_uri', 'state', 'nonce', 'request']
/**
* Base authentication request (used for login and password reset workflows).
*/
class AuthRequest {
/**
* @constructor
* @param [options.response] {ServerResponse} middleware `res` object
* @param [options.session] {Session} req.session
* @param [options.userStore] {UserStore}
* @param [options.accountManager] {AccountManager}
* @param [options.returnToUrl] {string}
* @param [options.authQueryParams] {Object} Key/value hashmap of parsed query
* parameters that will be passed through to the /authorize endpoint.
* @param [options.enforceToc] {boolean} Whether or not to enforce the service provider's T&C
* @param [options.tocUri] {string} URI to the service provider's T&C
*/
constructor (options) {
this.response = options.response
this.session = options.session || {}
this.userStore = options.userStore
this.accountManager = options.accountManager
this.returnToUrl = options.returnToUrl
this.authQueryParams = options.authQueryParams || {}
this.localAuth = options.localAuth
this.enforceToc = options.enforceToc
this.tocUri = options.tocUri
}
/**
* Extracts a given parameter from the request - either from a GET query param,
* a POST body param, or an express registered `/:param`.
* Usage:
*
* ```
* AuthRequest.parseParameter(req, 'client_id')
* // -> 'client123'
* ```
*
* @param req {IncomingRequest}
* @param parameter {string} Parameter key
*
* @return {string|null}
*/
static parseParameter (req, parameter) {
const query = req.query || {}
const body = req.body || {}
const params = req.params || {}
return query[parameter] || body[parameter] || params[parameter] || null
}
/**
* Extracts the options in common to most auth-related requests.
*
* @param req
* @param res
*
* @return {Object}
*/
static requestOptions (req, res) {
let userStore, accountManager, localAuth
if (req.app && req.app.locals) {
const locals = req.app.locals
if (locals.oidc) {
userStore = locals.oidc.users
}
accountManager = locals.accountManager
localAuth = locals.localAuth
}
const authQueryParams = AuthRequest.extractAuthParams(req)
const returnToUrl = AuthRequest.parseParameter(req, 'returnToUrl')
const acceptToc = AuthRequest.parseParameter(req, 'acceptToc') === 'true'
const options = {
response: res,
session: req.session,
userStore,
accountManager,
returnToUrl,
authQueryParams,
localAuth,
acceptToc
}
return options
}
/**
* Initializes query params required by Oauth2/OIDC type work flow from the
* request body.
* Only authorized params are loaded, all others are discarded.
*
* @param req {IncomingRequest}
*
* @return {Object}
*/
static extractAuthParams (req) {
let params
if (req.method === 'POST') {
params = req.body
} else {
params = req.query
}
if (!params) { return {} }
const extracted = {}
const paramKeys = AUTH_QUERY_PARAMS
let value
for (const p of paramKeys) {
value = params[p]
// value = value === 'undefined' ? undefined : value
extracted[p] = value
}
// Special case because solid-auth-client does not include redirect in params
if (!extracted.redirect_uri && params.request) {
extracted.redirect_uri = IDToken.decode(params.request).payload.redirect_uri
}
return extracted
}
/**
* Calls the appropriate form to display to the user.
* Serves as an error handler for this request workflow.
*
* @param error {Error}
*/
error (error, body) {
error.statusCode = error.statusCode || 400
this.renderForm(error, body)
}
/**
* Initializes a session (for subsequent authentication/authorization) with
* a given user's credentials.
*
* @param userAccount {UserAccount}
*/
initUserSession (userAccount) {
const session = this.session
debug('Initializing user session with webId: ', userAccount.webId)
session.userId = userAccount.webId
session.subject = {
_id: userAccount.webId
}
return userAccount
}
/**
* Returns this installation's /authorize url. Used for redirecting post-login
* and post-signup.
*
* @return {string}
*/
authorizeUrl () {
const host = this.accountManager.host
const authUrl = host.authEndpoint
authUrl.query = this.authQueryParams
return url.format(authUrl)
}
/**
* Returns this installation's /register url. Used for redirecting post-signup.
*
* @return {string}
*/
registerUrl () {
const host = this.accountManager.host
const signupUrl = url.parse(url.resolve(host.serverUri, '/register'))
signupUrl.query = this.authQueryParams
return url.format(signupUrl)
}
/**
* Returns this installation's /login url.
*
* @return {string}
*/
loginUrl () {
const host = this.accountManager.host
const signupUrl = url.parse(url.resolve(host.serverUri, '/login'))
signupUrl.query = this.authQueryParams
return url.format(signupUrl)
}
sharingUrl () {
const host = this.accountManager.host
const sharingUrl = url.parse(url.resolve(host.serverUri, '/sharing'))
sharingUrl.query = this.authQueryParams
return url.format(sharingUrl)
}
}
AuthRequest.AUTH_QUERY_PARAMS = AUTH_QUERY_PARAMS
module.exports = AuthRequest