jwt-dotnet / jwt

Jwt.Net, a JWT (JSON Web Token) implementation for .NET
Other
2.14k stars 462 forks source link

Newtonsoft dependency and Blazor Client apps #204

Closed dazinator closed 5 years ago

dazinator commented 5 years ago

I'd love to use this library in a Blazor Client application. Microsoft have recently switched away from being relient on Newtonsoft as a dependency, and instead use System.Text.Json by default (developers can still opt-in to using newtonsoft if they wish). This is a bit more lightweight and works well in Blazor client applications as well as on the server side. Newtonsoft was never designed to be lightweight for browser side use.

However one gap in blazor client side apps is that there is no lightweight mechanism for decoding a JWT into a claims principal. See my issue here: https://github.com/aspnet/AspNetCore/issues/11417

So I found your library. The problem is, it pulls in newtonsoft.json by default (I know you can use a custom serialiser implementation, but the damage has already been done as the newtonsoft dependency is still pulled into the app increasing it's size).

Would you consider splitting jwt into jwt and jwt.newtonsoft packages so the newtonsoft serialiser package was optionally adopted? That way I could use jwt without the newtonsoft dependency, and then implement a serialiser based on System.Text.Json?

dazinator commented 5 years ago

I'm also wondering if this library would make a good fit lgihtweight client side usage, and by lightweight I mean the only features that will be required are:

  1. Decode a JWT token to read its claims etc.
  2. No need for anything to do with verification - as JWT's are validated on the server, and secrets are kept there not client side.
abatishchev commented 5 years ago

Actually I don't mind and was also thinking about the split, see #76. However the idea was abandoned due to the lack of either support or demand.

The library can do all three: encode, decode, validate. Those are core and essential functions. I would not split them further.

dazinator commented 5 years ago

Understood. I think the dependency on System.Security.Cryptography.Csp from a client side perspective where all you need is to decode the token into a structure to read its claims is possibly non optimal, but I understand why you wouldn't want to split this out further. I'll do some research to see what a lightweight decode mechanism into a ClaimsPrincipal would look like, it's probable I'll have to roll my own!

abatishchev commented 5 years ago

Other than Json.Net it has no other dependencies and fits NetStandard 1.3 so I find it lightweight enough to be used on the client side.

abatishchev commented 5 years ago

The split should be a trivial job. I'm happy to participate, do code reviews, fix/adjust CI/CD if would be necessary.

dazinator commented 5 years ago

Thanks. I have just experimented a little bit within my blazor client app, and to get readonly access the things I need is pretty trivial, without any external dependency:

var jwt = "header.payload.sig" // replace this with your jwt.

string[] jwtEncodedSegments = jwt.Split('.');
var payloadSegment = jwtEncodedSegments[1];

var decodePayload = System.Convert.FromBase64String(payloadSegment);
var decodedUtf8Payload = Encoding.UTF8.GetString(decodePayload);

var result = System.Text.Json.Serialization.JsonSerializer.Parse<Dictionary<string, JsonElement>>(decodedUtf8Payload);

For a few lines of code, there is no dependency on any external serialiser, or cryptography package.. this is probably going to be the easiest solution from my perspective however.. what is't great about this:

  1. I am deserialising into a Dictionary<string, JsonElement> and JsonElement is coupled to the serialiser System.Text.Json - so this implementation is coupled to that serialiser. If i wish to switch serialisers later on, i'll have to revisit this method implementation.

  2. It's just a dictionary of essentially objects. So no convenience properties for common JWT properties such as iat etc.

  3. Related to above, I ultimately want to turn the payload into a Claim[] - I'll have to add a bunch of logic that loops through the dictionary and builds a list of Claim's.

So for my use case, if jwt offered value gains in those 3 areas, but without forcing dependenices on newtonsoft, or cryptography libraries, then I think it would be a good fit for blazor client applications that use JWT authentication.. What do you think? Perhaps I should keep a separate implementation and not try to adapt jwt for this case?

abatishchev commented 5 years ago

If it's that simple and works well for you then maybe it's not worth troubles. Again, I welcome the split across the JSON library but don't think it's a good idea to split across the encoder/decoder.

Re JsonElement: you may want to try to serialize to object first and the to JsonElement down the road, on the next step/layer.

dazinator commented 5 years ago

Ok thanks. I'll stick with what I've got then for now I think :-)