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

Issue #4128 - Add missing padding and use URL decoder #4129

Merged
merged 1 commit into from Oct 7, 2019

Conversation

travisspencer
Copy link
Contributor

@travisspencer travisspencer commented Sep 28, 2019

This fixes the issue (#4128) I raised about incorrect decoding of some ID token JWTs that have sections that need their padding added back.

@joakime
Copy link
Contributor

joakime commented Sep 28, 2019

Your commits do not satisfy the Eclipse Legal requirement for a signed ECA. (See details of commit checks)
We are unable to merge without a signed ECA.
See https://github.com/eclipse/jetty.project/blob/jetty-9.4.x/CONTRIBUTING.md#eclipse-contributor-agreement

@joakime joakime added this to the 9.4.x milestone Sep 30, 2019
@joakime joakime added this to In progress in Jetty 9.4.22 via automation Sep 30, 2019
@joakime joakime moved this from In progress to Review in progress in Jetty 9.4.22 Sep 30, 2019
@@ -175,6 +175,29 @@ and the Token Endpoint (which it is in this flow), the TLS server validation
return (Map)JSON.parse(jwtClaimString);
}

private static byte[] padJWTSection(String unpaddedEncodedJwtSection)
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think the case here with === is necessary.

This could be simplified using the example from
https://tools.ietf.org/html/rfc7515#appendix-C

Something like:

static byte[] b64DecodeWithoutPadding(String arg)
{
    String s = arg;
    switch (s.length() % 4) // Pad with trailing '='s
    {
        case 0: break; // No pad chars in this case
        case 2: s += "=="; break; // Two pad chars
        case 3: s += "="; break; // One pad char
        default: throw new IllegalArgumentException("Illegal base64url string!");
    }
    return Base64.getUrlDecoder().decode(s); // Standard base64 decoder
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ya, that is simpler. Will look into that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lachlan-roberts , @joakime et a. maybe you can help with this, but it seems the above code is licensed under BSD. See https://trustee.ietf.org/documents/IETF-TLP-5_001.html. So, is it OK to bring this in? Does something need to be done, like an attribution or something?

Copy link
Contributor

Choose a reason for hiding this comment

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

@travisspencer how about we write this in a different way with the same resulting logic.

remainder    action       (4-remainder)%4
-----------------------------------------
0            0 padding        0
1            error            -
2            2 padding        2
3            1 padding        1
private static byte[] padBase64(byte[] unpaddedBase64)
{
    int remainder = unpaddedBase64.length % 4;
    if (remainder == 1)
        throw new IllegalArgumentException("Not valid Base64");

    int paddingNeeded = (4 - remainder) % 4;
    byte[] paddedBase64 = Arrays.copyOf(unpaddedBase64, unpaddedBase64.length + paddingNeeded);
    Arrays.fill(paddedBase64, unpaddedBase64.length, paddedBase64.length, (byte)'=');

    return paddedBase64;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, good one @lachlan-roberts . That special case for a remainder of 1 took me a sec, but it's because a base64-endoded string will always be an even number. I see.

I think that an if statement like I have below is good to avoid the unnecessary array copy and I'd like to assign unpaddedBase64.length to a variable for readability. Will make those changes and update this PR.

Copy link
Contributor

@joakime joakime left a comment

Choose a reason for hiding this comment

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

Would like to see unit tests for the decoder portion, showing the various flavors of received data and to verify that decoder works as intended (and to prevent regression).

Signed-off-by: Travis Spencer <travis@curity.io>
Copy link
Contributor

@lachlan-roberts lachlan-roberts left a comment

Choose a reason for hiding this comment

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

I think the logic of padJWTSection looks good now.

I have written some tests as @joakime suggested and will put up a separate PR for them.

@travisspencer
Copy link
Contributor Author

Ah great, @lachlan-roberts , that you wrote some tests as well. I had that on my todo list, but hadn't gotten to it yet. I'll check out your PR, so I can learn the details of how that's done.

With those, I think this PR is done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Jetty 9.4.22
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

3 participants