一般的注意事項
私たちは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 クライアントで同じことを開始することです。
前もって感謝します!