I am using the Vertx framework on my API for authorization with JWT tokens. After the user is authorized and the token is decrypted I want to access the contents of the token, particularly a "userId" field within the token.
Originally I was accessing this with req
as the RoutingContext
as:
req.user().principal().getString("userId");
This works as intended until it is compiled on a different machine. When compiled on a different machine req.user().principal()
only contains the field access_token
, containing the still encrypted JWT.
The solution to this was to access the user ID through
req.user().attributes().getJsonObject("accessToken").getString("userId");
I've tested this on 4 different machines. 2 of them work using principal, and the other 2 require attributes. It seems to only matter which machine it is compiled on, not what it is run on. The code is not being changed between machines. Java, Maven, and Vertx versions are the same each time.
Some solutions I've found online simply check if the needed field is in principal, and if not to use attributes instead. This seems like a bad workaround though. There has to be a proper way to access it.
What is the proper way to access the values within the decoded token? And why does it seem to change depending on the compiling machine?
In vert.x 3.x the tokens were always decoded to a JSON object and this object would be the
principal
. In vert.x 4 a lot of work has been done on the auth n/z area so the rule of thumb is:principal
contains the "source" properties that allowed the creation of thisUser
object.attributes
contains decoded/generated properties during the auth n/z process.So you should expect the decoded token to always be on
attributes
if you're using vert.x 4. A recent commit added back those properties to theprincipal
for JWT auth in order to keep it backwards compatible.The details: The reason why the token is now not decoded to the
principal
is becauseUser
objects are decoupled from auth providers. So Even though aUser
was created fromJWTAuth
it could be used byOAuth2Auth
. So the internal structure needs to be consistent. Second, Oauth2 with OpenID Connect also uses tokens, but there are several kinds of tokens:access_token
id_token
Decoding these tokens to the principal would mean that, in some cases properties could overlap. One of these overlaps would be the properties related to expiration/validity of the token. Getting the whole
User
validation in a wrong state in some situations.Finally, we can now use vertx auth for server side auth n/z but also for client auth. This means we need to preserve the original raw token (which is the principal) so we can quickly add it without tampering to a client request in order to perform auth "on behalf of".