-
Notifications
You must be signed in to change notification settings - Fork 14
Passport JWT strategy for mobile #110
Passport JWT strategy for mobile #110
Conversation
@@ -28,12 +31,16 @@ export class PassportAuth implements EndpointSecurity { | |||
* @param app - An express application | |||
* @param sessionOpts - Session options to be used by express-session |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add note that when skipping this session is not being used.
@@ -111,7 +140,23 @@ export class PassportAuth implements EndpointSecurity { | |||
* @param passportApi - passport.js instance | |||
*/ | |||
protected setup(passportApi: passport.Passport) { | |||
const options = { | |||
jwtFromRequest: ExtractJwt.fromAuthHeader(), | |||
secretOrKey: 'secret' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remember to extract and document that as keeping this secret
is crucial for general application security.
} | ||
}); | ||
|
||
router.post('/login-mobile', authService.authenticate('jwt'), (req, res, next) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this is needed? Probably forgot to remove it?
Checked changes locally. Great progress so far. |
*/ | ||
public init(app: express.Router, sessionOpts?: SessionOptions) { | ||
public init(app: express.Router, sessionOpts?: SessionOptions, secret?: string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
secret?: any
may be better => That's restrictive as people may pass also key (which is probably better to secure this)
}; | ||
this.userRepo.getUserByLogin(jwtPayload.username, callback); | ||
})); | ||
protected setup(passportApi: passport.Passport, jwtOpts?: JwtOptions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing documentation for parameter.
this.userRepo.getUserByLogin(jwtPayload.username, callback); | ||
})); | ||
} else { | ||
passportApi.use(new Strategy(defaultStrategy(this.userRepo, this.userService))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw. - wit this change our defaultStrategy
may not be as accurate as before. WDYT to rename this to WebStrategy to reflect the use case?
})); | ||
protected setup(passportApi: passport.Passport, jwtOpts?: JwtOptions) { | ||
if (jwtOpts) { | ||
passportApi.use(new JwtStrategy(jwtOpts, (jwtPayload, done) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Optional] [style] If default strategy is extracted to separate file let's have this as well.
}; | ||
this.userRepo.getUserByLogin(jwtPayload.username, callback); | ||
})); | ||
protected setup(passportApi: passport.Passport, jwtOpts?: JwtOptions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Question] Do we still using interface for this? I think we may actually not need
We can have two setup methods once with jwtOptions and second that will setup session based strategy? This will save you another if and will make code cleaner.
We can even add name to provide more context.
setupToken and setupCookie etc.
demo/server/config-dev.json
Outdated
@@ -19,5 +19,9 @@ | |||
}, | |||
"redis": { | |||
"url": "redis://127.0.0.1:6379" | |||
}, | |||
"jwtSecret": "raincatcher", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will suggest here to put really long generated hash (min 250bits).
It's also important to document this properly.
demo/server/config-dev.json
Outdated
}, | ||
"jwtSecret": "raincatcher", | ||
"clientUrl": { | ||
"portal": "http://localhost:9003/?url=http://localhost:8001" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Bug] 💯 That's not goingto work for any other environment apart from local development.
Having it this way will also mean additional setup instruction to this.
Overall -1 for this parameter, but we probably need to talk about it to get proper intentions here.
demo/server/src/modules/index.ts
Outdated
demoDataSetup(connectionPromise); | ||
|
||
const portalApp = express.Router(); | ||
portalsecurityMiddleware = securitySetup(portalApp, sessionOpts); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Proposition] As mentioned above we do not use interface. Let's just rename this to reflect what we really setting this up. This method is just helper to setup passport strategy (simplification, hiding complexity)
return res.render('login', { | ||
title: 'Portal Feedhenry Workforce Management' | ||
}); | ||
}); | ||
|
||
router.post('/login', authService.authenticate('local', '/', '/loginError')); | ||
router.post('/login', authService.authenticate('local', { | ||
successReturnToOrRedirect: config.clientUrl.portal, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above: Worth reading as inspiration: http://www.baeldung.com/spring-security-redirect-login
|
||
router.get('/loginError', (req: express.Request, res: express.Response) => { | ||
return res.render('login', { | ||
title: 'Feedhenry Workforce Management', | ||
title: 'Portal Feedhenry Workforce Management', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Style][Optional] Portal Feedhenry Workforce Management
=> RainCatcher Portal
[Optional] - Externalize to config.
[Optional] - Move to passport (as they are now really connected to the actual strategies) not universal.
|
||
router.get('/loginError', (req: express.Request, res: express.Response) => { | ||
return res.render('login', { | ||
title: 'Feedhenry Workforce Management', | ||
title: 'Portal Feedhenry Workforce Management', | ||
message: 'Invalid credentials'}); | ||
}); | ||
|
||
router.get('/profile', authService.protect(), (req: express.Request, res: express.Response) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Question] Is that used in portal only? Maybe comment.
|
||
router.get('/loginError', (req: express.Request, res: express.Response) => { | ||
return res.render('login', { | ||
title: 'Feedhenry Workforce Management', | ||
title: 'Portal Feedhenry Workforce Management', | ||
message: 'Invalid credentials'}); | ||
}); | ||
|
||
router.get('/profile', authService.protect(), (req: express.Request, res: express.Response) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proper format will be user/profile
@JameelB - Exceptional work. There is one bug we can deal with and couple a minor improvements. |
import { UserRepository } from '../user/UserRepository'; | ||
import { UserService } from '../user/UserService'; | ||
|
||
import { EndpointSecurity } from '@raincatcher/express-auth'; | ||
import { defaultStrategy } from './DefaultStrategy'; | ||
import { jwtStrategy, webStrategy } from './DefaultStrategy'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Very optional] DefaultStrategy
may be plural here : DefaultStrategies
.
demo/server/config-prod.json
Outdated
"jwtSecret": "raincatcher", | ||
"clientUrl": { | ||
"portal": "http://localhost:9003/?url=http://localhost:8001" | ||
"jwtSecret": "D837131FD17F62CB85FBD5919563086369691F4D42379C3596F811839A8992CBA1FBA88DF243BF2481940F112D339C33283BDFEF29A13612550EDAAAB7B5E061", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping @austincunningham - that's update for demo passport auth setup.
Users will need to change that in order to make sure that solution is secure.
@JameelB - Marking as approved for now, but let's not merge until angularjs work will be reviewed and tested. Unit tests needs minor tweak:
|
4766c5c
to
21f2060
Compare
Changes Unknown when pulling 8e531a9 on JameelB:offline-mobile-auth into ** on feedhenry-raincatcher:master**. |
1 similar comment
Changes Unknown when pulling 8e531a9 on JameelB:offline-mobile-auth into ** on feedhenry-raincatcher:master**. |
Changes Unknown when pulling 86629f3 on JameelB:offline-mobile-auth into ** on feedhenry-raincatcher:master**. |
Changes Unknown when pulling 7c220c4 on JameelB:offline-mobile-auth into ** on feedhenry-raincatcher:master**. |
1 similar comment
Changes Unknown when pulling 7c220c4 on JameelB:offline-mobile-auth into ** on feedhenry-raincatcher:master**. |
Changes Unknown when pulling 3ce0a2d on JameelB:offline-mobile-auth into ** on feedhenry-raincatcher:master**. |
const token = req.headers.authorization.toString().substring(4); | ||
try { | ||
const user = jwt.verify(token, this.jwtOpts.secretOrKey); | ||
hasRole = role ? this.userService.hasResourceRole(user, role) : true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO role ? A : B
makes this code unreadable - try to avoid that in the future, especially in mission critical code like security implementation.
req.session.clientURL = req.session.returnTo; | ||
let hasRole; | ||
|
||
if (req.headers && req.headers.authorization) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be wort to check if auth is JWT.
Motivation
The current strategy that Passport is using for mobile is not working properly due to the implications listed on RAINCATCH-1192.
Description
Add Passport's JWT strategy for mobile authentication instead of cookies.
Progress
Additional Notes
Related JIRA - https://issues.jboss.org/browse/RAINCATCH-1209