9

一般的注意事項

私たちはIdentityServer3を使用しており、これまでのところ非常に満足しています。
MS と Thinktecture OWIN ミドルウェアの両方の助けを借りて、MVC と ASP.NET Web API アプリケーションを非常に簡単に保護することができました。

私たちが取り組んでいるクライアントにはまだ多くの SOAP WCF サービスがあり、ここで行き詰っています。

セットアップ

私はうそをつくつもりはありません.WCFの経験はまったくありません.非常に基本的なシナリオでしか使用していません.basicHttpBinding、トランスポートなし、メッセージセキュリティを理解しています.

これは私が達成したいことです:

  • クライアントが IdentityServer から JWT アクセス トークンを取得する
  • どういうわけか、トークンは SOAP メッセージ ヘッダーで終了します。
  • WCF はトークンを読み取り、検証します
  • WCF はクレームを検査し、いくつかの基準に基づいて承認を実行します

3番目のステップが機能しません。

サーバーのセットアップ

  • セキュリティモードws2007FederationHttpBinding付きを使用しています。TransportWithMessageCredentialメッセージには a が含まれてBearerKeyおり、トークンのタイプはurn:ietf:params:oauth:token-type:jwt
  • このサービスは、 NuGet パッケージJwtSecurityTokenHandlerから追加した WIF ID パイプラインを使用します。System.IdentityModel.Tokens.Jwt

クライアントのセットアップ

  • STS によって発行された JWT トークンはBinarySecurityTokenXML 要素にラップされ、それ自体がGenericXmlSecurityElement
  • このトークンは、のパラメータとして使用されCreateChannelWithIssuedTokenますChannelFactory

何が起こるのですか

トークンは SOAP ヘッダーで検出され、 に渡されJwtSecurityTokenHandlerます。
しかし、例外がスローされます。

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 要素をさらに読み取るときにエラーが発生したようです。奇妙なのは、トークンが最後の要素であることです。メッセージ全体は次のようになります。

<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>スタック トレースから、トークンが適切に読み取られて処理されているため、最後の要素を読み取るときに例外をスローする必要があります。

再現

サンプル リポジトリをフォークしたので、気が向いたら見てみてください。関連するプロジェクトは次のとおりです。

  • SelfHost (Minimal)sourcesフォルダー内。これがSTSです
  • ソリューションではClients、WCF サービスはAPIsフォルダーにあります。
  • Clientsソリューションでは、WCF クライアントはプロジェクトConsole Client Credentials With Wcfです。

それを起動する最善の方法は、最初に STS を開始し、次にRight click -> Debug -> Start new instanceWCF サービスで開始し、次に WCF クライアントで同じことを開始することです。

前もって感謝します!

4

1 に答える 1

11

私はこの問題を解決できませんでしたが、IdentityServer の開発者の 1 人である Dominick Baier が回避策を見つけました。
彼は、例外は WCF のバグか、WCF とJwtSecurityTokenHandler. 彼は WCFが完了したと考えているため、誰かがそれを見てくれるとは思っていません。

彼の解決策は、JWT トークンを SAML トークンでラップすることです。次に、 をサブクラス化SamlSecurityTokenHandlerして元に戻し、 のインスタンスに対して検証しますJwtSecurityTokenHandler

リンクは次のとおりです。

みんな楽しんでね:-)

于 2015-07-02T15:31:27.727 に答える