我所做的是这样的:
我创建了自己的响应消息版本,其中包含创建 GenericXmlSecurityToken 所需的位。这通常是从 WSTrustChannel 返回的内容,因此这似乎是正确的做法。值得庆幸的是,包装 JWT 的 GenericXmlSecurityToken 的大多数参数都是 null;我只需要序列化令牌(在服务中的 JWTSecurityTokenHandler 上使用 WriteToken 进行序列化)以及 validFrom 和 validTo 值。
客户端代码:
XmlElement element = document.CreateElement("wsse", "BinarySecurityToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
element.SetAttribute("ValueType", "urn:ietf:params:oauth:token-type:jwt");
element.SetAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
UTF8Encoding encoding = new UTF8Encoding();
element.InnerText = Convert.ToBase64String(encoding.GetBytes(jwtToken));
GenericXmlSecurityToken token = new GenericXmlSecurityToken(
element,
null,
validFrom,
validTo,
null,
null,
null);
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuedTokenType = "urn:ietf:params:oauth:token-type:jwt";
var factory2 = new ChannelFactory<IService1>(binding, new EndpointAddress("https://localhost:44300/Service1.svc"));
factory2.Credentials.SupportInteractive = false;
factory2.Credentials.UseIdentityConfiguration = true;
var proxy = factory2.CreateChannelWithIssuedToken(token);
var info = proxy.DoWork();
web.config 的相关部分:
绑定:
<ws2007FederationHttpBinding>
<binding>
<security mode="TransportWithMessageCredential">
<message issuedKeyType="BearerKey" establishSecurityContext="false" issuedTokenType="urn:ietf:params:oauth:token-type:jwt"/>
</security>
</binding>
</ws2007FederationHttpBinding>
身份模型部分:
<system.identityModel>
<identityConfiguration>
<audienceUris>
<add value="--audienceUri--"/>
</audienceUris>
<securityTokenHandlers>
<add type="--namespace--.CustomJWTSecurityTokenHandler, --my dll--" />
<securityTokenHandlerConfiguration>
<certificateValidation certificateValidationMode="PeerTrust"/>
</securityTokenHandlerConfiguration>
</securityTokenHandlers>
<issuerNameRegistry>
<trustedIssuers>
<add name="--issuer--" thumbprint="--thumbprint--"/>
</trustedIssuers>
</issuerNameRegistry>
</identityConfiguration>
</system.identityModel>
以及此问题中的 CustomJWTSecurityTokenHandler (我的场景仅需要 validIssuer 部分):如何使用对称密钥配置 Microsoft JWT?
我还没有看到在其他地方使用了issuedTokenType 属性,但我发现它对于让我的代码正常工作至关重要。如果没有它,我会收到此错误:“MessageSecurityException:找不到“Microsoft.IdentityModel.Tokens.JWT.JWTSecurityToken”令牌类型的令牌身份验证器。根据当前安全设置,无法接受该类型的令牌。”
作为一种解决方案,这可能有点过分了,但我认为它最大限度地减少了自定义代码的数量,并将其集中在我觉得更舒服的地方。
感谢user2338856 和leastprivilege 让我顺利完成任务!