admin管理员组

文章数量:1313384

UPDATED I'm trying to verify a JWT access token programmatically using the x5c / x509 public key value below. I can get this working by plugging the token and x5c values into external web sites but not programmatically using JavaScript / jsrsasign. Any suggestions would be greatly appreciated.

Here is the the OIDC provider's public JSON Web Key Set.

    {
        "keys": [
            {
                "kty": "RSA",
                "kid": "server",
                "use": "sig",
                "alg": "RS256",
                "n": "gLZO9w1OT_SWO-KbqiU0k3HevHggiY70XbDqgE1YaqhD-MwFUWNudExzF3oB28NYWYg5v6CJY0F-pUNtgukDM6ARDlh0n4xIvBRlnUnCTCx7pYOjpfXbTv49tlXmh4-ddh8EeQBLrF92u5UYs0tnZd8843mvYWohUNH1X1hM08-hpk7xCiy4XdwbeSlH757D2d5E0J0dGtZ744-dB2ZRCw2Vms_mk4Yyny4ifx2j2gIhikbb7WGmsTR2sWrtuhgZ_EBNUvrD0O54xbhQNTTFQ1pi9UZxo_gYc5Gp5fLcSOK6SDBKXbDS5hhy1vFyoa0xdgFv-xpem7YzmkKqzfjC9w",
                "e": "AQAB",
                "x5c": [
                    "MIIDMDCCAhigAwIBAgIEFIopYzANBgkqhkiG9w0BAQsFADBaMQkwBwYDVQQGEwAxCTAHBgNVBAgTADEJMAcGA1UEBxMAMQkwBwYDVQQKEwAxCTAHBgNVBAsTADEhMB8GA1UEAxMYZmNpc2Rldi5pY2UuaWJtY2xvdWQuY29tMB4XDTE4MTAwMTE4MTYyOFoXDTI4MDkyODE4MTYyOFowWjEJMAcGA1UEBhMAMQkwBwYDVQQIEwAxCTAHBgNVBAcTADEJMAcGA1UEChMAMQkwBwYDVQQLEwAxITAfBgNVBAMTGGZjaXNkZXYuaWNlLmlibWNsb3VkLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIC2TvcNTk/0ljvim6olNJNx3rx4IImO9F2w6oBNWGqoQ/jMBVFjbnRMcxd6AdvDWFmIOb+giWNBfqVDbYLpAzOgEQ5YdJ+MSLwUZZ1Jwkwse6WDo6X1207+PbZV5oePnXYfBHkAS6xfdruVGLNLZ2XfPON5r2FqIVDR9V9YTNPPoaZO8QosuF3cG3kpR++ew9neRNCdHRrWe+OPnQdmUQsNlZrP5pOGMp8uIn8do9oCIYpG2+1hprE0drFq7boYGfxATVL6w9DueMW4UDU0xUNaYvVGcaP4GHORqeXy3EjiukgwSl2w0uYYctbxcqGtMXYBb/saXpu2M5pCqs34wvcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAdtN9znA9a6luPAQurcQn8kJBlllslRWsNPMhPWpMtYaMLx6JhmDICGbaYZBGUboedwnUaEk6tE2b+EVlUE/tnaKVJms2cmCCFExQQrTHmRfFI/Vi/esVqAnz1E2dB61LMnQ2AeebXAZ/C7hRt1uXVboXr5Zokppr4FRS9QsjSK4dhcXxhfglTKJOPZ4dkSexhe6hybpL8XdGhoyf2SyNXCy5iYX0zQ5BmJaLimOcJyasZ/A7/YgsVbQyAe6Ubno6/sIUuOZ+J+snZsBSLViqcftGVPUkIWamv/yNQcEJrDWa4C+sr+9Yb7uFjuj4gDY0jvGkGmu53g0K8Vks+IfAdQ=="
                ],
                "x5t#S256": "nTAGJuFFrm-vNBdkLVNmuePwTmlXr0T87IppgJPRT9k"
            }
        ]
    }

Here is the code I'm using to verify the access token with the x5c. I'm under the impression I should be using the x5c value, but if there is another way that is fine with me. Just need to verify the token with the above values under keys.

// break line every 64 characters.

x5cValue = x5cValue.replace(/(.{64})/g, "$1\n");

