如何在WCF和WIF中使用JWT令牌? [英] How to use JWT tokens with WCF and WIF?

查看:125
本文介绍了如何在WCF和WIF中使用JWT令牌?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用 IdentityServer3 ,到目前为止,对此我们感到非常满意.
在MS和Thinktecture OWIN中间件的帮助下,我们已经非常轻松地保护MVC和ASP.NET Web API应用程序.

We're using IdentityServer3 and have been very happy with it so far.
We've gotten to secure MVC and ASP.NET Web API applications very easily with the help of both MS and Thinktecture OWIN middlewares.

我们正在工作的客户端仍然有很多SOAP WCF服务,这就是我们遇到的障碍.

The client we're working for still has a lot of SOAP WCF services, and this is where we're getting stuck.

我不会说谎,我对WCF经验还很远,我只在非常基本的情况下使用过它-了解basicHttpBinding,没有传输或消息安全性.

I'm not gonna lie, I'm far from being experienced with WCF, I've only used it for very basic scenarios - understand basicHttpBinding, no transport nor message security.

这是我要实现的目标:

  • 客户端从IdentityServer获取JWT访问令牌
  • 以某种方式令牌最终出现在SOAP消息头中
  • WCF读取并验证令牌
  • WCF根据某些标准检查索赔并执行授权

我无法执行第三步.

  • 我正在将ws2007FederationHttpBindingTransportWithMessageCredential安全模式一起使用.该消息包含BearerKey,令牌的类型为urn:ietf:params:oauth:token-type:jwt
  • 该服务使用WIF身份管道,在其中添加了System.IdentityModel.Tokens.Jwt NuGet包中的JwtSecurityTokenHandler
  • I'm using a ws2007FederationHttpBinding with TransportWithMessageCredential security mode. The message contains a BearerKey and the token is of type urn:ietf:params:oauth:token-type:jwt
  • The service uses the WIF identity pipeline, in which I added the JwtSecurityTokenHandler from the System.IdentityModel.Tokens.Jwt NuGet package
  • 由STS发出的JWT令牌包装在BinarySecurityToken XML元素中,而XML元素本身包装在GenericXmlSecurityElement
  • 此令牌用作ChannelFactory
  • CreateChannelWithIssuedToken的参数
  • The JWT token issued by the STS is wrapped in a BinarySecurityToken XML element, itself wrapped in a GenericXmlSecurityElement
  • This token is used as a parameter of the CreateChannelWithIssuedToken of the ChannelFactory

在SOAP标头中找到令牌,并将其传递给JwtSecurityTokenHandler.
但是随后引发异常:

The token is found in the SOAP header and passed on to the JwtSecurityTokenHandler.
But then an exception is thrown:

System.ServiceModel.Security.MessageSecurityException: Message security verification failed. ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Xml.XmlBufferReader.GetChars(Int32 offset, Int32 length, Char[] chars)
   at System.Xml.XmlBufferReader.GetString(Int32 offset, Int32 length)
   at System.Xml.StringHandle.GetString()
   at System.Xml.XmlBaseReader.ReadEndElement()
   at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteFullPass(XmlDictionaryReader reader)
   at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
   at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessageCore(Message& message, TimeSpan timeout)
   at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout)
   --- End of inner exception stack trace ---

JustDecompiling之后,进一步读取SOAP标头中的XML元素时似乎出现了错误.奇怪的是令牌是最后一个元素.这是整个消息的样子:

After JustDecompiling, it looks like there's an error when further reading the XML elements in the SOAP header. What's strange is that the token is the last element. Here's what the whole message looks like:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <s:Header>
        <a:Action s:mustUnderstand="1">http://tempuri.org/IService/GetListOfStrings</a:Action>
        <a:MessageID>urn:uuid:5c22d4e2-f9b8-451a-b4ca-a844f41f7231</a:MessageID>
        <ActivityId CorrelationId="554fc496-7c47-4063-9539-d25606f186b0" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">1213dcd7-55b7-4153-8a6d-92e0922f76dd</ActivityId>
        <a:ReplyTo>
            <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
        <VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo90CpMlUwLBOmEPkZ5C8fRQAAAAAVWkkf2rJS0qImBv+Yx1recUXdbBLjThDkAMkwfW3/2AACQAA</VsDebuggerCausalityData>
        <a:To s:mustUnderstand="1">https://localhost.fiddler:44322/Service.svc</a:To>
        <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <u:Timestamp u:Id="_0">
                <u:Created>2015-05-21T06:41:45.362Z</u:Created>
                <u:Expires>2015-05-21T06:46:45.362Z</u:Expires>
            </u:Timestamp>
            <wsse:BinarySecurityToken ValueType="urn:ietf:params:oauth:token-type:jwt" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><!-- Removed --></wsse:BinarySecurityToken>
        </o:Security>
    </s:Header>
    <s:Body>
        <GetListOfStrings xmlns="http://tempuri.org/" />
    </s:Body>
</s:Envelope>

看起来没有什么畸形的东西.从堆栈跟踪中,由于正确地读取和处理了令牌,因此在读取</o:Security>结束元素时必须引发异常.

Doesn't look like there's something malformed or anything. From the stack trace, the exception must be thrown when reading the </o:Security> end element since the token was properly read and handled.

我分叉了示例存储库,以便您随意查看. 以下是相关的项目:

I forked the samples repo so you can have a look if you feel like it. Here are the relevant projets:

    sources文件夹中的
  • SelfHost (Minimal).这是STS
  • Clients解决方案中,WCF服务位于APIs文件夹中
  • Clients解决方案中,WCF客户端是Console Client Credentials With Wcf项目
  • SelfHost (Minimal) in the sources folder. This is the STS
  • In the Clients solution, the WCF service is in the APIs folder
  • In the Clients solution, the WCF client is the Console Client Credentials With Wcf project

启动它的最佳方法是先启动STS,然后在WCF服务上启动Right click -> Debug -> Start new instance,然后在WCF客户端上启动.

Best way to fire it up is to start the STS first, then Right click -> Debug -> Start new instance on the WCF service, then the same on the WCF client.

提前谢谢!

推荐答案

我没有解决此问题,但是IdentityServer的开发人员之一Dominick Baier找到了解决方法.
他认为该异常来自WCF中的错误或WCF与JwtSecurityTokenHandler之间的不兼容.由于他认为WCF已经完成,因此他不希望有人对此进行检查.

I didn't get to solve this problem but Dominick Baier, one of the developers of IdentityServer, found a workaround.
He thinks the exception comes from a bug in WCF or an incompatibility between WCF and the JwtSecurityTokenHandler. Since he considers WCF done, he doesn't expect someone to take a look at it.

他的解决方案是将JWT令牌包装在SAML令牌中.然后,通过对SamlSecurityTokenHandler进行子类化,将其取回并针对JwtSecurityTokenHandler的实例进行验证.

His solution is to wrap the JWT token in a SAML token. Then, by subclassing SamlSecurityTokenHandler, get it back and validate it against an instance of JwtSecurityTokenHandler.

以下是链接:

  • Dominick's blog post
  • Samples repo on GitHub where he put the code
  • Specific commit on GitHub

每个人都玩得开心,现在:-)

Everybody have fun, now :-)

这篇关于如何在WCF和WIF中使用JWT令牌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