Web Core and JWT Token

I'm receiving a token from a singe-sign-on system as a parameter of my web core client.
I need to decode this token in order to get the user_id using HS256 algorithm.

I give an example of the url I receive :

.................../Project.html?key=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.G9FrgfaW2FA7pHyY6mUtrXiPrNcztpmbTAVTNlTJ204

I can read the key (which is the JWT issued by the server during the login process) and use it to dialog with the Rest Server as well as to decode the user_id which is the operation I need to implement ...
I know the secret key which is for this example X0785b (both token and key are actual data).

Can anyone can help me on that ?

Thanks

type or paste code here

There is no builtin functions to decrypt HS256. You would need find and use a specific JS library using the asm directive, using JavaScript code. However, I don't think decrypting tokens client side is a good practice, your token secret should never be available from the browser.

1 Like

The user_id is stored in the claims portion of the jwt: eyJ1c2VyX2lkIjoxfQ. That information is base64 encoded. In delphi there is the unit System.NetEncoding. Simply call TNetEncoding.Base64.Decode('eyJ1c2VyX2lkIjoxfQ') which will give you: '{"user_id":1}'.

Typically you would create a Webservice which will authenticate your user and return a jwt with a corresponding claim-Section.
When you call the webservice and the user is properly authenticated, you can then use the jwt for future webservice-requests where you add an authorization header segment with a value of Bearer = jwt-Token.
If you want to add a claim, simply create another web-service providing the current jwt in the authorization header and the claim you want to add. In the webservice you could parse the curent claims and add the claim. Then the webservice creates another signed jwt and returns it.

Don't put any routines in Web core which will use the secret to sign jwts! Then that secret will be part of the downloaded java script of the application. That's not what you want! Use Webservices to check the validity of a jwt. Once verified, you can decode the base64 encoded claim section and use the data from there. That way the secret stays in the routines of the Webservice and cannot be compromised.

Hope this helps

2 Likes

Thanks Andreas, it helps a lot. I'm all set now with that !

Here's what I've got in my project. The XData server returns a JWT to the webcore client via a service operation. Various claims are stored in the JWT. In this case I'm after one called 'usr' which is the database username, different perhaps than the login credentials (typically email address). So the client doesn't otherwise know this bit of information and doesn't need the user to know about it either.

Basic idea (as from the previous comments here) is to get the second part of the JWT, the bits between the two periods, and run it through a Base64 decode, giving you a JSON-type list of claims. Then use JSON methods to get the claim of interest.

// JWT is just a string populated elsewhere
var
  JWTClaims: TJSONObject;
  Username: String;

begin
  JWTClaims :=  TJSONObject.ParseJSONValue(Window.atob(Copy(JWT, Pos('.', JWT)+1, LastDelimiter('.', JWT)-Pos('.', JWT)-1))) as TJSONObject;
  Username :=  (JWTClaims.Get('usr').JSONValue as TJSONString).Value;
  JWTClaims.Free;
end;

Not sure if there is a cleaner way to do it, but this seems to work ok.

2 Likes

That's correct. In Web Core, I would advise to use the JSON classes from JS unit, which in this case is TJSObject. That's personal preference, since those are the native ones from the browser. The TJSONObject are wrappers built for compatibility with Delphi code.