在我的 ASP.NET Core Web API 上验证 Microsoft Access 令牌

问题描述 投票:0回答:1

Attached is the screenshot of the token在我的客户端(nextAuth),我从 Microsoft 获得了一次访问令牌,现在我希望从 ASP.NET Core Web API 上的后端验证该令牌。据我所知,该过程是从 Microsoft 获取密钥,并且具有相同“孩子”的密钥使用该密钥进行验证。

这是我从 Microsoft 获得的 JWT 的标头部分:

{
    "nonce": "v9eWI-Nv75YgvN8IgSNSlHPK-UH8iOcEUz8KXqj6DeA",
    "alg": "RS256",
    "x5t": "H9nj5AOSswMphg1SFx7jaV-lB9w",
    "kid": "H9nj5AOSswMphg1SFx7jaV-lB9w"
}

现在,经过大量尝试,我被迫对从 Microsoft 获得的密钥的证书值进行硬编码以获得一些成功

我访问了 URL https://login.microsoftonline.com/{myTenantId}/discovery/keys?appid={clientId}

得到了这个

{
      "kty": "RSA",
      "use": "sig",
      "kid": "H9nj5AOSswMphg1SFx7jaV-lB9w",
      "x5t": "H9nj5AOSswMphg1SFx7jaV-lB9w",
      "n": "iheTlbqieo0KzaFBTz6dxt9LAENfe2d0ywnpvZx9khzurtApc4ThWBpeoTBI6UpReeCwyW6DQjJSGCqHwe-wqRdgoiMc0PV-danrh0px38x2KL_j7VoHR0hlQBYOpp5GBMdz-Nsc80wBtHAqxz7Nno3qYNTXUvwZ2LSbbvgoPXrh0zhLlSrn2gAroRv6Z8xSOVg3CSmZeVgZHJv4aMYQiBiIIZW68YN5ywHxOf6-LdrhqN24NPSLYUNPKGxCkUkWg-VV-iulUqIkDxn3SKiX4zVA-jevbuUrsK3MeRHoJLqXMf8KnpPkf4ZLCTLdUNFyLyxFvqnm6QUAgpDrQ_rxhw",
      "e": "AQAB",
      "x5c": [
        "MIIC/jCCAeagAwIBAgIJAJjMBdn72zEjMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMjQwODE4MTkzMzIzWhcNMjkwODE4MTkzMzIzWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiheTlbqieo0KzaFBTz6dxt9LAENfe2d0ywnpvZx9khzurtApc4ThWBpeoTBI6UpReeCwyW6DQjJSGCqHwe+wqRdgoiMc0PV+danrh0px38x2KL/j7VoHR0hlQBYOpp5GBMdz+Nsc80wBtHAqxz7Nno3qYNTXUvwZ2LSbbvgoPXrh0zhLlSrn2gAroRv6Z8xSOVg3CSmZeVgZHJv4aMYQiBiIIZW68YN5ywHxOf6+LdrhqN24NPSLYUNPKGxCkUkWg+VV+iulUqIkDxn3SKiX4zVA+jevbuUrsK3MeRHoJLqXMf8KnpPkf4ZLCTLdUNFyLyxFvqnm6QUAgpDrQ/rxhwIDAQABoyEwHzAdBgNVHQ4EFgQUVOgUL8kBykezhhopW+Whb6mtqhowDQYJKoZIhvcNAQELBQADggEBAHqgxwjA+D7HzUT5mNRf8uizC9SkHdLXULyZTehFbSYEB3SYXZIbUWJcd88uaDUZ7CxPaojg6swmuB9XnzcZh8Gpa5y1ThSWvmPvUIDq1e03OJzhsC6dPmwoysmLvovngkGJ/AWURK7zRot53DLYWt0d/0KPDExPsovava0LeQjU8bLxHwQ9+8JFFxoN/aE85TQc8Whw+xZ4NX6BdTiucY8ku0smJLblwWui+mGyFSfDFW9r/r8LMUifgXTkaLYz4Z7sQdPFsdSoAR2jOzKhiz6acyQ1R4QUheN0EBmuPSsbu9M+E6tSYD+4q3GmQWtXjVagJoKPos0DIhe785YZjtI="
      ]
    }

正如你所看到的,两者都有相同的

kid

这是我的后端代码:

 private const string KeyString = @"MIIC/jCCAeagAwIBAgIJAJjMBdn72zEjMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMjQwODE4MTkzMzIzWhcNMjkwODE4MTkzMzIzWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiheTlbqieo0KzaFBTz6dxt9LAENfe2d0ywnpvZx9khzurtApc4ThWBpeoTBI6UpReeCwyW6DQjJSGCqHwe+wqRdgoiMc0PV+danrh0px38x2KL/j7VoHR0hlQBYOpp5GBMdz+Nsc80wBtHAqxz7Nno3qYNTXUvwZ2LSbbvgoPXrh0zhLlSrn2gAroRv6Z8xSOVg3CSmZeVgZHJv4aMYQiBiIIZW68YN5ywHxOf6+LdrhqN24NPSLYUNPKGxCkUkWg+VV+iulUqIkDxn3SKiX4zVA+jevbuUrsK3MeRHoJLqXMf8KnpPkf4ZLCTLdUNFyLyxFvqnm6QUAgpDrQ/rxhwIDAQABoyEwHzAdBgNVHQ4EFgQUVOgUL8kBykezhhopW+Whb6mtqhowDQYJKoZIhvcNAQELBQADggEBAHqgxwjA+D7HzUT5mNRf8uizC9SkHdLXULyZTehFbSYEB3SYXZIbUWJcd88uaDUZ7CxPaojg6swmuB9XnzcZh8Gpa5y1ThSWvmPvUIDq1e03OJzhsC6dPmwoysmLvovngkGJ/AWURK7zRot53DLYWt0d/0KPDExPsovava0LeQjU8bLxHwQ9+8JFFxoN/aE85TQc8Whw+xZ4NX6BdTiucY8ku0smJLblwWui+mGyFSfDFW9r/r8LMUifgXTkaLYz4Z7sQdPFsdSoAR2jOzKhiz6acyQ1R4QUheN0EBmuPSsbu9M+E6tSYD+4q3GmQWtXjVagJoKPos0DIhe785YZjtI=";

 [HttpPost("validate-token3")]
 public IActionResult DecodeValidToken()
 {
     try
     {
         string accessToken = "MyTokenHereWhichICannotPasteHere";

         var certificate = new X509Certificate2(Convert.FromBase64String(KeyString));
         var rsa = certificate.GetRSAPublicKey();
         var rsaSecurityKey = new RsaSecurityKey(rsa);
         var tokenHandler = new JwtSecurityTokenHandler();

         var validationParameters = new TokenValidationParameters
         {
             ValidateIssuerSigningKey = true,
             IssuerSigningKey = rsaSecurityKey,
             ValidateIssuer = false,
             ValidateAudience = false
         };

         var principal = tokenHandler.ValidateToken(accessToken, validationParameters, out SecurityToken validatedToken);
         return Ok(principal.Claims);
     }
     catch (SecurityTokenInvalidSignatureException ex)
     {
         return Unauthorized(new { Message = "Invalid token signature", Details = ex.Message });
     }
     catch (Exception ex)
     {
         return StatusCode(500, new { Message = "Internal server error", Details = ex.Message });
     }
 }

即使我的令牌有

kid
,我仍然收到此错误:

Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException:'IDX10503:签名验证失败。托肯没有孩子。尝试过的密钥:“Microsoft.IdentityModel.Tokens.RsaSecurityKey,KeyId:”,InternalId:“y16ADo8cPNxOAHfa262kqg7euKagSoVzzY5Wo4CzT5c”。 , 密钥 ID: '。 TokenValidationParameters 中的键数:“1”。 配置中的键数:“0”。 捕获异常:
”。
令牌:'[类型为“System.IdentityModel.Tokens.Jwt.JwtSecurityToken”的安全工件已隐藏。有关更多详细信息,请参阅 https://aka.ms/IdentityModel/SecurityArtifactLogging。]'。有关详细信息,请参阅 https://aka.ms/IDX10503。'

过去 4 天我一直在尝试解决这个问题,但仍然没有运气,即使我尝试了一种不同的方法,我们从 Microsoft 获取密钥并传递所有密钥进行验证

azure microsoft-graph-api asp.net-core-webapi single-sign-on microsoft-entra-id
1个回答
0
投票

我生成了访问令牌并尝试使用与下面相同的代码来验证令牌:

enter image description here

遇到了同样的错误

enter image description here

注意:Microsoft Graph API 令牌并不需要验证。

  • 它旨在与 Microsoft 服务一起使用。
  • 您只能验证适用于您的应用程序的 API。

因此要解决该错误,请检查以下内容:

公开 API 并添加范围:

enter image description here

授予API权限:

enter image description here

确保通过将 scope 传递为 api://***/ScopeName

 来生成 
访问令牌

现在token有效并且成功得到输出:

class Program
{
    private const string KeyString = @"xxx";

    static void Main(string[] args)
    {
        string accessToken = "MyTokenHereWhichICannotPasteHere"; 

        try
        {
            var certificate = new X509Certificate2(Convert.FromBase64String(KeyString));
            var rsa = certificate.GetRSAPublicKey();
            var rsaSecurityKey = new RsaSecurityKey(rsa);
            var tokenHandler = new JwtSecurityTokenHandler();

            var validationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = rsaSecurityKey,
                ValidateIssuer = false,
                ValidateAudience = false
            };

            var principal = tokenHandler.ValidateToken(accessToken, validationParameters, out SecurityToken validatedToken);
            Console.WriteLine("Token is valid. Claims:");
            foreach (var claim in principal.Claims)
            {
                Console.WriteLine($"{claim.Type}: {claim.Value}");
            }
        }
        catch (SecurityTokenInvalidSignatureException ex)
        {
            Console.WriteLine($"Unauthorized: Invalid token signature. Details: {ex.Message}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

enter image description here

请参阅此 GitHub 博客 Azure AD 身份验证、Next-Auth JWT 和 .NET Core Web API · nextauthjs/next-auth · 讨论 #5996 · GitHub,其中访问令牌是使用 Next-Auth 在前端生成的。

© www.soinside.com 2019 - 2024. All rights reserved.