如何使用ADFS续订SAML断言?

时间:2017-09-26 12:06:32

标签: wcf saml adfs

我可以使用以下代码使用用户名和密码成功从ADFS请求SAML SecurityToken:

private GenericXmlSecurityToken IssueToken(string userName, string password)
{
    var relyingPartyIdentifier = new EndpointReference("https://mywebsite.net");
    var stsAddress = "https://myadfs.com/adfs/services/trust/13/usernamemixed";
    var wsBinding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential);

    wsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
    wsBinding.Security.Message.EstablishSecurityContext = false;
    wsBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

    var trustChannelFactory = new WSTrustChannelFactory(wsBinding, stsAddress);
    trustChannelFactory.Credentials.SupportInteractive = false;
    trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
    trustChannelFactory.Credentials.UserName.Password = password;
    trustChannelFactory.Credentials.UserName.UserName = userName;

    var tokenRequest = new RequestSecurityToken()
    {
        RequestType = RequestTypes.Issue,
        AppliesTo = relyingPartyIdentifier,
        KeyType = KeyTypes.Symmetric,
        TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"
    };

    tokenRequest.Claims.Add(new RequestClaim(ClaimTypes.Name));
    tokenRequest.Claims.Add(new RequestClaim(ClaimTypes.Email));

    var channel = trustChannelFactory.CreateChannel();
    var token = (GenericXmlSecurityToken)channel.Issue(tokenRequest);

    return token;
}

但是,该令牌将在一小时后到期。所以我的问题是,如何根据初始令牌发出新令牌,以便我不需要记住用户名和密码?

我尝试了以下代码:

public GenericXmlSecurityToken RenewToken(SecurityToken token)
{
    var relyingPartyIdentifier = new EndpointReference("https://mywebsite.net");
    var stsAddress = "https://myadfs.com/adfs/services/trust/13/usernamemixed";
    var wsBinding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);

    wsBinding.Security.Message.EstablishSecurityContext = false;
    wsBinding.Security.Message.IssuerAddress = new EndpointAddress(new Uri(stsAddress));
    wsBinding.Security.Message.IssuerBinding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential);
    wsBinding.Security.Message.IssuerMetadataAddress = new EndpointAddress("https://myadfs.com/adfs/services/trust/mex");

    var trustChannelFactory = new WSTrustChannelFactory(wsBinding, stsAddress);
    trustChannelFactory.Credentials.SupportInteractive = false;
    trustChannelFactory.Credentials.UserName.UserName = Settings.UserName;
    trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;

    var tokenRequest = new RequestSecurityToken()
    {
        RequestType = RequestTypes.Renew,
        RenewTarget = new SecurityTokenElement(token),
        AppliesTo = relyingPartyIdentifier,
        KeyType = KeyTypes.Symmetric,
        TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1",
    };

    tokenRequest.Claims.Add(new RequestClaim(ClaimTypes.Name));
    tokenRequest.Claims.Add(new RequestClaim(ClaimTypes.Email));

    var channel = trustChannelFactory.CreateChannel();

    // This call fails with: 
    // SecurityNegotiationException: Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint. '
    // Inner Exception: FaultException: An error occurred when verifying security for the message.
    var newToken = (GenericXmlSecurityToken)channel.Issue(tokenRequest);

    return newToken;
}

但是对channel.Issue的调用失败,出现以下异常:

SecurityNegotiationException:无法打开安全通道,因为与远程端点的安全协商失败。这可能是由于在用于创建通道的EndpointAddress中缺少或错误指定了EndpointIdentity。请验证EndpointAddress指定或暗示的EndpointIdentity是否正确标识远程端点。 '

内部异常: FaultException:验证邮件的安全性时发生错误。

我完全不知道如何使用初始令牌获取新令牌。

0 个答案:

没有答案