Как проверить токен JWT, подписанный с x509 только с открытым ключом в AspNetCore - PullRequest
1 голос
/ 25 сентября 2019

У меня есть приложение AspNetCore, которое генерирует для меня токен JWT на основе сертификата PFX.

public string GenerateToken()
{
    using (var certificate = new X509Certificate2("certificate.pfx"))
    {
        var credentials = new X509SigningCredentials(certificate);
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.Name, "Name"),
                new Claim(ClaimTypes.Role, "Tester"),
            }),
            IssuedAt = DateTime.UtcNow,
            Expires = DateTime.UtcNow.AddDays(1),
            SigningCredentials = credentials
        };

        var handler = new JwtSecurityTokenHandler();
        var token = handler.CreateToken(tokenDescriptor);
        return handler.WriteToken(token);
    }
}

И с тем же PFX вы можете проверить, действительна ли подпись.

public ClaimsPrincipal ValidateToken(string token)
{
    using (var certificate = new X509Certificate2("certificate.pfx"))
    {
        var key = new X509SecurityKey(certificate);
        var validationParameters = new TokenValidationParameters()
        {
            ValidateAudience = false,
            ValidateIssuer = false,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = key
        };

        var handler = new JwtSecurityTokenHandler();
        try
        {
            var claims = handler.ValidateToken(token, validationParameters, out var validatedToken);
            if (claims != null && validatedToken != null)
            {
                return claims;
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
        }
    }

    return null;
}

Но для этого требуется, чтобы другие приложения, которым требуется только проверка токена JWT, также имели доступ к этому сертификату PFX.

Если я возьму сгенерированный токен с этим PFX

eyJhbGciOiJSUzI1NiIsImtpZCI6IjZEQzE4QTU4MEI4QjIxNzE4MjY5MTdDNkRGRDdGNjM5NEFBMTAwNDgiLCJ4NXQiOiJiY0dLV0F1TElYR0NhUmZHMzlmMk9VcWhBRWciLCJ0eXAiOiJKV1QifQ.eyJ1bmlxdWVfbmFtZSI6Ik5hbWUiLCJyb2xlIjoiVGVzdGVyIiwibmJmIjoxNTY5NDI4MDIwLCJleHAiOjE1Njk1MTQ0MTksImlhdCI6MTU2OTQyODAxOX0.kmszDk3cYEfK7dOzynotOuzTkc0GFIMbRau5ELOUROz5De-6M4YA_tWpjH1Ss6wPM078RKZeMIpolMOGvCLaza1XUp2w7fiJ_zWNJ1r4XiYzfdGiHnrUM7IwjYfwVbV7Ez2sk0FMmka-yO0UeHOKICEoxUAEBA_KzJiWHQfJJssOxcNdu4rwX1CeJ0xnJCKi77GDZ54GhdrQ_NuHzWOQZrsLa7_QfJtNTufOAzAg_kSI7XRCt6LOIkNTiENY_iJSnurlbg0O3VqkmlBvBEOS-ihd0h2Gt_AGEJ22OB4oh7Xip-xf7gm4dPR2u3ISEVmEq5H6J444CDuuKKulB7OLeKEnh9-2fGw8o-q-RIZeOo4r6UqxEW3n6TrEu7hIoAP72x5xc8ptpAPG9GtCsUjMgZcQV4QCLA9zxNxApC6J9cmgZgfI7kTGeardjsy32I23BjUl0AH0c4lh5I3SVeZB7W0mvqLj_UG_O8o57c-0dhU5kcYXJjI5gtQc1gba0ZCokA5NomnHmtpWuNvtRp4O2PwbyjM2O2RxxN07fAkPC1o4Ukm-b_n_OudyznLfmFZwv9wxqn5n-_vIy4WPuM1tm-LIzuXb0dRHDJrI8OPtj43VKNMEkQO604Fb13tVvj3iMB_n3ZWSMuLtMBLNeIED-3eynZfnr0vdMYktHNsvf6o

и поместите его в https://jwt.io/ Мне нужен только открытый ключ для проверки подписи.

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxd05ZB9CBfleKjaKzBTv
HylxmrEbm/yPLQKgB3oFwK4qCtcvr9dwsdK7iqFKqrmWIU/6CQrMdrx/k1s0NDWn
jdQCsnTpJ/i/rbGyasL80ilsXjOnA6G07OpvVO88Jn6J9Jz8oDsKSRpk1YV8Z6UM
pGnvlwhkhvTa43sICAPlbdc+FVzT5/3UGHiZ7D0M7I4cMLchrjQM+XP3M7AJl2vC
x/oo7twIzl/J4R5AvKlVz57NSggvyLkAIUIGEM8NpINt1f4aWEthWSLcMf8KUBJX
33MGDWb0HXaA/m1ovxWzmh001qa/miw8xl/ViurEeX9lZZjtNvW3PbV4TB4CxPUj
u61occD/Mek664PBMq+qztM22jg3tyAiIhyntDeLZtRpI3e1TwYMgF21PAc3Vskd
iuqhwFM9V/lVaRJJFJIqd94dOT20FZ78ECFCSnSEjNLaAd2Cm6WzoCf2qYPdb9ZD
2aRUm9+x0bbKxr7dFAM8mC753zuWpAPd0HGo6peAdVBQ4ZYQJ+9Px6lKcSsz4dMq
2OkoBNBCLgDaBZjfbNSxWt57OIDZpteFGgPETYf4JHs85/91JnztS/bAU1h0zrdh
L8s0l8IF89abOt5ZQ6PlwtljhMHBOjO41o/5pFo3hAEmTfv2aUjOH+amhbX9jeOJ
wFtHPr7inytlyltrrNwByeMCAwEAAQ==
-----END PUBLIC KEY-----

Я бы хотел, чтобы другое приложение только требовало мой открытый ключ, поэтому я делаюне нужно распределять PFX по нескольким приложениям (что позволяет им самим генерировать токены JWT).

Как проверить токены JWT, подписанные сертификатом X509, только с открытым ключом в AspNetCore?

1 Ответ

0 голосов
/ 26 сентября 2019

Основываясь на предложении @ Crypt32, я смог создать отдельный сертификат.

using (var certificate = new X509Certificate2("certificate.pfx"))
{
    using (var file = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read))
    {
        await file.WriteAsync(certificate.RawData);
    }
}

С этим новым сертификатом я смог успешно проверить токены, но при попытке создать новый токен я получилInvalidOperationException.

System.InvalidOperationException
  HResult=0x80131509
  Message=IDX10638: Cannot create the SignatureProvider, 'key.HasPrivateKey' is false, cannot create signatures. Key: [PII is hidden. For more details, see https://aka.ms/IdentityModel/PII.].
  Source=Microsoft.IdentityModel.Tokens
  StackTrace:
   at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider..ctor(SecurityKey key, String algorithm, Boolean willCreateSignatures)
   at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures)
   at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateJwtSecurityTokenPrivate(String issuer, String audience, ClaimsIdentity subject, Nullable`1 notBefore, Nullable`1 expires, Nullable`1 issuedAt, SigningCredentials signingCredentials, EncryptingCredentials encryptingCredentials)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateToken(SecurityTokenDescriptor tokenDescriptor)

Так что, похоже, это способ распространения валидатора токена JWT.

...