Coder Social home page Coder Social logo

jwt's People

Contributors

azure-pipelines[bot] avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar lochgeo avatar mortalflesh avatar olivier-spinelli avatar ycrumeyrolle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jwt's Issues

What is the meaning of 'defaultAlgorithm'?

I'm having a hard time figuring out the "defaultAlgorithm" here:

TokenValidationPolicyBuilder RequireSignature(string issuer, Jwks keys, SignatureAlgorithm defaultAlgorithm)
Because the "alg" header parameter (https://tools.ietf.org/html/rfc7515#section-4.1.1):

This Header Parameter MUST be present and MUST be understood and processed by implementations.

... default here seems rather strange to me. Is it a way to REQUIRE a given algorithm? In this case, how does this fit with the multiple keys that could be associated to the "kid"?

(This defaultAlgorithm is not optional... just like the "alg" parameter.)

Sorry to ask but I'll appreciate some explanations about this... Thanks in advance.

Originally posted by @olivier-spinelli in #545 (comment)

This API is new in v2.0, still in beta, so there may be some remaining polish on the public API.
The excepted usage is:

            var policy = new TokenValidationPolicyBuilder()
                           .RequireSignature("https://idp.example.com/", key, SignatureAlgorithm.HS256)
                           .RequireAudience("636C69656E745F6964")
                           .Build();

By doing so, there is a link between the issuer, the key, and the signature algorithm. The issuer is used as a lookup for finding the required validation. This is the common usage of a JWS: You have an issuer, a key, and an associated signature algorithm.
So this is not a default algorithm.

It is also possible to do so (legacy usage):

            var policy = new TokenValidationPolicyBuilder()
                           .DefaultIssuer("https://idp.example.com/")
                           .RequireSignatureByDefault(key, SignatureAlgorithm.HS256)
                           .Build();

The default issuer is not used as lookup, but only as the last chance to validate an issuer, as-well as the signature key. This allow some use cases where there is no issuer.

Your question convinces me on 2 points:

  • A review of the name of the methods & parameters should be done. defaultAlgorithm is a perfect example of name without clear intention.
  • Some methods exposed for "legacy usage" are more disturbing than expected. Require***ByDefault, RequireAlgorithm. Marking this methods as obsolete might be an option.

Help to create JWT token from JWK

Hello.
How can I use your library to create an JWT token with Elliptic Curve JSON Web Key?

private const string privkey =
"{"kty":"EC","alg":"ES256","crv":"P-256"," + ""x":"lmzBhWRXSZTx5q6b80PK_GL7b94YYXI1hNB3YdJ6bzQ","y":"sXwmQX8sAm5yoybyq0RvMMhQp7Ox4lvhdpy_xPjfs58"," +""d":"P_MepPu0IPJEIQ_WUL5p12qb-phfMBdiDC8vHgdwvJ4"}";

None of the methods does not work:
1.
var privJwk = new ECJwk(256, "P_MepPu0IPJEIQ_WUL5p12qb-phfMBdiDC8vHgdwvJ4","lmzBhWRXSZTx5q6b80PK_GL7b94YYXI1hNB3YdJ6bzQ","sXwmQX8sAm5yoybyq0RvMMhQp7Ox4lvhdpy_xPjfs58");
2.
var privJwk = ECJwk.FromJson(privkey);

Probable bug in Jwk.FromX509Certificate

Shouldn't the boolean parameter for ExportParameters be true if withPrivateKey is true? I was trying a JWE validation with asymmetric key and it kept on failing with "Encryption Key Not found" error -which I think maybe due to this. In file src\JsonWebToken\Jwk.cs

           if (withPrivateKey)
            {
                using var rsa = certificate.GetRSAPrivateKey();
                if (!(rsa is null))
                {
                    var rsaParameters = rsa.ExportParameters(false);
                    key = new RsaJwk(rsaParameters);
                }
            }

Also, it might be better to add a assert in test\JsonWebToken.Tests\JsonWebKeyTests.cs to check for jwk.HasPrivateKey property if the input certificate has a private key.

        [Theory]
        [MemberData(nameof(GetCertificates))]
        public void CreateFromCertificate(X509Certificate2 certificate, bool hasPrivateKey, int keySize)
        {
            var jwk = Jwk.FromX509Certificate(certificate, hasPrivateKey);
            Assert.Equal(keySize, jwk.KeySizeInBits); 
            if(hasPrivateKey)
            {
                Assert.True(jwk.HasPrivateKey);
            }
        }

Manual refresh for JwksHttpKeyProvider

We're currently wrapping JwksHttpKeyProvider in a custom key provider factory in order to support the following requirement (supports automatic key rotation for our services):

When a key is missing from the JWKS, the validation service shall attempt to reload the JWKS from the /.well-known/jwks.json endpoint. This shall be attempted at a rate of no more than once per minute.

I propose adding the following to JwksHttpKeyProvider.cs:

namespace JsonWebToken
{
    /// <summary>Represents a <see cref="IKeyProvider"/> that retrieve the key set from an HTTP resource as JWKS.</summary>
    public sealed class JwksHttpKeyProvider : IKeyProvider, IDisposable
    {
...

        // Possible implementation
        public void Refresh()
        {
            _refreshLock.Wait();
            try
            {
                _syncAfter = EpochTime.UtcNow + RefreshInterval;
            }
            finally
            {
                _refreshLock.Release();
            }
        }
    }
}

This would allow us to setup refreshing the JWKS if a key is missing.

Since this is a 2.0 release, perhaps this could be rolled up to IKeyProvider?

How to Initialize AsymmetricJwk

Hi
I am working on .Net and interested to use JsonWebToken for Signing Purpose. i want to implement Using OAuth 2.0 for Server to Server Applications in google. The only signing algorithm supported by the Google OAuth 2.0 Authorization Server is RSA using SHA-256 hashing algorithm. I have the private key in my hand.i need to initialize AsymmetricJwk, i think. But the example only showing SymmetricJwk.Can you Please help me, how can i initialize AsymmetricJwk using Private Key.

Thanks

add custom claims with object value

i couldn't find a way to add custom claims to JwsDescriptor which accepts claim value as object, where it get automatically json serialized when jwt is written.

e.g.

descriptor.AddClaim("https://hasura.io/jwt/claims", new HasuraClaim
{
UserId = user.Id,
DefaultRole = "user",
Roles = new[] { "user" }
});

Signature validation fails when no signature algorithm is specified

I am attempting to validate an access token coming from Azure AD B2C, and the validation is failing even though jwt.io successfully validates the signature. This is version 1.9.0.

In SignatureValidationPolicy.cs, line 101, Jwk.CanUseForSignature() is called with "RS256" as signatureAlgorithm, and it returns true, because the SignatureAlgorithm property returns null. Then, on line 103, alg ends up null because both algorithm and key.SignatureAlgorithm are null. That means that the code never tries to validate the signature, and InvalidSignature is the result.

SymmetricJwk string key decoding fail

Hello,
I'm trying to create a SymmetricJwk with user password - so only him can verify the JWT again.

But I got an Exception.

System.FormatException: The input is not a valid Base-64 URL string as it contains a non-base 64 character.
   at JsonWebToken.ThrowHelper.ThrowOperationNotDoneException(OperationStatus status)
   at JsonWebToken.Base64Url.Decode(ReadOnlySpan`1 base64Url, Span`1 data)
   at JsonWebToken.Base64Url.Decode(ReadOnlySpan`1 base64Url)
   at JsonWebToken.Base64Url.Decode(String data)
   at JsonWebToken.SymmetricJwk..ctor(String k)

I found this https://stackoverflow.com/questions/44866847/convert-frombase64string-does-not-work-in-code-but-works-in-online-tool/44867049 so it explained me, why I got the error exactly.

But I think it might be a bug for creating a JWK, since when I create a token here https://jwt.io/#debugger-io with that password, it is created without any problem.

So I'm not sure, why there is _k = Base64Url.Decode(k); in the first place, could it be done by System.Text.Encoding.UTF8.GetBytes instead? I guess it would be more user friendly.

But maybe I see it all wrong (I'm kinda new to JWT world).

Inconsistency in casing of "iat" claim between descriptor and header ToString methods

This is just a tiny inconsistency I noticed in some testing. It probably wouldn't affect anyone unless they're abusing the ToString methods of JwsDescriptor and Jwt.

The following code:

var descriptor = new JwsDescriptor
{
    Algorithm = SignatureAlgorithm.None,
    IssuedAt = DateTime.UtcNow,
    ExpirationTime = DateTime.UtcNow.AddHours(1),
    Issuer = "https://idp.example.com/",
    Audience = "636C69656E745F6964"
};

Console.WriteLine("Descriptor ToString():");
Console.WriteLine(descriptor.ToString());
Console.WriteLine();

var tokenBytes = new JwtWriter().WriteToken(descriptor);

Console.WriteLine("Jwt ToString():");
Console.WriteLine(new JwtReader().TryReadToken(tokenBytes, TokenValidationPolicy.NoValidation).Token?.ToString());

Produces the following output:

Descriptor ToString():
{
  "alg": "none"
}
.
{
  "iat": 1588358068,
  "exp": 1588361668,
  "iss": "https://idp.example.com/",
  "aud": "636C69656E745F6964"
}

Jwt ToString():
{
  "alg": "none"
}.{
  "aud": "636C69656E745F6964",
  "iss": "https://idp.example.com/",
  "exp": 1588361668,
  "Iat": 1588358068
}

Note that the descriptor ToString output correctly has the "iat" claim in lowercase but the Jwt ToString output has it with a capital "I" ("Iat").

This line seems to be the source of the problem.

Encrypted key present in ECDH-ES algorithm results in Invalid JWE

Hello, should there be a encrypted key present when using this algorithm ?

According to my readings, this algorithm uses Direct Key Agreement, and when using this it seems that the JWE Encrypted key value should have been empty ? https://datatracker.ietf.org/doc/html/rfc7516#section-5.2 (10)

It's turning out to be a invalid JWE, since in the CEK part we are getting ".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA." instead of the empty octet ?

Example:

string json = "{\r\n        \"alg\": \"ES256\",\r\n        \"crv\": \"P-256\",\r\n        \"kty\": \"EC\",\r\n        \"use\": \"sig\",\r\n        \"x\": \"OKs1T_4N9Z78RQ87olZ98PW__ROFWL5fw1671XB20zw\",\r\n        \"y\": \"8y5YBG5RY4gK2bObN4Aj5eNmXBoLMrCHKEMwykPSTIg\"\r\n      }";
string payload = "teste";

var descriptor = new PlaintextJweDescriptor(payload)
{
    EncryptionKey = Jwk.FromJson(json),
    EncryptionAlgorithm = EncryptionAlgorithm.Aes256Gcm,
    Algorithm = KeyManagementAlgorithm.EcdhEs
};

var writer = new JwtWriter();
string jwe = writer.WriteTokenString(descriptor);

Console.WriteLine(jwe);

eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiRUNESC1FUyIsImVwayI6eyJjcnYiOiJQLTI1NiIsIngiOiJNQnpzbF9VM2ZFemxLMzVvbWh4TjlOd05yRm11ZXlRRGR2WUVxd2hENWtnIiwieSI6Ilc1TnJvZGxvQXdTbHptUjZ3cVAwZjVxRHBEQ2NqM0Y0YXEteUNwS1p5a3cifX0.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.2JvH70MzlecMiZtG.Fy85KTI.dHuw2Cw7_im2TAP_YpKrfQ

Thanks in advance @ycrumeyrolle

JWE generation using A128CBC_HS256 produces the wrong length authentication tag

RFC 7518 JSON Web Algothrims specify that the authentication tag should be truncated to the first 16 octets.

The AES_CBC_HMAC_SHA2 parameters specific to AES_128_CBC_HMAC_SHA_256 are:
The input key K is 32 octets long.
ENC_KEY_LEN is 16 octets.
MAC_KEY_LEN is 16 octets.
The SHA-256 hash algorithm is used for the HMAC.
The HMAC-SHA-256 output is truncated to T_LEN=16 octets, by
stripping off the final 16 octets.

However when JWE tokens are generated the full 32 octets generated by HMAC SHA256 are being appended. This is generating invalid tokens.

Hash-Algorithm for key derivation (ECDH-ES)

Hey,
i tried your library and the one from Microsoft (Microsoft.IdentityModel.JsonWebTokens) and the interoperability between both.
https://datatracker.ietf.org/doc/html/rfc7518#section-4.6.2 seems to state that the Hash should be calculated with SHA256

In Microsoft code it looks like this:

// JWA's spec https://datatracker.ietf.org/doc/html/rfc7518#section-4.6.2 specifies SHA256, saml might be different
byte[] derivedKey = _ecdhPrivate.DeriveKeyFromHash(_ecdhPublic.PublicKey, HashAlgorithmName.SHA256, prepend, append);

In your code the hash algorithm is defined through it's encryption algorithm:

_hashAlgorithm = GetHashAlgorithm(encryptionAlgorithm);
...
 var hashAlgorithm = encryptionAlgorithm.SignatureAlgorithm.HashAlgorithm
...
exchangeHash = new ReadOnlySpan<byte>(ephemeralKey.DeriveKeyFromHash(otherPartyKey.PublicKey, _hashAlgorithm, _secretPreprend, secretAppend), 0, _keySizeInBytes);>

If you now use a combination of EcdhEsA128kw and Aes128CbcHmacSha256 it works because here SHA256 is used.
But if you use a combination of EcdhEsA256kw and Aes256CbcHmacSha512 the tokens from the MS-Lib and the tokens of your lib cannot be understood by the other party, because you would use SHA512 in that case.

Who is right - who is wrong? I dont have clue but hope you have an answer to this because i would like to connect two applications using different frameworks ;-)

ECJwk GetCanonicalizeSize wrong - Kid randomly wrong

Hello,
in EC JWK the size is calculated by:

	protected internal override int GetCanonicalizeSize()
	{
		return 35 + Base64Url.GetArraySizeRequiredToEncode(Crv.Name.EncodedUtf8Bytes.Length) + Base64Url.GetArraySizeRequiredToEncode(X.Length) + Base64Url.GetArraySizeRequiredToEncode(Y.Length);
	}

but it should be

	protected internal override int GetCanonicalizeSize()
	{
		return 35 + Crv.Name.EncodedUtf8Bytes.Length + Base64Url.GetArraySizeRequiredToEncode(X.Length) + Base64Url.GetArraySizeRequiredToEncode(Y.Length);
	}

because Crv.Name.EncodedUtf8Bytes is copied in Canonicalize:

	protected internal override void Canonicalize(Span<byte> buffer)
	{
		int length = StartCanonicalizeValue.Length;
		StartCanonicalizeValue.CopyTo(buffer);
		EllipticalCurve ellipticalCurve = Crv;
		ellipticalCurve.Name.EncodedUtf8Bytes.CopyTo(buffer.Slice(length));
		int num = length;
		ellipticalCurve = Crv;
		length = num + ellipticalCurve.Name.EncodedUtf8Bytes.Length;
		Middle1CanonicalizeValue.CopyTo(buffer.Slice(length));
		length += Middle1CanonicalizeValue.Length;
		length += Base64Url.Encode(X, buffer.Slice(length));
		Middle2CanonicalizeValue.CopyTo(buffer.Slice(length));
		length += Middle2CanonicalizeValue.Length;
		length += Base64Url.Encode(Y, buffer.Slice(length));
		EndCanonicalizeValue.CopyTo(buffer.Slice(length));
	}

This is a problem because ComputeThumbprint uses this Value for the call to ComputeHash:

Sha256.Shared.ComputeHash(buffer.Slice(0, canonicalizeSize), span);

The buffer is either from ArrayPool or from Stackalloc - ArrayPool does not garantuee to null the array. So you get random Kids when the last bytes differ because they dont get initialized.

I think the Renting is also wrong - you use Stackalloc if canonicalSize is bigger than 256 - i think the condition should be reversed - using stack alloc for smaller arrays right?

I didnt check for RSA and the others, potentially they share some of those bugs.

I can do PRs if you like. Right now our project is running on your "2.0.0-beta.4" i would like to have a stable version :-)

If you dont do maintenance on this project i would be ready to fork this - your library is awesome and much better than the crap Microsoft implemented for their authorization. Want to see it fly :-)

Read SignatureAlgorithm from X509Certificate if available

We're using X509 certs to sign and verify JWTs, and we have come across an issue where we have to explicitly state the signature algorithm in our policy because Jwk.Alg is null.

I believe this could instead be read from the X509 cert and added to the JWK in FromX509Certificate:

X509Certificate2Collection collection = store.Certificates
                                             .Find(
                                                 X509FindType.FindByThumbprint,
                                                 thumbprint ?? throw new ArgumentNullException(nameof(thumbprint)));
if (collection.Count == 0)
{
    // ...
}

try
{
    Jwk jwk = Jwk.FromX509Certificate(collection[0], withPrivateKey);
    // jwk.Alg == null
    // collection[0].SignatureAlgorithm.FriendlyName == "sha256RSA"
    return jwk;
}
catch (Exception ex)
{
     // ...
}

Basically supporting RFC 3279 and family (https://tools.ietf.org/html/rfc3279#section-2.2).

Token fails validation with status = NotYetValid

I have a token that was retrieved from Auth0, and issued a few minutes ago. When I validate the token with .EnableLifetimeValidation(), the validation fails, with Status being NotYetValid. The code that does the validation is as follows:

var policy = new TokenValidationPolicyBuilder()
	.RequireAudience("https://tv-dev-test/")
	.RequireSignature(m_keys)
	.RequireIssuer(m_domain)
	.EnableLifetimeValidation()
	.Build();

var reader = new JwtReader();
var header = AuthenticationHeaderValue.Parse(req.Headers[HeaderNames.Authorization]);
var result = reader.TryReadToken(header.Parameter, policy);

Console.WriteLine(result.Succedeed);
Console.WriteLine(result.Status);
Console.WriteLine(result.Exception?.ToString());
Console.WriteLine($"now is {DateTime.UtcNow} {DateTime.UtcNow.Kind}");
Console.WriteLine($"not before {result.Token.NotBefore} {result.Token.NotBefore?.Kind}");
Console.WriteLine($"issued at {result.Token.IssuedAt} {result.Token.IssuedAt?.Kind}");
Console.WriteLine($"expiration time {result.Token.ExpirationTime} {result.Token.ExpirationTime?.Kind}");

The output of this validation is as follows:

False
NotYetValid

now is 9/17/2020 9:49:05 PM Utc
not before
issued at 9/17/2020 9:09:54 PM Utc
expiration time 9/18/2020 9:09:54 PM Utc

The current time is definitely between the "issued at" and the "expires at" times, but the validation still fails. Is there something I am doing wrong?

JWE with arbitrary bytes/string as payload

Hi Yann,

The RFC 7516, while describing the plaintext does not specify that the content needs to be a valid JWS. I am trying to create a JWE using a string as my content, but I get the error that type (string) is not a valid JwsDescriptor. Below is the code that I am using

       var keyEncryptionKey = Jwk.FromX509Certificate(new X509Certificate2(), false);

        // Creates a JWE descriptor with all its properties
        var descriptor = new JweDescriptor<string>()
        {
            EncryptionKey = keyEncryptionKey,
            EncryptionAlgorithm = EncryptionAlgorithm.Aes256Gcm,
            Algorithm = KeyManagementAlgorithm.RsaOaep,
            Payload = "data"
        };

        // Generates the UTF-8 string representation of the JWT
        var writer = new JwtWriter();
        var token = writer.WriteTokenString(descriptor);

Is it possible to produce a such a JWE using the library? Could you help me with a code sample, if its possible?

Operation is not supported on this platform.

When the code hits JwtWriter.WriteTokenString() on a Windows Server 2012 R2, I get the following error but no other information.

Operation is not supported on this platform.

Stack trace doesn't seam to be much help,

The code is running fine on a number of other servers, all server have the "Microsoft .NET Core 5.00 Windows Server Hosting" installed all other functions appear to working fine.

Other Windows server including a 2012 R2 , 2016 and 2019 appear to be fine, any ideas how to narrow this problem down?

Some Errors on Validation BinaryPayloadJwt

`static void Main()
{
var signatureKey = SymmetricJwk.FromBase64Url("R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU");
var encryptionKey = new SymmetricJwk("R9MyWaEoyiMYViVWo8Fk4T");
var payload = new byte[] { 76, 105, 102, 101, 32, 108, 111, 110, 103, 32, 97, 110, 100, 32, 112, 114, 111, 115, 112, 101, 114, 46 };
var descriptor = new BinaryJweDescriptor(payload)
{
EncryptionKey = encryptionKey,
EncryptionAlgorithm = EncryptionAlgorithm.Aes128CbcHmacSha256,
Algorithm = KeyManagementAlgorithm.Aes128KW
};

        var writer = new JwtWriter();
        var token = writer.WriteTokenString(descriptor);

        Console.WriteLine("The JWT is:");
        Console.WriteLine(descriptor);
        Console.WriteLine("payload:"+Encoding.UTF8.GetString(payload));
        Console.WriteLine("Its compact form is:");
        Console.WriteLine(token);
                    
        var policy = new TokenValidationPolicyBuilder()
                       .RequireSignature(signatureKey, SignatureAlgorithm.HmacSha256)
                       .RequireAudience("636C69656E745F6964")//this is not exist in payload,why result still succed?
                       .RequireIssuer("https://idp.example.com/")//this is not exist in payload,why result still succed?
                       .Build();

        var reader = new JwtReader(encryptionKey);
        var result = reader.TryReadToken(token, policy);
        if (result.Succedeed)
        {
            Console.WriteLine("Decypt token is " + result.Token.Payload.ToString());//payload should be a byteArray,why here is null?
        }
        else
        {
            Console.WriteLine("Failed to read the token. Reason: " + Environment.NewLine + result.Status);
        }
    }`

some not reasonable.
If throw a byteArray or string Payload, that will be good.

Better support multiple issuers

It may be common to have a lots of issuers for secevent.
The current way to resolve this is to try to validate against each issuer policy.

A better way to achieve this is to lookup the issuer policy based on the 'iss' claim.
This require to review the TokenValidationPolicy usage.

Fix warning on CI build

##[warning]/opt/hostedtoolcache/dotnet/sdk/3.0.100/Roslyn/Microsoft.CSharp.Core.targets(59,5): Warning MSB3052: The parameter to the compiler is invalid, '/define:$(BUILDCONFIGURATION)' will be ignored.

Re-evaluate usage of Utf8JsonReader.ValueSpan for property name equality via SequenceEqual of raw bytes

https://github.com/ycrumeyrolle/Jwt/blob/59bace31afecca486d80cfb87f40db5fdbec4cd8/src/OpenIdConnect/Address.cs#L39-L45
This type of comparison of the raw bytes (using ValueSpan) will not always work and miss property names that are "equal" but contain escaped characters.

Is this expected/fine? If not, consider using ValueTextEqual APIs t do the property name comparisons. Generally speaking, getting the raw bytes via ValueSpan and then using SequenceEqual probably isn't what you want to do unless you control the input or only want to support the exact bytes.

https://github.com/dotnet/corefx/blob/d3911035f2ba3eb5c44310342cc1d654e42aa316/src/System.Text.Json/ref/System.Text.Json.cs#L316-L318
https://docs.microsoft.com/en-us/dotnet/api/system.text.json.utf8jsonreader.valuetextequals?view=netcore-3.0#System_Text_Json_Utf8JsonReader_ValueTextEquals_System_ReadOnlySpan_System_Byte__

For instance:
If the json payload contained formatted this comparison will work fine, but it wouldn't work for \\u0066ormatted (f == \u0066).
Something to consider.

I would double check usage of reader.ValueSpan property in other instances as well (where the comparison is being deferred (when saved in JwtProperty, etc.).
https://github.com/ycrumeyrolle/Jwt/search?utf8=%E2%9C%93&q=ValueSpan&type=
Like: https://github.com/ycrumeyrolle/Jwt/blob/90431793b0419333d1f47467192b3361f6c76e39/src/JsonWebToken/JwtObject.cs#L188

Also, is the JSON input here trusted or known to be valid UTF-8?

cc @ycrumeyrolle

Writer freezes while writing a token

Hello,

I'm trying to generate a token, but it freezes at writing... am I doing something wrong?

I'm using F# with .netcore 3.1 on Mac OS (10.15.4).

printfn "JWT.create ..."
use key = new SymmetricJwk("R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU", SignatureAlgorithm.HmacSha256)
printfn " -> key ok"

let descriptor =
    JwsDescriptor(
        KeyId = key.ToString(),
        JwtId = Guid.NewGuid().ToString(),
        IssuedAt = (DateTime.UtcNow |> Nullable),
        ExpirationTime = (DateTime.UtcNow.AddMinutes(30.0) |> Nullable),
        Issuer = (currentApp |> SoftwareComponent.value),
        Audience = (currentApp |> SoftwareComponent.value)
    )
    |> tee (fun d -> d.ToString() |> printfn " -> descriptor ok \n %A")

printfn " -> writer"
let writer = JwtWriter()
printfn " -> writing token ..."
let token = writer.WriteTokenString(descriptor)
printfn " -> Token:\n%A" token

Output is:

JWT.create ...
 -> key ok
 -> descriptor ok 
 "{
  "kid": "{\n  \u0022kty\u0022: \u0022oct\u0022,\n  \u0022alg\u0022: \u0022HS256\u0022,\n  \u0022k\u0022: \u0022R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU\u0022\n}"
}
.
{
  "jti": "2e9996df-b8ca-4e7a-a369-8ae1b8d843ff",
  "iat": 1588085668,
  "exp": 1588087468,
  "iss": "sc-eligibilityConfigurator-common-local@dev1-services",
  "aud": "sc-eligibilityConfigurator-common-local@dev1-services"
}"
 -> writer
 -> writing token ...

Adds a CLI

  • Generates JWK
  • Encrypt JWK
  • Decrypt JWK
  • Convert PEM & X509 to JWK
  • Check the validity of a JWK

JWE decryption using A128CBC_HS256 fails to decrypt valid tokens

JWE tokens generated using A128CBC_HS256 by other libraries fail to be decrypted correctly as the authentication fails. This seems to be due wrong length authentication tag being checked. It should only check the first 128 bits.

If you try to decrypt the example token given in RFC7516 the decryption fails.

RFC7518 specifies only the first 128 bits to be used in the tag

Example

using System;
using JsonWebToken;			

public class Program
{
	public static void Main()
	{
		// Key and token from https://www.rfc-editor.org/rfc/rfc7516.html#appendix-A.3
		
		Jwk encryptionKey = new SymmetricJwk("GawgguFyGrWKav7AX4VKUg");
		string token = "eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.U0m_YmjN04DJvceFICbCVQ";
		
		JwtReader jwtReader = new JwtReader(encryptionKey);
		var policy = new TokenValidationPolicyBuilder().AcceptUnsecureToken().Build();
		
		var result = jwtReader.TryReadToken(token, policy);
		Console.WriteLine($"Decryption Statue: {result.Status}");
		
		// The token should be decrypted and equal "Live long and prosper." However it fails decryption
	}
}

https://dotnetfiddle.net/YdEJXG

Add a claim with JWTArray

Hello again,
I really tried to figure out this myself, but I couldn't.

I need to add a custom claim to payload:

{
  ...,
  "groups": [
     "first",
     "second",
     "third"
  ]
}

but so far I can only add it to look like this:

{
  ...,
  "groups": {
    "groups": [
      "first",
      "second",
      "third"
    ]
  }
}

This code leads to a "double nested" groups:

let array =
    ["first"; "second"; "third"]
    |> List.map (fun v -> JwtValue(v))
    |> System.Linq.Enumerable.ToList // convert to Collection.Generic.List
    |> JwtArray

let property = JwtProperty("groups", array)
descriptor.AddClaim("groups", property)

I'd like to just add an array as claim

descriptor.AddClaim("groups", array)

but there is no such option.

I can create a JwtObject and add an array there, but it also needs a key and it has List<JwtProperty> _properties inside. JwtProperty AFAIK needs to have both name and value.


But if I create a token elsewhere, I can read value exactly the way I want to:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0MTg1YzQ0NC03OWNkLTRmNmUtODYwOC01N2E0NTI1YWFjNWYiLCJleHAiOjE2MTg3NDkyOTYsImlhdCI6MTU4NzY0NTI5NiwiaXNzIjoic2MtZWxpZ2liaWxpdHlDb25maWd1cmF0b3IiLCJncm91cHMiOlsiZmlyc3QiLCJzZWNvbmQiLCJ0aGlyZCJdfQ.gKXcjZkXLOI8MlImxiTRC4TuYa6UBvqw_Gb2ltJdZ4c
match result.Token.Payload.TryGetValue("groups") with
| true, groups -> printfn "groups <%A>:\n%A" (groups.Value.GetType()) groups.Value
| _ -> ()

Output:

groups <JsonWebToken.JwtArray>:
seq [JsonWebToken.JwtValue; JsonWebToken.JwtValue; JsonWebToken.JwtValue]

I even tried to fork it and "fix" it myself to the PR, but I don't know how to create a nameless property or claim.

JwsDescriptor.Payload setter weird behavior.

This unit test fails:

        [Fact]
        public void DescriptorPayloadIsAStandardReferenceObject()
        {
            var descriptor = new JwsDescriptor(Jwk.None, SignatureAlgorithm.None);

            var p1 = new JwtPayload { { "One", "Member" } };
            var p1Content = p1.ToString();
            descriptor.Payload = p1;

            var p2 = new JwtPayload { { "Something", "else" } };
            var p2Content = p2.ToString();            
            descriptor.Payload = p2;

            Assert.Equal(p1.ToString(),p1Content);
            Assert.Equal(p2.ToString(),p2Content);
        }

With this:

    Assert.Equal() Failure
                                     ↓ (pos 24)
    Expected: ··· "Something": "else",\r\n  "One": "Member"\r\n}
    Actual:   ··· "Something": "else"\r\n}
                                     ↑ (pos 24)

This is a rather surprising side effect. Considering the implementation (see below _payload.CopyTo(value);), I'm wondering if this is intentional or not...

public override JwtPayload? Payload
{
    get => _payload;
    set
    {
        if (value is null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
        }

        _payload.CopyTo(value);
        _payload = value;
    }
}

If its not, I can make a PR to fix this (including the above test).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.