我在Azure Active Directory中使用令牌身份验证(而不是cookie)。
基于这篇文章:https://www.itunity.com/article/angular-2-openid-connect-azure-active-directory-3093
我能够让它在客户端工作。
public validateSignature(token): Observable<boolean> {
/* Retrieve from federated metadata endpoint.
In this sample, the document was downloaded locally */
return this.httpService.get("metadata/metadata.xml")
.map((res: Response) => {
let dom = (new DOMParser()).parseFromString(res.text(), "text/xml");
let json = xml2json(dom, "");
let cert = "-----BEGIN CERTIFICATE-----" +
JSON.parse(json).EntityDescriptor[0]["ds:Signature"]
["KeyInfo"]["X509Data"]["X509Certificate"] +
"-----END CERTIFICATE-----";
let key = KEYUTIL.getKey(cert);
return KJUR.jws.JWS.verifyJWT(token, key, { alg: ['RS256'] });
})
}
我试图在.NET Core 1.0.3中重新实现上述方法。
基于这篇文章:how to sign and verify signature with net and a certificate
以下行不会在.NET Core上编译:
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PublicKey.Key;
我不确定根据.NET Core中的证书验证令牌的正确方法是什么。
答案 0 :(得分:2)
验证Azure AD发布的令牌的简单方法是利用Web API的OWIN注释。我们只需要配置JwtBearerOptions
并将请求发送到受Azure AD保护的控制器。如果未验证令牌,您将收到401响应。您可以参考代码示例here。
如果您想实现代码以手动验证令牌,我们可以参考代码,以便Microsoft在Microsoft.AspNetCore.Authentication.JwtBearer中验证令牌。
我还编写了一个代码示例供您参考:
public class JsonWebTokenValidator
{
public void Validate(string token)
{
var stsDiscoveryEndpoint = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
var options = new JwtBearerOptions
{
ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever()),
TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidateIssuer = true,
ValidIssuer = "https://sts.windows.net/{tenantId}/",
ValidateAudience = true,
ValidAudience = "{audience}",
RequireExpirationTime = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ClockSkew = TimeSpan.Zero
},
Authority = "https://login.microsoftonline.com/{tenantId}",
};
SecurityToken validatedToken = null;
ClaimsPrincipal result = null;
var configuration = options.ConfigurationManager.GetConfigurationAsync(new CancellationToken()).Result;
options.TokenValidationParameters.IssuerSigningKeys = configuration.SigningKeys;
options.ConfigurationManager.RequestRefresh();
foreach (var validators in options.SecurityTokenValidators)
{
result = validators.ValidateToken(token, options.TokenValidationParameters, out validatedToken);
}
foreach (var claim in result.Claims)
{
Console.WriteLine($"{claim.Subject}:{claim.Value}");
}
}
Project.json
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.IdentityModel.Clients.ActiveDirectory": "3.13.9",
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
},
"System.IdentityModel.Tokens.Jwt": {
"version": "5.1.3"
},
"Microsoft.AspNetCore.Authentication.JwtBearer": "1.0.0",
"Microsoft.IdentityModel.Protocols": "2.1.3",
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "2.0.0"
},
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
}
}
答案 1 :(得分:0)
根据此质量检查:implement RSA in .NET core您的cert
对象应该有一个GetRSAPublicKey()
方法,该方法返回一个RSA
对象 - 只需确保将其包装在using
中}因为它是IDisposable
。
static bool Verify(string text, byte[] signature, string certPath)
{
X509Certificate2 cert = new X509Certificate2( certPath );
using( RSA rsa = cert.GetRSAPublicKey() )
using( SHA1Managed sha1 = new SHA1Managed() )
{
byte[] data = Encoding.Unicode.GetBytes( text );
byte[] hash = sha1.ComputeHash( data );
return rsa.VerifyHash( hash, CryptoConfig.MapNameToOID("SHA1"), signature );
}
}
显然GetRSAPublicKey()
被定义为扩展方法:https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.rsacertificateextensions.getrsapublickey(v=vs.110).aspx