- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在我的 MVC 站点上,如果我检测到正在使用 ADFS 帐户,我将重定向到 ADFS 登录页面。用户输入他们的 ADFS 凭据后,ADFS 站点发布一个 WsFederationMessage
回到我的网站。如何验证作为此 WsFederationMessage
的一部分提供给我的站点的 ADFS token ?
内部 AuthenticationHandler
中间件类,我有以下调用 ValidateToken
的相关代码方法:
IFormCollection form = await Request.ReadFormAsync();
WsFederationMessage wsFederationMessage = new WsFederationMessage(form);
if (!wsFederationMessage.IsSignInMessage)
{
Request.Body.Seek(0, SeekOrigin.Begin);
return null;
}
var token = wsFederationMessage.GetToken();
if (wsFederationMessage.Wresult != null && Options.SecurityTokenHandlers.CanReadToken(token))
{
SecurityToken validatedToken;
ClaimsPrincipal principal = Options.SecurityTokenHandlers.ValidateToken(token, Options.TokenValidationParameters, out validatedToken);
...
}
当我尝试调用 ValidateToken
时出现此错误:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.IdentityModel.SignatureVerificationFailedException: ID4037: The key needed to verify the signature could not be resolved from the following security key identifier 'SecurityKeyIdentifier (
IsReadOnly = False, Count = 1, Clause[0] = X509RawDataKeyIdentifierClause(RawData = [Removed by Author]. Ensure that the SecurityTokenResolver is populated with the required key.
在搜索分辨率时,我找到了 this article , 所以我解码了 X509Certificate
在 token
内呈现我上面代码中的字符串对象使用 this site's OpenSSL-based decoder ,因为它是在 <X509Certificate></X509Certificate>
中进行 PEM 编码的返回的 XAML 标记 token
字符串。事实上,这是解决方案文章所说的签名证书。所以我继续我的 ADFS 服务器,将签名证书导出为公共(public)证书并将其安装在我网站的 Trusted Root Certificate Authorities
上。 .该链接还提到我必须:
Import the certificate to the Signature tab of the RP Trust
因此,我将签名证书添加到我的 ADFS 服务器上我的依赖方信任的签名选项卡中,我在其中对我的机器标识符有一个信任规则。这一切之后,它仍然没有用。不过有一点背景知识,我的网站通过 IIS 在我的机器上本地运行,并且我更改了主机文件设置以使其指向 https://adfs-example.local/
.我的 ADFS 服务器目前通过 VPN 连接到我的站点,所以我的意思是 ADFS 服务器本身永远无法正确解析 https://adfs-example.local/
的标识符。如果它需要直接从此 URI 请求某些内容,但一旦浏览器重定向到我站点的登录页面并提供 ADFS token ,事情显然仍然有效。
将我的上帝遗弃的头撞在墙上,我尝试添加我自己的 IssuerSigningKeyResolver
:
TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKeyResolver = (token, securityToken, keyIdentifier, validationParameters) =>
{
var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var cert = store.Certificates.Find(X509FindType.FindByThumbprint, "<My Certificate's Thumbprint>", true)[0];
store.Close();
var provider = (RSACryptoServiceProvider)cert.PublicKey.Key;
return new RsaSecurityKey(provider);
}
};
现在我遇到了一个错误,但不知道如何处理它:
IDX10213: SecurityTokens must be signed. SecurityToken: '{0}'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.IdentityModel.Tokens.SecurityTokenValidationException: IDX10213: SecurityTokens must be signed. SecurityToken: '{0}'.
Source Error:
Line 61: Line 62: var validatedToken = (SecurityToken)null; Line 63: var principal = Options.SecurityTokenHandlers.ValidateToken(token, Options.TokenValidationParameters, out validatedToken); Line 64:
var claimsIdentity = principal.Identity as ClaimsIdentity; Line 65:
var ticket = new AuthenticationTicket(claimsIdentity, null);
处理程序被调用两次。在第一次调用时,这似乎成功了。似乎第一个 token 已签名。在第二次调用时,它失败了。似乎第二个 token 未签名。为什么我的一些安全 token 没有签名?我该如何进一步调试呢?有人遇到过这样的事情吗?
现在只好查源了,把AzureAD的整个trunk都拉出来了(也称为 Wilson),我正在检查代码。它在 SAML 安全 token 处理程序的这一行失败:
if (samlToken.Assertion.SigningToken == null && validationParameters.RequireSignedTokens)
{
throw new SecurityTokenValidationException(ErrorMessages.IDX10213);
}
我不明白。这意味着签名 token 为空。为什么签名 token 为空?
编辑:再次检查 ADFS 服务器,我认为设置它的人忘记将私钥包含在“ token 签名”和“ token 解密”证书中,这些证书是AD FS -> 服务 -> ADFS 管理单元的证书选项卡。但奇怪的是,通过与设置它的人的交谈,显然它需要服务证书并吐出另外两个用于 token 签名和解密......但没有他们的私钥?
编辑:根据this article ,这两个“ token 签名”和“ token 解密”证书应该是有效的,因为它们是自动生成的,只是它们的私钥存储在 Active Directory 中:
When you use the self-signed certificates for token signing and decryption, the private keys are stored in Active Directory in the following container:
CN=ADFS,CN=Microsoft,CN=Program Data,DC=domain,DC=com
Consequently, for the ADFS installation to install the private keys into this location, you must be a domain admin to install ADFS or have the appropriate rights assigned to this container.
最佳答案
最后,我放弃了 AzureAD Nuget 包,它无缘无故地引起了头痛。我采用了直接的方法。现在我只是要求我的 AD FS 服务器验证用户凭据。这是代码(请务必安装 Windows Identity Foundation SDK,并添加对 Microsoft.IdentityModel.dll
、System.IdentityModel.dll
和 的引用System.ServiceModel.dll
):
using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.Xml;
using Microsoft.IdentityModel.Protocols.WSTrust;
using Microsoft.IdentityModel.Protocols.WSTrust.Bindings;
namespace ADFSFederationToken
{
class Program
{
static string _relyingPartyIdentifier = "https://yourapplication.local/"; // Must be whatever you specified on your AD FS server as the relying party address.
static string _adfsServerAddress = "https://adfs.example.local/"; // Your ADFS server's address.
static string _username = "username@domain.local"; // A username to your ADFS server.
static string _password = "password"; // A password to your ADFS server.
static string _signingCertificateThumbprint = "1337..."; // Put the public ADFS Token Signing Certificate's thumbprint here and be sure to add it to your application's trusted certificates in the Certificates snap-in of MMC.
static string _signingCertificateCommonName = "ADFS Signing - adfs.example.local"; // Put the common name of the ADFS Token Signing Certificate here.
static void Main(string[] args)
{
Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory factory = null;
try
{
_relyingPartyIdentifier = _relyingPartyIdentifier.EndsWith("/") ? _relyingPartyIdentifier : _relyingPartyIdentifier + "/";
_adfsServerAddress = _adfsServerAddress.EndsWith("/") ? _adfsServerAddress : _adfsServerAddress + "/";
factory = new Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress(_adfsServerAddress + "adfs/services/trust/13/usernamemixed"));
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.UserName.UserName = _username;
factory.Credentials.UserName.Password = _password;
var rst = new Microsoft.IdentityModel.Protocols.WSTrust.RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointAddress(_relyingPartyIdentifier),
KeyType = WSTrust13Constants.KeyTypes.Bearer
};
var channel = factory.CreateChannel();
var genericToken = channel.Issue(rst) as GenericXmlSecurityToken;
var handler = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();
var tokenString = genericToken.TokenXml.OuterXml;
var samlToken = handler.ReadToken(new XmlTextReader(new StringReader(tokenString)));
ValidateSamlToken(samlToken);
}
finally
{
if (factory != null)
{
try
{
factory.Close();
}
catch (CommunicationObjectFaultedException)
{
factory.Abort();
}
}
}
}
public static ClaimsIdentity ValidateSamlToken(SecurityToken securityToken)
{
var configuration = new SecurityTokenHandlerConfiguration();
configuration.AudienceRestriction.AudienceMode = AudienceUriMode.Always;
configuration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(_relyingPartyIdentifier));
configuration.CertificateValidationMode = X509CertificateValidationMode.ChainTrust;
configuration.RevocationMode = X509RevocationMode.Online;
configuration.CertificateValidator = X509CertificateValidator.ChainTrust;
var registry = new ConfigurationBasedIssuerNameRegistry();
registry.AddTrustedIssuer(_signingCertificateThumbprint, _signingCertificateCommonName);
configuration.IssuerNameRegistry = registry;
var handler = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection(configuration);
var identity = handler.ValidateToken(securityToken).First();
return identity;
}
}
}
编辑:如果我想从 AzureAD NuGet 包开始工作并继续重定向并使用他们的表单发布请求解析器,我仍然可以使用上面的代码来完成此操作。我仍然可以读取 XAML token 字符串并解析为有效的 SecurityToken
对象,如下所示:
var token = wsFederationMessage.GetToken();
var samlToken = handler.ReadToken(new XmlTextReader(new StringReader(token)));
ValidateSamlToken(samlToken);
关于c# - 如何验证此 ADFS token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33236812/
我正在开发一个应用程序,它使用 OAuth - 基于 token 的身份验证。 考虑到我们拥有访问和刷新 token ,这就是流程的样子。 Api call -> intercepter append
如何取消标记此代码的输出? 类(class)核心: def __init__(self, user_input): pos = pop(user_input) subject = ""
当我使用命令 kubectl 时与 --token标记并指定 token ,它仍然使用 kubeconfig 中的管理员凭据文件。 这是我做的: NAMESPACE="default" SERVICE
我正在制作 SPA,并决定使用 JWT 进行身份验证/授权,并且我已经阅读了一些关于 Tokens 与 Cookies 的博客。我了解 cookie 授权的工作原理,并了解基本 token 授权的工作
我正在尝试从应用服务获取 Google 的刷新 token ,但无法。 日志说 2016-11-04T00:04:25 PID[500] Verbose Received request: GET h
我正在开发一个项目,只是为了为 java 开发人员测试 eclipse IDE。我是java新手,所以我想知道为什么它不起作用,因为我已经知道该怎么做了。这是代码: public class ecli
我正在尝试使用 JwtSecurityTokenHandler 将 token 字符串转换为 jwt token 。但它出现错误说 IDX12709: CanReadToken() returned
我已阅读文档 Authentication (来自 Facebook 的官方)。我仍然不明白 Facebook 提供的这三种访问 token 之间的区别。网站上给出了一些例子,但我还是不太明白。 每个
我的部署服务器有时有这个问题,这让我抓狂,因为我无法在本地主机中重现,我已经尝试在我的 web.config 中添加机器 key ,但没有成功远。 它只发生在登录页面。 我的布局:
我已经设法获得了一个简单的示例代码,它可以创建一个不记名 token ,还可以通过阅读 stackoverflow 上的其他论坛来通过刷新 token 请求新的不记名 token 。 启动类是这样的
如果我有以前的刷新 token 和使用纯 php 的访问 token ,没有 Google Api 库,是否可以刷新 Google Api token ?我在数据库中存储了许多用户刷新和访问 toke
我通过 Java 应用程序使用 Google 电子表格时遇到了问题。我创建了应用程序,该应用程序运行了 1 年多,没有任何问题,我什至在 Create Spreadsheet using Google
当我有一个有效的刷新 token 时,我正在尝试使用 Keycloak admin REST API 重新创建访问 token 。 我已经通过调用 POST/auth/realms/{realm}/p
我正在尝试让第三方 Java 客户端与我编写的 WCF 服务进行通信。 收到消息时出现如下异常: Cannot find a token authenticator for the 'System.I
在尝试将数据插入到我的 SQl 数据库时,我收到以下错误 System.Data.SqlServerCe.SqlCeException: There was an error parsing the
使用数据库 session token 系统,我可以让用户使用用户名/密码登录,服务器可以生成 token (例如 uuid)并将其存储在数据库中并将该 token 返回给客户端。其上的每个请求都将包
我最近注册了 Microsoft Azure 并设置了认知服务帐户。使用 Text Translation API Documentation 中的说明我能够使用 interactive online
我使用 IAntiforgery API 创建了一个 ASP.Net Core 2 应用程序。 这提供了一种返回 cookie 的方法。 客户端获取该 cookie,并在后续 POST 请求中将该值放
我正在使用 spacy 来匹配某些文本(意大利语)中的特定表达式。我的文本可以多种形式出现,我正在尝试学习编写一般规则的最佳方式。我有如下 4 个案例,我想写一个适用于所有案例的通用模式。像这样的东西
我无法理解 oauth 2.0 token 的原则处理。 我的场景是,我有一个基于 web 的前端后端系统,带有 node.js 和 angular 2。用户应该能够在此站点上上传视频。然后创建一些额
我是一名优秀的程序员,十分优秀!