Skip to content

Commit

Permalink
feat: allow passing loginHint option to ensureAuthenticated
Browse files Browse the repository at this point in the history
  • Loading branch information
oleksandrpravosudko-okta committed Jan 24, 2022
1 parent 23bba66 commit 78b184c
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"env": {
"node": true
},
"parserOptions": {
"ecmaVersion": 2018
}
}
11 changes: 10 additions & 1 deletion src/connectUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ connectUtil.createOIDCRouter = context => {
};

connectUtil.createLoginHandler = context => {
const passportHandler = passport.authenticate('oidc');
const csrfProtection = csrf();
const ALLOWED_OPTIONS = ['login_hint'];

return function(req, res, next) {
const viewHandler = context.options.routes.login.viewHandler;
Expand Down Expand Up @@ -76,6 +76,15 @@ connectUtil.createLoginHandler = context => {
return res.redirect(authorizationUrl);
});
}
const options = Object.keys(req.query).reduce((opts, option) => {
return ALLOWED_OPTIONS.includes(option) ? {
...opts,
[option]: req.query[option]
} : {
...opts
}
}, {})
const passportHandler = passport.authenticate('oidc', options);
return passportHandler.apply(this, arguments);
}
};
Expand Down
14 changes: 12 additions & 2 deletions src/oidcUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ function customizeUserAgent(options) {
return options;
}

function appendOptionsToQuery(url, options) {
if (options.loginHint) {
const urlObject = new URL(url, 'relative:///');
const searchParams = urlObject.searchParams;
searchParams.append('login_hint', options.loginHint);
// extend original query (if any)
return `${url.split('?').shift()}${urlObject.search}`;
}
return url;
}

oidcUtil.createClient = context => {
const {
issuer,
Expand Down Expand Up @@ -133,9 +144,8 @@ oidcUtil.ensureAuthenticated = (context, options = {}) => {
if (req.session) {
req.session.returnTo = req.originalUrl || req.url;
}

const url = options.redirectTo || context.options.routes.login.path;
return res.redirect(url);
return res.redirect(appendOptionsToQuery(url, options));
}

next();
Expand Down
44 changes: 44 additions & 0 deletions test/unit/connectUtil.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const connectUtil = require('../../src/connectUtil.js');

jest.mock('csurf', function () {
return function () {

}
});

var mockAuthenticate;
jest.mock('passport', function () {
mockAuthenticate = jest.fn().mockReturnValue(() => {})
return {
authenticate: mockAuthenticate
}
})



describe('connectUtil', function () {
describe('createLoginHandler', function () {
it('passes known options to passport handler initializer', function () {
const loginHandler = connectUtil.createLoginHandler({
options: {
routes: {
login: {
}
}
}
});
const res = {};
const req = {
query: {
login_hint: 'username@org.org',
chown_base: true
}
};

loginHandler(req, res);
expect(mockAuthenticate).toBeCalledWith('oidc', {
login_hint: 'username@org.org'
});
});
});
});
29 changes: 27 additions & 2 deletions test/unit/oidcUtil.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ const passport = require('passport');
const OpenIdClient = require('openid-client');
const oidcUtil = require('../../src/oidcUtil.js');

jest.mock('negotiator', function () {
return function () {
return {
mediaType: function () {
return 'text/html';
}
}
}
});

function createMockOpenIdClient(config={}) {
const Issuer = OpenIdClient.Issuer;

Expand Down Expand Up @@ -94,6 +104,21 @@ describe('oidcUtil', function () {
expect(error).toEqual(undefined);
};
passportStrategy.authenticate(createMockRedirectRequest());
})
})
});
});

describe('ensureAuthenticated', () => {
it('appends known options to redirect URL', () => {
const requestHandler = oidcUtil.ensureAuthenticated({}, {
redirectTo: '/login',
loginHint: 'username@org.org'
});
let req = jest.mock();
let res = {
redirect: jest.fn()
};
requestHandler(req, res, () => {});
expect(res.redirect).toBeCalledWith('/login?login_hint=username%40org.org');
});
});
})

0 comments on commit 78b184c

Please sign in to comment.