但是如果你没有在你的项目中使用OWIN,那将会有点困难或者至少耗费时间。 本文 这里 是很好的资源。
而且因为除了详细的代码之外,我没有太多要补充的内容。这里有一些对你有用的东西:
public async Task<ClaimsPrincipal> CreatePrincipleAsync() { AzureActiveDirectoryToken azureToken = Token.FromJsonString<AzureActiveDirectoryToken>(); var allParts = azureToken.IdToken.Split("."); var header = allParts[0]; var payload = allParts[1]; var idToken = payload.ToBytesFromBase64URLString().ToAscii().FromJsonString<AzureActiveDirectoryIdToken>(); allParts = azureToken.AccessToken.Split("."); header = allParts[0]; payload = allParts[1]; var signature = allParts[2]; var accessToken = payload.ToBytesFromBase64URLString().ToAscii().FromJsonString<AzureActiveDirectoryAccessToken>(); var accessTokenHeader = header.ToBytesFromBase64URLString().ToAscii().FromJsonString<AzureTokenHeader>(); var isValid = await ValidateToken(accessTokenHeader.kid, header, payload, signature); if (!isValid) { throw new SecurityException("Token can not be validated"); } var principal = await CreatePrincipalAsync(accessToken, idToken); return principal; } private async Task<bool> ValidateToken(string kid, string header, string payload, string signature) { string keysAsString = null; const string microsoftKeysUrl = "https://login.microsoftonline.com/common/discovery/keys"; using (var client = new HttpClient()) { keysAsString = await client.GetStringAsync(microsoftKeysUrl); } var azureKeys = keysAsString.FromJsonString<MicrosoftConfigurationKeys>(); var signatureKeyIdentifier = azureKeys.Keys.FirstOrDefault(key => key.kid.Equals(kid)); if (signatureKeyIdentifier.IsNotNull()) { var signatureKey = signatureKeyIdentifier.x5c.First(); var certificate = new X509Certificate2(signatureKey.ToBytesFromBase64URLString()); var rsa = certificate.GetRSAPublicKey(); var data = string.Format("{0}.{1}", header, payload).ToBytes(); var isValidSignature = rsa.VerifyData(data, signature.ToBytesFromBase64URLString(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); return isValidSignature; } return false; }
我在这里使用的一些功能是不可用的,它们是自描述的。
验证令牌有两个步骤。首先,验证令牌的签名以确保令牌是由Azure Active Directory颁发的。其次,根据业务逻辑验证令牌中的声明。
例如,我们需要验证 iss 和 aud 如果您正在开发单个租户应用程序,则声明。而且你还需要验证 nbf 确保令牌未过期。您可以参考的更多声明 这里 。
iss
aud
nbf
以下描述来自 这里 关于签名验证的细节。 (注意:下面的示例使用Azure AD v2端点。您应该使用与客户端应用程序正在使用的端点对应的端点。)
Azure AD中的访问令牌是JSON Web令牌(JWT),由安全令牌服务在私钥中签名。 JWT包括3个部分:标题,数据和签名。从技术上讲,我们可以使用公钥来验证访问令牌。 第一步 - 检索并缓存歌唱令牌(公钥) 终点: https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
Azure AD中的访问令牌是JSON Web令牌(JWT),由安全令牌服务在私钥中签名。
JWT包括3个部分:标题,数据和签名。从技术上讲,我们可以使用公钥来验证访问令牌。
第一步 - 检索并缓存歌唱令牌(公钥)
终点: https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
然后我们就可以使用了 JwtSecurityTokenHandler 使用以下示例代码验证令牌:
JwtSecurityTokenHandler
public JwtSecurityToken Validate(string token) { string stsDiscoveryEndpoint = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration"; ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint); OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result; TokenValidationParameters validationParameters = new TokenValidationParameters { ValidateAudience = false, ValidateIssuer = false, IssuerSigningTokens = config.SigningTokens, ValidateLifetime = false }; JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler(); SecurityToken jwt; var result = tokendHandler.ValidateToken(token, validationParameters, out jwt); return jwt as JwtSecurityToken; }
如果您在项目中使用OWIN组件,则更容易验证令牌。我们可以使用以下代码验证令牌:
app.UseWindowsAzureActiveDirectoryBearerAuthentication( new WindowsAzureActiveDirectoryBearerAuthenticationOptions { Audience = ConfigurationManager.AppSettings["ida:Audience"], Tenant = ConfigurationManager.AppSettings["ida:Tenant"] });
然后我们可以使用下面的代码来验证令牌中的“范围”:
public IEnumerable<TodoItem> Get() { // user_impersonation is the default permission exposed by applications in AAD if (ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/scope").Value != "user_impersonation") { throw new HttpResponseException(new HttpResponseMessage { StatusCode = HttpStatusCode.Unauthorized, ReasonPhrase = "The Scope claim does not contain 'user_impersonation' or scope claim not found" }); } ... }
这是一个使用Azure AD保护Web API的代码示例:
使用Azure AD中的承载令牌保护Web API
只是想为使用.net Core 2.0的人添加Fei的答案
你将不得不修改2行 Validate(string token) 方法。
Validate(string token)
ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint , new OpenIdConnectConfigurationRetriever()); //need the 'new OpenIdConnect...' ... TokenValidationParameters validationParameters = new TokenValidationParameters { ValidateAudience = true, ValidateIssuer = true, IssuerSigningKeys = config.SigningKeys, //.net core calls it "IssuerSigningKeys" and "SigningKeys" ValidateLifetime = true };