Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added methods in JsonWebTokenHandler that allow custom JWT header claims to be added #1223

Merged
merged 1 commit into from
Sep 6, 2019

Conversation

mafurman
Copy link
Member

@mafurman mafurman commented Jul 18, 2019

Fixes #1210 and #1237.

/// <summary>
/// Encrypts a JWS.
/// </summary>
/// <param name="innerJwt">A 'JSON Web Token' (JWT) in JWS Compact Serialization Format.</param>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we modify this parameter name and comment, we don't really know or verify that the string is a JWS in Compact Serialization Format.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the parameter name and comment should be changed, or perhaps maybe we should verify that the string is in JWS format?

In the RFC the value to be encrypted is referred to as 'plaintext', so we could call it that.

However, if something other than a JWS is passed into this method, the result produced by this method will no longer be something our library can verify. I feel like this may cause confusion.

The name of the method also happens to be 'EncryptToken', which may also get confusing.

/// will result in an exception being thrown.
/// <remarks> These claims are only added to the outer header (in case of a JWE).</remarks>
/// </summary>
public IDictionary<string, object> AdditionalHeaderClaims { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property is only for JWT's. What will SAML handlers do with this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking this would be a property that's only used when creating JWT tokens. I could make the comment clearer with regards to this if you think that'll help.

On a related note, IDictionary<string, object> Claims is currently not being used by the SAML handlers either.

Copy link
Member

@brentschmaltz brentschmaltz Aug 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this captures the issue for SAML and the dictionary: #1155

@mafurman mafurman force-pushed the mafurman/customJwtHeader branch from 6e43d3c to 0f506ac Compare July 23, 2019 20:28
@leastprivilege
Copy link
Contributor

I haven't looked at the API yet - but per our recent discussion, please make sure it is easily possible to set the typ header value.

@mafurman mafurman force-pushed the mafurman/customJwtHeader branch from 9696e13 to ef50621 Compare August 7, 2019 00:33
{
var header = new JObject();

if (!string.IsNullOrEmpty(encryptingCredentials.Alg))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alg, Enc can not be null.

private set => _alg = string.IsNullOrEmpty(value) ? throw LogHelper.LogArgumentNullException("alg") : value;

private set => _enc = string.IsNullOrEmpty(value) ? throw LogHelper.LogArgumentNullException("enc") : value;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Fixed.

var header = new JObject
{
{ JwtHeaderParameterNames.Alg, signingCredentials.Algorithm },
{ JwtHeaderParameterNames.Kid, signingCredentials.Key.KeyId },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KeyId can be null.

Copy link
Member Author

@mafurman mafurman Aug 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Also added in a test for this.

@@ -199,7 +269,7 @@ public virtual string CreateToken(SecurityTokenDescriptor tokenDescriptor)
if (!payload.Any())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1237 was opened as an empty payload should be allowed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Also added in some tests.

/// <exception cref="ArgumentNullException">if <paramref name="compressionAlgorithm"/> is null.</exception>
/// <exception cref="ArgumentNullException">if <paramref name="additionalHeaderClaims"/> is null.</exception>
/// <returns>A JWE in compact serialization format.</returns>
public virtual string CreateToken(string payload, SigningCredentials signingCredentials, EncryptingCredentials encryptingCredentials, string compressionAlgorithm, IDictionary<string, object> additionalHeaderClaims)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to add a comment to capture the SecurityTokenException thrown if any default header claims are found.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! I fixed this in all the relevant methods.

/// <exception cref="ArgumentNullException">if <paramref name="signingCredentials"/> is null.</exception>
/// <exception cref="ArgumentNullException">if <paramref name="additionalHeaderClaims"/> is null.</exception>
/// <returns>A JWS in Compact Serialization Format.</returns>
public virtual string CreateToken(string payload, SigningCredentials signingCredentials, IDictionary<string, object> additionalHeaderClaims)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to add a comment to capture the SecurityTokenException thrown if any default header claims are found.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

var rawHeader = Base64UrlEncodedUnsignedJWSHeader;
if (signingCredentials != null && !JsonWebTokenManager.KeyToHeaderCache.TryGetValue(JsonWebTokenManager.GetHeaderCacheKey(signingCredentials), out rawHeader))
// If there's no additional header claims to be added to the header and the token will be signed, try to retrieve a header value from the cache.
if (additionalHeaderClaims == null && signingCredentials != null && !JsonWebTokenManager.KeyToHeaderCache.TryGetValue(JsonWebTokenManager.GetHeaderCacheKey(signingCredentials), out rawHeader))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) could add additionalHeaderClaims.Count > 0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that we should check for this before seeing if 'additionalHeaderClaims' intersects _defaultHeaderParameters? Or that we should check for this so that we still use the header cache if 'additionalHeaderClaims' is empty?

I added in a check in both places.

@mafurman mafurman force-pushed the mafurman/customJwtHeader branch 2 times, most recently from 1e3a6da to e5f426e Compare August 23, 2019 19:12
@mafurman mafurman force-pushed the mafurman/customJwtHeader branch from e5f426e to 5a2deab Compare August 27, 2019 00:03
@mafurman mafurman force-pushed the mafurman/customJwtHeader branch from 5a2deab to 9df81a5 Compare September 5, 2019 21:33
@mafurman mafurman force-pushed the mafurman/customJwtHeader branch from 9df81a5 to f9746b6 Compare September 6, 2019 01:23
@mafurman mafurman merged commit be4e090 into dev Sep 6, 2019
@steveoshima
Copy link

FYI, this currently isnt working with RSA-PSS support.

@GeoK
Copy link
Member

GeoK commented Oct 7, 2019

Hi @steveoshima - It's not clear what exactly is not working. Can you provide more information or/and a small repro project?

@GeoK
Copy link
Member

GeoK commented Oct 15, 2019

@steveoshima - Are you still hitting the issue when using RSA-PSS?
We are planning on releasing 5.6.0 soon and we would appreciate your input.

@steveoshima
Copy link

steveoshima commented Oct 16, 2019

@steveoshima - Are you still hitting the issue when using RSA-PSS?
We are planning on releasing 5.6.0 soon and we would appreciate your input.

I attempted to check different branches to get RSA-PSS with custom headers working last week. However, no branches worked that i tried. I spotted the cusom header test with RSA-PSS was incomplete. I messaged about this on the issue. See my comment here - #1210

You will see the test is missing additonal header setup data, if this is added im sure the error will occur. -

@mafurman mafurman deleted the mafurman/customJwtHeader branch September 28, 2021 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow creation of a customized header using JsonWebTokenHandler
5 participants