// base64 decode

var x5cValueAtob = atob(x5cValue);

// Add Begin / END certificate

x5cValue = "-----BEGIN CERTIFICATE-----\n" + x5cValueAtob + "\n-----END CERTIFICATE-----";

var decoded = KJUR.jws.JWS.verify(accessTokenJson, rawContent, ["RS256"]);

Should I be adding the BEGIN / END PUBLIC KEY strings to the x5c value before / after base64 decode? yes, thanks to Adam

Do I need to process the x5c value before verify?

Returned response - decoded: false

Thank you in advance.

UPDATED I'm trying to verify a JWT access token programmatically using the x5c / x509 public key value below. I can get this working by plugging the token and x5c values into external web sites but not programmatically using JavaScript / jsrsasign. Any suggestions would be greatly appreciated.

Here is the the OIDC provider's public JSON Web Key Set.

    {
        "keys": [
            {
                "kty": "RSA",
                "kid": "server",
                "use": "sig",
                "alg": "RS256",
                "n": "gLZO9w1OT_SWO-KbqiU0k3HevHggiY70XbDqgE1YaqhD-MwFUWNudExzF3oB28NYWYg5v6CJY0F-pUNtgukDM6ARDlh0n4xIvBRlnUnCTCx7pYOjpfXbTv49tlXmh4-ddh8EeQBLrF92u5UYs0tnZd8843mvYWohUNH1X1hM08-hpk7xCiy4XdwbeSlH757D2d5E0J0dGtZ744-dB2ZRCw2Vms_mk4Yyny4ifx2j2gIhikbb7WGmsTR2sWrtuhgZ_EBNUvrD0O54xbhQNTTFQ1pi9UZxo_gYc5Gp5fLcSOK6SDBKXbDS5hhy1vFyoa0xdgFv-xpem7YzmkKqzfjC9w",
                "e": "AQAB",
                "x5c": [
                    "MIIDMDCCAhigAwIBAgIEFIopYzANBgkqhkiG9w0BAQsFADBaMQkwBwYDVQQGEwAxCTAHBgNVBAgTADEJMAcGA1UEBxMAMQkwBwYDVQQKEwAxCTAHBgNVBAsTADEhMB8GA1UEAxMYZmNpc2Rldi5pY2UuaWJtY2xvdWQuY29tMB4XDTE4MTAwMTE4MTYyOFoXDTI4MDkyODE4MTYyOFowWjEJMAcGA1UEBhMAMQkwBwYDVQQIEwAxCTAHBgNVBAcTADEJMAcGA1UEChMAMQkwBwYDVQQLEwAxITAfBgNVBAMTGGZjaXNkZXYuaWNlLmlibWNsb3VkLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIC2TvcNTk/0ljvim6olNJNx3rx4IImO9F2w6oBNWGqoQ/jMBVFjbnRMcxd6AdvDWFmIOb+giWNBfqVDbYLpAzOgEQ5YdJ+MSLwUZZ1Jwkwse6WDo6X1207+PbZV5oePnXYfBHkAS6xfdruVGLNLZ2XfPON5r2FqIVDR9V9YTNPPoaZO8QosuF3cG3kpR++ew9neRNCdHRrWe+OPnQdmUQsNlZrP5pOGMp8uIn8do9oCIYpG2+1hprE0drFq7boYGfxATVL6w9DueMW4UDU0xUNaYvVGcaP4GHORqeXy3EjiukgwSl2w0uYYctbxcqGtMXYBb/saXpu2M5pCqs34wvcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAdtN9znA9a6luPAQurcQn8kJBlllslRWsNPMhPWpMtYaMLx6JhmDICGbaYZBGUboedwnUaEk6tE2b+EVlUE/tnaKVJms2cmCCFExQQrTHmRfFI/Vi/esVqAnz1E2dB61LMnQ2AeebXAZ/C7hRt1uXVboXr5Zokppr4FRS9QsjSK4dhcXxhfglTKJOPZ4dkSexhe6hybpL8XdGhoyf2SyNXCy5iYX0zQ5BmJaLimOcJyasZ/A7/YgsVbQyAe6Ubno6/sIUuOZ+J+snZsBSLViqcftGVPUkIWamv/yNQcEJrDWa4C+sr+9Yb7uFjuj4gDY0jvGkGmu53g0K8Vks+IfAdQ=="
                ],
                "x5t#S256": "nTAGJuFFrm-vNBdkLVNmuePwTmlXr0T87IppgJPRT9k"
            }
        ]
    }

