Multiple tokens
Hi, I'm currently using express-jwt as follows:
app.use(expressJwt({
secret: config.jwtSecret,
credentialsRequired: false,
getToken: req => req.cookies.id_token,
}));
I'm using it currently for authentication purposes only: identifying the user. I also want a second token for authorization, with a lower TTL, so a user would have to be authorized more frequently.
How can I offer another token to be extracted to a different property (say, req.roles).
Is what I need makes sense? Is there a better way to achieve what I want? How can this be done using express-jwt? Thanks!
@papigers did you find a solution?
You can chain multiple instances of jwt: app.use(jwt(authConfig), jwt(anotherConfig));
For anotherConfig you definitely need to use the getToken(https://github.com/auth0/express-jwt#customizing-token-location) to read the second token from somewhere else, and the requestProperty option (https://github.com/auth0/express-jwt#retrieving-the-decoded-payload) to write it to another property.
@Narretz the chaining as you described doesn't seem to work, it always just picks the first one? and the second doesn't work?
using it like:
app.use(jwt(JWT_STATION_AUTH), jwt(JWT_USER_AUTH))
@JClackett hard to say why it doesn't work for you. Are you sure you are using getToken and requestProperty?
@Narretz so because the first jwt config would throw an error when the first config wasn't found, it skipped the second and went to my error handler. I fixed by doing:
maybe there's another way? but this works just annoying having separate error handlers but oh well
this.app
.use(expressJwt(JWT_USER_AUTH))
.use((err: any, _: any, __: any, next: any) => {
if (err.name === "UnauthorizedError") next()
})
.use(expressJwt(JWT_STATION_AUTH))
.use((err: any, _: any, __: any, next: any) => {
if (err.name === "UnauthorizedError") next()
})
@JClackett but now everything passes through, even when you don't have any tokens. What you want is to combine your two middlewares into one that requires that at least one of the given middlewares (expressJwt(JWT_USER_AUTH) or expressJwt(JWT_STATION_AUTH)) succeeded.
@vidstige I don't need it to throw an error though, just assign the appropriate property on the req object. this seems to be working as I expect? not sure what the best way of combining them would be
Yeah, I ran into this exact same thing, and it's not clear how to combine them in a good way. The thing is if you only have one jwt-express middleware, then it will etiher populate req.user or throw an error. This ensures you do not serve sensitive data unless a valid token is provided. So after considering this, imho, the most sensible semantics would be if one first middlewares you're combining does not error, you bail out and are happy. If it errors, you go to the next one. Except when it's the last one, then you want it to error. So a bit messy there. I looked into the connect api and so on, and it's not clear to me how to do it in a neat way, but I'm sure it can be done.
One workaround I guess, is to do what you did and then have a fifth middleware after that checks that req.user was indeed populated, but feels brittle and furthermore you loose the exact error message (token expired or whatever). :thinking:
I made a custom secret provider instead as a workaround for the time being, but that as well comes with drawbacks.