简体   繁体   English

在WCF WIF管道中处理REST SWT令牌不起作用

[英]Handling REST SWT tokens in WCF WIF pipeline is not working

I'm struggling on a setup mentioned in the subject line and am wondering if someone can help me. 我正在努力解决主题行中提到的设置,并且想知道是否有人可以帮助我。

Essentially, what I have is a WCF service and I want to achieve that the user can authenticate against the ACS using a custom login page (using the javascript with required information from ACS). 从本质上讲,我拥有的是WCF服务,并且我想实现用户可以使用自定义登录页面(使用javascript和ACS提供的必需信息)针对ACS进行身份验证的功能。

After doing that the user should get redirected to the WCF service using the provided SWT token. 之后,应使用提供的SWT令牌将用户重定向到WCF服务。 I am using the SimpleWebTokenHandler as a basis for the SWT token handling, but I'm not sure it's playing any role in this. 我正在使用SimpleWebTokenHandler作为SWT令牌处理的基础,但是我不确定它是否在其中起任何作用。

Here's the Web.config I'm running 这是我正在运行的Web.config

<configuration>
    <configSections>
        <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
        <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral" />
    </configSections>
    ...
    <system.serviceModel>
        <diagnostics>
        </diagnostics>
        <services>
            <service name="WcfWifSwtAcs.Service1">
                <endpoint address="xmlService" binding="webHttpBinding" bindingConfiguration="" behaviorConfiguration="restPoxBehaviour" name="xmlServiceEndpoint" contract="WcfWifSwtAcs.IService1" />
            </service>
        </services>
        <behaviors>
            <endpointBehaviors>
                <behavior name="restPoxBehaviour">
                    <webHttp helpEnabled="true" />
                </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior>
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceCredentials useIdentityConfiguration="true">
                        ...
                    </serviceCredentials>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <protocolMapping>
            <add scheme="http" binding="ws2007FederationHttpBinding" />
        </protocolMapping>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
        <bindings>
            <ws2007FederationHttpBinding>
                <binding name="">
                    <security mode="Message">
                        <message 
                            issuedTokenType="http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0">
                            <issuerMetadata address="https://xxxx.accesscontrol.windows.net/v2/wstrust/13/certificate/mex" />
                        </message>
                    </security>
                </binding>
            </ws2007FederationHttpBinding>
        </bindings>
    </system.serviceModel>
    <system.webServer>
    ...
    </system.webServer>
    <system.identityModel>
        <identityConfiguration>
            <audienceUris>
                <add value="http://localhost:56782/Service1.svc" />
            </audienceUris>
            <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
                <trustedIssuers>
                    <add thumbprint="XXX" name="xxx.accesscontrol.windows.net" />
                </trustedIssuers>
            </issuerNameRegistry>
        <issuerTokenResolver type="SimpleWebToken.CustomIssuerTokenResolver, WcfWifSwtAcs" />
            <securityTokenHandlers>
                <clear/>
                <add type="SimpleWebToken.SimpleWebTokenHandler, WcfWifSwtAcs"/>
            </securityTokenHandlers>
        </identityConfiguration>
    </system.identityModel>
</configuration>

Now I can see, that the authentication happens and that the browser is redirected with the body to the service. 现在我可以看到,身份验证已经完成,浏览器随主体一起重定向到了服务。 I can also see that the SimpleWebToken handler get's instantiated and the token type URI is being requested. 我还可以看到,实例化了SimpleWebToken处理程序,并且正在请求令牌类型URI。 But that's almost all that happens. 但这几乎就是所有的事情。 No actual token handling verification and whatsoever is happnening. 没有实际的令牌处理验证,而且任何事情都令人惊讶。

This is the token that get's sent to the service (after parsing). 这是发送到服务(在解析后)的令牌。

