9

The JWT RFC does not seem to have any problem containing complex arrays such as:

{
    "email": "test@test.com",
    "businesses": [
        {
            "businessId": "1",
            "businessName": "One",
            "roles": [
                  "admin",
                  "accountant"
            ]
        },
        {
            "businessId": "2",
            "businessName": "Two",
            "roles": [
                  "support"
            ]
        }
     ]
}

And this seems a desirable scenario for our needs, since as part of the token we'd like to have a list of businesses a user has access to and what roles does he have for each business (it's part of its identity). The authorization policies at the API would later understand those groups and apply the required authorization logic.

I have seen that with IdentityServer4 the claims are added to the ProfileDataRequestContext's IEnumerable<Claim> IssuedClaims property.

Is there any recommended alternative to this complex claim structure? If not, is there any way to build that structure with IdentityServer4 (maybe some extension?) or the only way would be to manually serialize the JSON since the Claim seems to accept only a string?

PS: I have seen this question and this other where one of the authors of Identity Server talks about something similar being an antipattern. Not sure if the antipattern would be to have complex claims' structure or "authorization implementation details" in the claims.

Any advice on this would be great!

UPDATE:

After giving some thoughts I agree having a complex hierarchy of claims is not desirable and I could go around this problem with a dirty solution of prefixing roles for each businessId. Something like this:

{
    "email": "test@test.com",
    "roles": [
        "1_admin",
        "1_accountant",
        "2_support"
     ],
     "businesses": [
        "1_One",
        "2_Two" 
     ]
}

that way I keep a simple structure and later on, at the client or API I can read the claims and find out that 1 is the id for the business with name One and it has the roles admin and account.

Would this be a better solution?

Community
  • 1
  • 1
diegosasw
  • 8,724
  • 7
  • 66
  • 106

1 Answers1

13

Claims are about identity information - and not complex permission "objects". You are far better off with a dedicated permission service that returns your permissions in any format you want based on the identity of the user.

I also hope your permission data doesn't change while the token is being used, otherwise you end up with stale data.

That said - claims are always strings in .NET - but you can serialize JSON objects into it by setting the ClaimValueType to IdentityServerConstants.ClaimValueTypes.Json.

leastprivilege
  • 17,248
  • 1
  • 29
  • 47
  • Thank you. If the claims (permission data) change I suppose there's some way to invalidate the token in the identity server when the API tries to validate it so that the API can inform the client (401) that it needs to request a new token with the claims updated? – diegosasw Sep 08 '16 at 10:18
  • Other option is to reissue a different token for the client if this wants to access some other business' resources. Using the tenant option could fit here? client has a token describing its user identity for business One with A,B roles. User swaps to business Two in UI and requests a new token by sending tenant=businessTwoId so that Identity Server sees that the user is still authenticated and issues the new token this time with info about the business Two and its roles. This simplifies JWT, not sure whether it's possible to issue different tokens for the same user and different tenant? – diegosasw Sep 08 '16 at 10:27
  • 3
    Just don't use tokens for permissions and you don't have to architect around the fact that they don't belong there. – leastprivilege Sep 08 '16 at 10:37
  • 1
    @leastprivilege do you have additional information on why we should't use JWT for authorization? – tuler Nov 30 '16 at 12:52
  • Use payload section of the token. Reference https://stackoverflow.com/questions/29715178/complex-json-web-token-array-in-webapi-with-owin/57197767#57197767 – Lovjith Jul 25 '19 at 08:45
  • @leastprivilege could you share how you get the permissions for a user, every request? i can see you say dont put them in the JWT, but there doesnt seem to be much info on how and where they should be. – Seabizkit Dec 03 '19 at 07:39