0

I have a code that decodes JWT tokens, splits the string part that contains claims and converts that info into a JSON object.

return JSON.parse(atob(token.split('.')[1])) as LoggedInUser;

It works but when it comes to user's name, since it has some turkish characters, I get a string with non-readable characters. User's name is "Uğur Gül" in the picture below.

wrongly formatted json object

I think I should somehow parse with utf-8 formatting but can't find how to that. I'm working with angular framework. How can I fix this issue?

Edit: Here is a decoded version of my mock-data token on jwt.io. I'm trying to get the payload from token like the way jwt.io creates an JSON object, and I'm assigning needed values to related fields to an instance of LoggedInUser class.

jwt.io decoded version

emreertunc
  • 37
  • 2
  • 7
  • 1
    The data comes from a backend? Please show me the token data before parsing. – Flo Dec 26 '22 at 08:29
  • @Flo Yes, data comes from backend. Just edited my question. You can check the example data it contains. Token comes from backend is a long string like this one: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" I'm getting the part after first dot. That's payload part. – emreertunc Dec 26 '22 at 08:41
  • 1
    that's "John Doe", show us "Uğur Gül" – gog Dec 26 '22 at 08:54
  • @Flo here is one with "Uğur Gül" "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiIyIiwiVXNlckdpdmVuTmFtZSI6IlXEn3VyIEfDvGwiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiIyIiwiZXhwIjoxNjcyMDQ2Mzc1LCJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo3MDEzLyIsImF1ZCI6Imh0dHBzOi8vbG9jYWxob3N0OjcwMTMvIn0.EERKwS2yfT6TnPJN4zlHyvW4WhrEMmaFLpUh0r8Ej70" – emreertunc Dec 26 '22 at 09:05

1 Answers1

-2

One way is to escape and unescape the name on the backend/frontend. I don't know how your app works.

We use escape and Uğur Gül will converted to U%u011Fur%20G%FCl. Set this to GivenUserName, create the token and send it to the frontend. Frontend decodes it, gave the name and call unescape. So you have the correct name again.

Sample:

data = '{"UserId":"2","UserGivenName":"U%u011Fur%20G%FCl","http://schemas.microsoft.com/ws/2008/06/identity/claims/role":"2","exp":1672046375,"iss":"https://localhost:7013/","aud":"https://localhost:7013/"}'

  constructor() {
    console.log((escape("Uğur Gül")));
    console.log(unescape(escape("Uğur Gül")))

    this.token = (btoa(this.data))
    const jsonData = JSON.parse(atob(this.token));
    console.log(unescape(jsonData.UserGivenName));
  }

Important

escape and unescape are marked as deprecated. You can use encodeURI and decodeURI instead:

    console.log(encodeURI('Uğur Gül'));
    console.log(decodeURI(encodeURI('Uğur Gül')));

Here is a Stackblitz to play.

Flo
  • 2,232
  • 2
  • 11
  • 18
  • Not only _shouldn't_ this be necessary, `escape` is also on the list of deprecated functions you shouldn't use. – deceze Dec 26 '22 at 09:23
  • Look at updated Post – Flo Dec 26 '22 at 09:26
  • Better, but it still doesn't work if you're given a UTF-8 encoded string by a 3rd party which you need to deal with. – deceze Dec 26 '22 at 09:29
  • Then we need to see the backend code, which encode the string. Without it this is a working solution. – Flo Dec 26 '22 at 09:30
  • 1
    As provided in the sample, the backend provides a perfectly fine UTF-8 encoded JWT. It's a known "issue" in JS that decoding base64 containing UTF-8 encoded text to a string is… tricky. I closed this question as a duplicate… – deceze Dec 26 '22 at 09:32