wa=wsignin1.0&
wresult=
<t:RequestSecurityTokenResponse 
xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:Lifetime>
    <wsu:Created 
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2013-02-13T23:14:30.159Z</wsu:Created>
    <wsu:Expires
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2013-02-13T23:24:30.159Z</wsu:Expires>
</t:Lifetime>
<wsp:AppliesTo 
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
    <EndpointReference
        xmlns="http://www.w3.org/2005/08/addressing">
        <Address>http://localhost:56782/Service1.svc</Address>
    </EndpointReference>
</wsp:AppliesTo>
<t:RequestedSecurityToken>
    <wsse:BinarySecurityToken 
        wsu:Id="uuid:58e2fb15-dd1a-40bd-8ff0-ae24e22e6efe" 
        ValueType="http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0"
        EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"          xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        BASE64 DATA==
    </wsse:BinarySecurityToken>
</t:RequestedSecurityToken>
<t:TokenType>http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
</t:RequestSecurityTokenResponse>

Service itself is braindead simple, with following signature. 服务本身很简单,带有以下签名。

[OperationContract]
[WebInvoke(UriTemplate = "/GetData/{id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string GetData(string id);

Any ideas? 有任何想法吗? I've been verifying that the uri's, hostnames, thumbprints etc. are all valid. 我一直在验证uri的名称,主机名,指纹等均有效。 Also the service tracing doesn't really show up anything that is related either to token handling or exceptions in the token verification. 同样,服务跟踪并没有真正显示出与令牌处理或令牌验证中的异常相关的任何内容。

Somehow it almost seems that the token doesn't get even passed to the handler. 不知何故,令牌似乎甚至没有传递给处理程序。 At least all the claims and other authentication information is missing (null). 至少所有声明和其他身份验证信息都丢失(空)。

I would appreciate if someone points me to a direction of either where can I debug or if I'm missing something really obvious (which might also always be the case). 如果有人指出我在哪里可以调试或缺少真正明显的东西(可能总是如此)的方向,我将不胜感激。

PS I know I could achieve it with custom authentication modules and whatsoever, I'd rather get it running with WIF (it's becoming fundamental as I've spend more time on this as I really wanted and I'm very stubborn :p). PS我知道我可以使用自定义的身份验证模块来实现它,无论如何,我都希望它与WIF一起运行(因为我已经按照自己的意愿花了更多时间,而且我非常固执:p,它已成为基础。

Soo, dedication will bring one to a solution. 如此,奉献将带来一个解决方案。 Although I initially thought that this can't be done, it's apparent that it actually can. 尽管我最初认为这是无法完成的,但显然可以做到。 I'll put the solution here, as maybe there are other people who find it useful. 我将解决方案放在这里,因为也许其他人发现它很有用。

First of all, WCF REST services are using webHttpBinding , which according to MS documentation does not support the Windows Identity Foundation and claims handling in the pipeline. 首先,WCF REST服务使用的是webHttpBinding ,根据MS文档,它不支持Windows Identity Foundation并且要求在管道中进行处理。 Actually it does. 实际上确实如此。 Not in the WCF pipeline, but as the IIS module in web authentication flow. 不在WCF管道中,而是作为Web身份验证流程中的IIS模块。

First, you need to add the following modules to Web.config file. 首先,您需要将以下模块添加到Web.config文件中。

<system.webServer>
    <modules runManagedModulesForAllRequests="true">
        <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" preCondition="managedHandler" />
        <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" preCondition="managedHandler" />
    </modules>
 </system.webServer>

There's a caveat tho. 有一个警告。 You need still the <configSections> from my original posting. 您仍然需要我原始帖子中的<configSections> The problem is that you need, in VisualStudio, to mark the System.IdentyModel* assemblies as CopyLocal items (in the properties window). 问题是,您需要在VisualStudio中将System.IdentyModel*程序集标记为CopyLocal项目(在属性窗口中)。 Otherwise you'll get some cryptic exception that assembly cannot be loaded for the configuration section. 否则,您将获得一些神秘的例外,即无法为配置部分加载程序集。 NB! NB! It only happens if you are loading these two modules and doesn't happen when those modules are not getting loaded. 仅在加载这两个模块时发生,而在未加载这两个模块时则不会发生。 Didn't have any will to investigate that thing further, perhaps someone knows better what's the cause there. 没有进一步调查该事的意愿,也许有人更清楚那是什么原因。

Next if for any reason you plan to use the SWT token handling sample from MS WIF code, there are a couple of bugs that need to be fixed, otherwise the token parsing just won't happen or you will get invalid signatures out of the token verification. 接下来,如果出于任何原因您打算使用MS WIF代码中的SWT令牌处理示例,则需要修复几个错误,否则将不会进行令牌解析,否则您将获得令牌中无效的签名验证。

SimpleWebToken.cs you need to fix the SwtBaseTime as it is initialized incorrectly and the security token creation fails afterwards: 您需要修复SimpleWebToken.cs ,因为SwtBaseTime初始化不正确,并且之后安全令牌创建失败:

From public static DateTime SwtBaseTime = new DateTime( 1970, 1, 1, 0, 0, 0, 0 ); 来自公共静态DateTime SwtBaseTime = new DateTime(1970,1,1,0,0,0,0); // per SWT psec To //每SWT秒

public static DateTime SwtBaseTime = new DateTime( 1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc ); // per SWT psec

SimpleWebTokenHandler.cs you need to fix the casing of the following values: 您需要修复SimpleWebTokenHandler.cs的以下值的大小写:

From

const string BinarySecurityToken = "binarySecurityToken";
const string ValueType = "valueType";

To

const string BinarySecurityToken = "BinarySecurityToken";
const string ValueType = "ValueType";

CustomIssuerTokenResolver.cs you need to fix the key that is created as it's initalized with a UTF8 bytes, but it should actually get initialized with decoded Base64 bytes: CustomIssuerTokenResolver.cs您需要修复使用UTF8字节初始化的密钥,但实际上应使用解码的Base64字节对其进行初始化:

From

key = new InMemorySymmetricSecurityKey(UTF8Encoding.UTF8.FromBase64String(base64Key));

To

key = new InMemorySymmetricSecurityKey(System.Convert.FromBase64String(base64Key));

After you've fixed all this, everything sits in place. 修复所有问题后,所有内容就位。 The authenticators and authorizators are getting called and voilà, suddenly you have a WCF Service exposed as REST endpoint and all the claims etc. are also working. 身份验证者和授权者被呼叫并打断,突然之间,您有一个作为REST端点公开的WCF服务,并且所有声明等也都在工作。

I think your issue may be with the SWTTokenHandler in this sample: http://code.msdn.microsoft.com/vstudio/Custom-Token-ddce2f55 我认为您的问题可能与该示例中的SWTTokenHandler有关: http ://code.msdn.microsoft.com/vstudio/Custom-Token-ddce2f55

In CanReadToken(), it checks to see if the token is a BinarySecurityToken of type SWT: 在CanReadToken()中,它检查令牌是否为SWT类型的BinarySecurityToken:

if ( reader.IsStartElement( BinarySecurityToken )
&& ( reader.GetAttribute( ValueType ) == SimpleWebTokenConstants.ValueTypeUri ) )

But the constant BinarySecurityToken is defined as: 但是常量BinarySecurityToken定义为:

const string BinarySecurityToken = "binarySecurityToken";

Note the lower-case "b". 注意小写的“ b”。 XML elements are case sensitive, and the actual element is "BinarySecurityToken" with a capital B. This will cause the handler to return false in CanReadToken(), causing WIF to believe it doesn't have a handler registered for this token type. XML元素区分大小写,而实际元素是带有大写B的“ BinarySecurityToken”。这将导致处理程序在CanReadToken()中返回false,从而使WIF认为它没有为此令牌类型注册的处理程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM