如何将 JWT 令牌与 WCF 和 WIF 一起使用? [英] How to use JWT tokens with WCF and WIF?

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

问题描述

我们正在使用 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.

这就是我想要实现的目标:

This is what I want to achieve:

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

我无法进行第三步.

  • 我正在使用具有 TransportWithMessageCredential 安全模式的 ws2007FederationHttpBinding.该消息包含一个 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 元素中,它本身被包装在 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 ---

JustDecompile 之后,在进一步读取 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.

我分叉了 samples repo,如果您愿意,可以看看.以下是相关项目:

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

  • SelfHost (Minimal)sources 文件夹中.这是 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 服务上启动新实例,然后在 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.

以下是链接:

现在大家玩得开心:-)

Everybody have fun, now :-)

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

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