Here is the code I'm using to verify the access token with the x5c. I'm under the impression I should be using the x5c value, but if there is another way that is fine with me. Just need to verify the token with the above values under keys.

// break line every 64 characters.

x5cValue = x5cValue.replace(/(.{64})/g, "$1\n");

// base64 decode

var x5cValueAtob = atob(x5cValue);

// Add Begin / END certificate

x5cValue = "-----BEGIN CERTIFICATE-----\n" + x5cValueAtob + "\n-----END CERTIFICATE-----";

var decoded = KJUR.jws.JWS.verify(accessTokenJson, rawContent, ["RS256"]);

Should I be adding the BEGIN / END PUBLIC KEY strings to the x5c value before / after base64 decode? yes, thanks to Adam

Do I need to process the x5c value before verify?

Returned response - decoded: false

Thank you in advance.

Share Improve this question edited Mar 18, 2019 at 19:18 Mike T asked Mar 18, 2019 at 16:52 Mike TMike T 1831 gold badge2 silver badges13 bronze badges 8
  • Looks like yes: kjur.github.io/jsjws/api/symbols/KJUR.jws.JWS.html#.verify – Adam Jenkins Commented Mar 18, 2019 at 17:10
  • I tried adding the following before base64 decoding and got the same error. x5cValue = "-----BEGIN CERTIFICATE-----" + x5cValue + "-----END CERTIFICATE-----"; – Mike T Commented Mar 18, 2019 at 18:27
  • Actually Adam you got me thinking, i added the BEGIN / END text and line breaks every 64 characters. So now I'm sending like this to verify and the error has changed to - false. I think I'm gettiing closer :) – Mike T Commented Mar 18, 2019 at 18:43
  • I have no idea, but I think you still need to decode the x5cValue in between the begin and end certificates so it's -----BEGIN CERTIFICATE-----${atob(x5cValue)}-----END CERTIFICATE-----. I'm curious about one thing, though, do you need to verify the token, or just decode it to get at it's contents? – Adam Jenkins Commented Mar 18, 2019 at 18:59
  • Thanks Adam, tried your suggestion. Updated the code above to show. Still getting false returned. – Mike T Commented Mar 18, 2019 at 19:16
 |  Show 3 more ments

2 Answers 2

Reset to default 5

I spent a day scratching my head and finally got it working like

public static PublicKey getPublicKey(String x5c) throws CertificateException, IOException {
    System.out.println(" x5c ="+x5c);
    String stripped = x5c.replaceAll("-----BEGIN (.*)-----", "");
    stripped = stripped.replaceAll("-----END (.*)----", "");
    stripped = stripped.replaceAll("\r\n", "");
    stripped = stripped.replaceAll("\n", "");
    stripped.trim();
    System.out.println(" stripped ="+stripped);
    byte[] keyBytes = Base64.decode(stripped);
    CertificateFactory fact = CertificateFactory.getInstance("X.509");
    X509Certificate cer = (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(keyBytes));
    return cer.getPublicKey();

}

This answer may not help you to answer all your questions, but I have to write it to improve the solution security.

I'm under the impression I should be using the x5c value,
Do I need to process the x5c value before verify?

From the security point of view - do not use the x5c certificate to validate the signature directly. In that case anybody could just provide its own certificate and spoof any identity.

The purpose if the x5t / x5t#S256 header is to identify the signer - check you trust the certificate provided by x5c or x5t#S256 (or its issuer) under the specified iss, only then you should validate the signature. The x5t headers enables your service to validate token from multiple IdP (identity providers / token issuers) or enable renewing the signer's certificate without loosing trust of the serice providers.

If you trust only a single identity provider using a single certificate, you may just directly use the provider's certificate without doing anything with the provided header.

For the solution - seems Adam is right in the ments, I as well suggest you use the KEYUTIL to load/parse the certificate

本文标签: javascriptCannot Verify JWT Using x5c (x509) public CertificateStack Overflow