Skip to content

Commit 9161d11

Browse files
Pass returnToUrl to /register, refactor
1 parent 18d75da commit 9161d11

File tree

4 files changed

+93
-42
lines changed

4 files changed

+93
-42
lines changed

default-views/auth/login.hbs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@
4242
</div>
4343
<button type="submit" class="btn btn-primary" id="login">Login</button>
4444

45-
<div>Don't have an account? <a href="/register?{{{authParams}}}">Register</a></div>
45+
<div>Don't have an account?
46+
<a href="/register?returnToUrl={{{postRegisterUrl}}}">Register</a>
47+
</div>
4648
</form>
4749
</div>
4850
</body>

lib/api/authn/webid-oidc.js

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ function middleware (oidc) {
4141
})
4242
router.post('/api/auth/select-provider', bodyParser, selectProvider)
4343

44-
router.get(['/login', '/signin'], (req, res) => {
44+
router.get(['/login', '/signin'], LoginByPasswordRequest.get)
45+
router.post(['/login', '/signin'], bodyParser, LoginByPasswordRequest.post)
46+
47+
router.get('/register', (req, res) => {
4548
let params = Object.assign({}, req.query, { authParams: url.parse(req.url).query })
46-
res.render('auth/login', params)
49+
res.render('auth/register', params)
4750
})
48-
router.post(['/login', '/signin'], bodyParser, login)
4951

5052
router.get('/goodbye', (req, res) => {
5153
res.render('auth/goodbye')
@@ -83,14 +85,6 @@ function selectProvider (req, res, next) {
8385
})
8486
}
8587

86-
function login (req, res, next) {
87-
return LoginByPasswordRequest.handle(req, res)
88-
.catch(error => {
89-
error.status = error.status || 400
90-
next(error)
91-
})
92-
}
93-
9488
function authCodeFlowCallback (oidc, req) {
9589
debug.oidc('in authCodeFlowCallback()')
9690

@@ -157,7 +151,6 @@ function resumeUserFlow (req, res) {
157151
module.exports = {
158152
middleware,
159153
selectProvider,
160-
login,
161154
extractWebId,
162155
authCodeFlowCallback,
163156
getIssuerId,

lib/requests/login-request.js

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const UserAccount = require('../models/user-account')
1010
* Models a Login request, a POST submit from a Login form with a username and
1111
* password. Used with authMethod of 'oidc'.
1212
*
13-
* For usage example, see `handle()` docstring, below.
13+
* For usage example, see `post()` and `get()` docstrings, below.
1414
*/
1515
class LoginByPasswordRequest {
1616
/**
@@ -42,24 +42,36 @@ class LoginByPasswordRequest {
4242
}
4343

4444
/**
45-
* Handles a Login request on behalf of a middleware handler. Usage:
45+
* Handles a Login GET request on behalf of a middleware handler. Usage:
4646
*
4747
* ```
48-
* app.post('/login', (req, res, next) = {
49-
* LoginByPasswordRequest.handle(req, res)
50-
* .catch(next)
51-
* })
48+
* app.get('/login', LoginByPasswordRequest.get)
5249
* ```
5350
*
5451
* @param req {IncomingRequest}
5552
* @param res {ServerResponse}
5653
*
57-
* @throws {Error} HTTP 400 error if required parameters are missing, or
58-
* if the user is not found or the password does not match.
54+
* @return {Promise}
55+
*/
56+
static get (req, res) {
57+
const request = LoginByPasswordRequest.fromParams(req, res)
58+
59+
request.renderView()
60+
}
61+
62+
/**
63+
* Handles a Login POST request on behalf of a middleware handler. Usage:
64+
*
65+
* ```
66+
* app.post('/login', LoginByPasswordRequest.post)
67+
* ```
68+
*
69+
* @param req {IncomingRequest}
70+
* @param res {ServerResponse}
5971
*
6072
* @return {Promise}
6173
*/
62-
static handle (req, res) {
74+
static post (req, res) {
6375
const request = LoginByPasswordRequest.fromParams(req, res)
6476

6577
return LoginByPasswordRequest.login(request)
@@ -97,7 +109,7 @@ class LoginByPasswordRequest {
97109
session: req.session,
98110
userStore,
99111
accountManager,
100-
authQueryParams: LoginByPasswordRequest.extractQueryParams(body)
112+
authQueryParams: LoginByPasswordRequest.extractParams(req)
101113
}
102114

103115
return new LoginByPasswordRequest(options)
@@ -132,18 +144,25 @@ class LoginByPasswordRequest {
132144
* Initializes query params required by OIDC work flow from the request body.
133145
* Only authorized params are loaded, all others are discarded.
134146
*
135-
* @param body {Object} Key/value hashmap, ie `req.body`.
147+
* @param req {IncomingRequest}
136148
*
137149
* @return {Object}
138150
*/
139-
static extractQueryParams (body) {
151+
static extractParams (req) {
152+
let params
153+
if (req.method === 'POST') {
154+
params = req.body || {}
155+
} else {
156+
params = req.query || {}
157+
}
158+
140159
let extracted = {}
141160

142161
let paramKeys = LoginByPasswordRequest.AUTH_QUERY_PARAMS
143162
let value
144163

145164
for (let p of paramKeys) {
146-
value = body[p]
165+
value = params[p]
147166
value = value === 'undefined' ? undefined : value
148167
extracted[p] = value
149168
}
@@ -153,8 +172,18 @@ class LoginByPasswordRequest {
153172

154173
error (error) {
155174
let res = this.response
156-
let params = Object.assign({}, this.authQueryParams, { error: error.message })
157-
res.statusCode(error.statusCode || 400)
175+
let params = Object.assign({}, this.authQueryParams, {error: error.message})
176+
177+
res.status(error.statusCode || 400)
178+
179+
res.render('auth/login', params)
180+
}
181+
182+
renderView () {
183+
let res = this.response
184+
let params = Object.assign({}, this.authQueryParams,
185+
{ postRegisterUrl: this.postRegisterUrl() })
186+
158187
res.render('auth/login', params)
159188
}
160189

@@ -259,20 +288,45 @@ class LoginByPasswordRequest {
259288
return url.format(authUrl)
260289
}
261290

262-
/**
263-
* Redirects the Login request to continue on the OIDC auth workflow.
264-
*/
265-
redirectPostLogin (validUser) {
291+
postLoginUrl (validUser) {
266292
let uri
267293

268294
if (this.authQueryParams['redirect_uri']) {
269295
// Login request is part of an app's auth flow
270296
uri = this.authorizeUrl()
271-
} else {
297+
} else if (validUser) {
272298
// Login request is a user going to /login in browser
273299
uri = this.accountManager.accountUriFor(validUser.username)
300+
} else {
301+
let host = this.accountManager.host
302+
uri = host.serverUri
303+
}
304+
305+
return uri
306+
}
307+
308+
postRegisterUrl () {
309+
let uri
310+
311+
if (this.authQueryParams['redirect_uri']) {
312+
// Login/register request is part of an app's auth flow
313+
uri = this.authorizeUrl()
314+
} else {
315+
let host = this.accountManager.host
316+
uri = host.serverUri
274317
}
275318

319+
uri = encodeURIComponent(uri)
320+
321+
return uri
322+
}
323+
324+
/**
325+
* Redirects the Login request to continue on the OIDC auth workflow.
326+
*/
327+
redirectPostLogin (validUser) {
328+
let uri = this.postLoginUrl(validUser)
329+
276330
debug('Login successful, redirecting to ', uri)
277331

278332
this.response.redirect(uri)

test/unit/login-by-password-request.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const host = SolidHost.from({ serverUri: 'https://localhost:8443' })
2727
const accountManager = AccountManager.from({ host, authMethod })
2828

2929
describe('LoginByPasswordRequest', () => {
30-
describe('handle()', () => {
30+
describe('post()', () => {
3131
let res, req
3232

3333
beforeEach(() => {
@@ -43,7 +43,7 @@ describe('LoginByPasswordRequest', () => {
4343
let loginStub = sinon.stub(LoginByPasswordRequest, 'login')
4444
.returns(Promise.resolve())
4545

46-
return LoginByPasswordRequest.handle(req, res)
46+
return LoginByPasswordRequest.post(req, res)
4747
.then(() => {
4848
expect(fromParams).to.have.been.calledWith(req, res)
4949
fromParams.reset()
@@ -59,7 +59,7 @@ describe('LoginByPasswordRequest', () => {
5959
it('should invoke login()', () => {
6060
let login = sinon.spy(LoginByPasswordRequest, 'login')
6161

62-
return LoginByPasswordRequest.handle(req, res)
62+
return LoginByPasswordRequest.post(req, res)
6363
.then(() => {
6464
expect(login).to.have.been.called
6565
login.reset()
@@ -89,10 +89,10 @@ describe('LoginByPasswordRequest', () => {
8989
})
9090

9191
it('should initialize the query params', () => {
92-
let extractQueryParams = sinon.spy(LoginByPasswordRequest, 'extractQueryParams')
92+
let extractParams = sinon.spy(LoginByPasswordRequest, 'extractParams')
9393
LoginByPasswordRequest.fromParams(req, res)
9494

95-
expect(extractQueryParams).to.be.calledWith(req.body)
95+
expect(extractParams).to.be.calledWith(req)
9696
})
9797
})
9898

@@ -349,12 +349,13 @@ describe('LoginByPasswordRequest', () => {
349349
return body
350350
}
351351

352-
describe('extractQueryParams()', () => {
352+
describe('extractParams()', () => {
353353
let body = testAuthQueryParams()
354354
body['other_key'] = 'whatever'
355+
let req = { body, method: 'POST' }
355356

356357
it('should initialize the auth url query object from params', () => {
357-
let extracted = LoginByPasswordRequest.extractQueryParams(body)
358+
let extracted = LoginByPasswordRequest.extractParams(req)
358359

359360
for (let param of LoginByPasswordRequest.AUTH_QUERY_PARAMS) {
360361
expect(extracted[param]).to.equal(body[param])
@@ -376,9 +377,10 @@ describe('LoginByPasswordRequest', () => {
376377

377378
it('should pass through relevant auth query params from request body', () => {
378379
let body = testAuthQueryParams()
380+
let req = { body, method: 'POST' }
379381

380382
let request = new LoginByPasswordRequest({ accountManager })
381-
request.authQueryParams = LoginByPasswordRequest.extractQueryParams(body)
383+
request.authQueryParams = LoginByPasswordRequest.extractParams(req)
382384

383385
let authUrl = request.authorizeUrl()
384386

@@ -441,7 +443,7 @@ describe('LoginByPasswordRequest', () => {
441443

442444
let options = { accountManager, response: res }
443445
let request = new LoginByPasswordRequest(options)
444-
request.authQueryParams = LoginByPasswordRequest.extractQueryParams(body)
446+
request.authQueryParams = LoginByPasswordRequest.extractParams(body)
445447

446448
request.authorizeUrl = sinon.stub().returns(authUrl)
447449

0 commit comments

Comments
 (0)