I'm creating an JSON API with express and I'm using Passport with the HTTP Bearer strategy for authentication.
I've added passport.authenticate('bearer', {session: false})
as middleware. But whenever something is wrong with the session it simply responds with the body Unauthorized and status 401. The actual information is in the WWW-Authenticate
header, in the form of a challenge, something like:
Bearer realm="Users", error="invalid_token", error_description="invalid token"
And when no authentication tokens where given:
Bearer realm="Users"
I'd like to change the response into json which includes the error information.
As I don't have a lot of experience writing things for the backend, I've been reading through the docs and code.
The Bearer strategy simply calls fail with 400
or a challenge string. Basically there is where my issue begins, since I don't want to write a parser for these challenge strings, why isn't this information passed as regular variables?
In Passport's authenticate middleware this challenge is then, depending on your config, passed to callback, req.flash, the session and/or the WWW-Authenticate header. Looking through this code it tries to actually retrieve challenge.type
and challenge.message
first. When failure handling is not delegated to the application it checks whether the challenges are strings and if so puts them into the WWW-Authenticate header. This might be the reason the bearer strategy returns the challenge as string?
So maybe in my case it makes sense to supply a callback, so that I can directly access these challenges?
But then still, bearer's challenge is a string which requires parsing?
Are people not using this bearer strategy for JSON API's?
The default failure response in
passport
is here:https://github.com/jaredhanson/passport/blob/master/lib/middleware/authenticate.js#L174
However, if you provide an
authenticate
callback
it will run this code:https://github.com/jaredhanson/passport/blob/master/lib/middleware/authenticate.js#L107
So the solution is to provide a callback argument to
authenticate(passport, name, options, callback)
. You can then you can intercept the authentication failures and respond to them as you please.Note that the
res
object is not actually passed to your callback. You will have to wrap your call toauthenticate
like so to respond: