質問

I have .NET Core WebApi application with JWT token for authorization. I also have roles and permissions.

To make it more flexible for end user, I decided to make permissions like this:

[Authorize(Policy = "HasAccessToThisMethod")]
[Route("someMethod/{id}")]
[ProducesResponseType(typeof(int), 200)]
[HttpPost]
public async Task<IActionResult> SomeMethod(int id)

And store them in the tokens. With this approach, user can create whatever roles he/she wants and add permissions to them.

Recently, I had a problem with token size, it exceeded the default 16kb Windows/IIS limit. I increased it and called it a day, but after reading more about tokens I understood, that they usually are ~4kb.

Questions:

  • How bad is this approach?
  • Is it okay that token grows with permissions count?
  • Is replacing [Authorize] with custom middleware would be better?
    • It would check the user's permissions according to his uid/role/etc and not keeping all permissions in token.
    • If not, what solution is better?
役に立ちましたか?

解決 3

Thanks for suggestions. I ended up removing frontend related permissions from token, keeping only backend permissions, and it's working fine. Later I'll probably add friendly names and use abbreviations, as @Dom suggested.

他のヒント

It sounds like you have a lot of permissions, and maybe those permissions have very long names. One way of reducing the overall token size would be to severely abbreviate them, and add a static class of constants to make them humanly readable.

eg.

public static class Permissions
{
    public const string HasAccessToThisMethod = "HATTM";
}

and

[Authorize(Policy = Permissions.HasAccessToThisMethod)]

Of course this method won't work with infinite permission growth, or if the list of permissions is already ridiculously long, but it's a low effort, high impact change in the short term.

Is this approach with JWT tokens wrong?

I've seen various different approaches in use, and companies/developers seems to craft them based on needs and/or knowledge level.

I've implemented exactly this approach (of storing permissions in the token - not abbreviating them) in a previous role, and it's still working fine to this day. The big advantage of it is avoiding a round trip to the database for every single authorised request, which is always a plus but not always the most important thing, and should be sacrificed if API speed is not a number one priority and it is causing other issues.

You're effectively distributing state within the tokens which are typically handled by other means (like storing it in the backend). What you're doing can work, but there's a at least a few questions I might ask weighed against alternatives:

  • What is the cost of increasing the token size? This token is presumably sent each request increasing bandwidth and needs to be parsed and validated increasing server load. On systems with limiting resources (mobile, servers processing heavy requests, servers that have cost directly associated with cpu time) this could end up being a high priority to undo for optimization.

  • Who is signing these tokens, how often do you rotate signing keys, and what is the lifetime of the tokens, what is the refresh and revocation strategy? Allowing state which defines roles and permissions to be held by the user, you increase security risk if it's not properly signed or when your keys are compromised.

ライセンス: CC-BY-SA帰属
所属していません softwareengineering.stackexchange
scroll top