创建委托令牌 - 无法创建SecurityTokenService

时间:2012-05-29 07:18:07

标签: c# visual-studio-2012 .net-4.5 adfs2.0

我正在尝试构建一个使用ADFS和声明的系统。目前,这只是一个“玩具”实施。

我构建了一个非常简单的MVC Web应用程序,使用Visual Studio中的“Identity and Access ...”向导进行设置,以便与ADFS 2.0服务器通信,并将其部署到IIS服务器。一切正常,我可以检查并列出收到的索赔。

下一步是构建基于Web API的REST服务(表示MVC应用程序将依赖的后端服务),因此我希望将凭据传递到该后端服务器,以便它可以作出适当的授权决定。

所以第一步是让我创建委托令牌(然后,我希望能够根据HttpClient类来解决它的问题,以便进行其余的调用)。我有这个:

//We need to take the bootstrap token and create an appropriate ActAs token
var rst = new RequestSecurityToken
{
    AppliesTo = new EndpointReference("https://other-iis.example.com/Rest"),
    RequestType = RequestTypes.Issue,
    KeyType = KeyTypes.Symmetric,
    ActAs = new SecurityTokenElement(((BootstrapContext)((ClaimsIdentity)User.Identity).BootstrapContext).SecurityToken)
};

var sts = new SecurityTokenService(); //This line isn't valid
var resp = sts.Issue(System.Threading.Thread.CurrentPrincipal as ClaimsPrincipal, rst);

但问题是SecurityTokenService是抽象的。我在System.IdentityModelSystem.IdentityModel.Services中找不到从这个类派生的任何类型,并且上面没有包含对ADFS服务器的任何引用,我显然需要在某些时候提供它。

当然,我也可能完全走错了路线,或者只是碰到了一个小绊脚石而且看不到远处有一个更大的绊脚石,所以对此的任何建议也会受到赞赏。


我看过,例如,Identity Delegation Scenario,但是使用了CreateChannelActingAs,我认为在与休息服务交谈时我认为这不会起作用(或者是?),似乎也不适用于.NET 4.5。

3 个答案:

答案 0 :(得分:3)

我从ADFS 2.0请求令牌进行缓存并查看DisplayToken。也许这可以帮助你开始。

以下是我的最新动态:

    public SecurityToken GetToken(out RequestSecurityTokenResponse rstr)
    {
        Console.WriteLine("Connecting to STS...");

        WSTrustChannelFactory factory = null;

        try
        {
            if (_useCredentials)
            {
                // use a UserName Trust Binding for username authentication
                factory =
                    new WSTrustChannelFactory(
                        new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
                        "https://<adfs>/adfs/services/trust/13/UsernameMixed");

                factory.TrustVersion = TrustVersion.WSTrust13;

                // Username and Password here...
                factory.Credentials.UserName.UserName = "username";
                factory.Credentials.UserName.Password = "password";
            }
            else
            {
                // Windows authentication over transport security
                factory = new WSTrustChannelFactory(
                    new WindowsWSTrustBinding(SecurityMode.Transport),
                    "https://<adfs>/adfs/services/trust/13/windowstransport") { TrustVersion = TrustVersion.WSTrust13 };
            }

            var rst = new RequestSecurityToken
                          {
                              RequestType = RequestTypes.Issue,
                              AppliesTo = SvcEndpoint,
                              KeyType = KeyTypes.Symmetric,
                              RequestDisplayToken = true
                          };

            Console.WriteLine("Creating channel for STS...");

            IWSTrustChannelContract channel = factory.CreateChannel();

             Console.WriteLine("Requesting token from " + StsEndpoint.Uri);
             SecurityToken token = channel.Issue(rst, out rstr);
             Console.WriteLine("Received token from " + StsEndpoint.Uri);

            return token;
        }
        finally
        {
            if (factory != null)
            {
                try
                {
                    factory.Close();
                }
                catch (CommunicationObjectFaultedException)
                {
                    factory.Abort();
                }
            }
        }
    }

如果您想使用它,可能必须在ADFS 2.0中激活UsernameMixed端点,并且不要忘记之后重新启动服务!

答案 1 :(得分:1)

来自msdn

要创建STS,您必须从SecurityTokenService类派生。在您的自定义类中,您必须至少覆盖GetScope和GetOutputClaimsIdentity方法。

答案 2 :(得分:1)

不确定这对你有多大帮助,但你不应该创建一个SecurityTokenService。你不是在这里创建一个新的令牌,你的应用程序不应该作为STS - 这就是AD FS的用途。
您的应用程序应该只将从AD FS收到的令牌委托给服务(该概念在您在问题中提供的msdn链接中描述)

我猜你的网络api也很有可能支持这个,因为它建立在wcf上,从http的角度来看 - 没有理由它不支持ws-federation / saml 2令牌。

编辑:
This视频(从35:00开始 - )显示了一种方式,我认为,使用ws-federation saml标记来实现您正在寻找的内容。我猜测它也可以使用saml2令牌