/// <summary> /// Gets the <see cref="WsSerializationContext"/> to use when serializing the <see cref="WsTrustRequest"/>. /// </summary> /// <param name="trustRequest">The <see cref="WsTrustRequest"/> that will be serialized. /// <returns>The <see cref="WsSerializationContext"/> for the <see cref="WsTrustRequest"/>.</returns> private WsSerializationContext GetSerializationContext(WsTrustRequest trustRequest) { _ = trustRequest ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(trustRequest)); if (trustRequest.WsTrustVersion == WsTrustVersion.TrustFeb2005) { if (_wsSerializationContextTrustFeb2005 == null) { _wsSerializationContextTrustFeb2005 = new WsSerializationContext(trustRequest.WsTrustVersion); } return(_wsSerializationContextTrustFeb2005); } else if (trustRequest.WsTrustVersion == WsTrustVersion.Trust13) { if (_wsSerializationContextTrust1_3 == null) { _wsSerializationContextTrust1_3 = new WsSerializationContext(trustRequest.WsTrustVersion); } return(_wsSerializationContextTrust1_3); } else if (trustRequest.WsTrustVersion == WsTrustVersion.Trust14) { if (_wsSerializationContextTrust1_4 == null) { _wsSerializationContextTrust1_4 = new WsSerializationContext(trustRequest.WsTrustVersion); } return(_wsSerializationContextTrust1_4); } throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetResourceString(SR.WsTrustVersionNotSupported, trustRequest.WsTrustVersion.ToString()))); }
private void WriteSecurityTokenReference(XmlDictionaryWriter writer, SecurityTokenReference reference, bool attached) { var context = new WsSerializationContext(_version); if (attached) { WsTrustSerializer.WriteRequestedAttachedReference(writer, context, reference); } else { WsTrustSerializer.WriteRequestedUnattachedReference(writer, context, reference); } }
public override Claims ReadClaims(XmlDictionaryReader reader, WsSerializationContext serializationContext) { return(base.ReadClaims(reader, serializationContext)); }
/// Get a proof token from a WsTrust request/response pair based on section 4.4.3 of the WS-Trust 1.3 spec. /// How the proof token is retrieved depends on whether the requester or issuer provide key material: /// Requester | Issuer | Results /// ------------------------------------------------- /// Entropy | No key material | No proof token returned, requester entropy used /// Entropy | Entropy | Computed key algorithm returned and key computed based on request and response entropy /// Entropy | Rejects requester entropy | Proof token in response used as key /// No entropy | Issues key | Proof token in response used as key /// No entropy | No key material | No proof token /// </summary> /// <param name="request">The WS-Trust request (RST).</param> /// <param name="response">The WS-Trust response (RSTR).</param> /// <returns>The proof token or null if there is no proof token.</returns> internal static BinarySecretSecurityToken GetProofToken(WsTrustRequest request, RequestSecurityTokenResponse response, WsSerializationContext serializationContext, SecurityAlgorithmSuite algorithmSuite) { // According to the WS-Trust 1.3 spec, symmetric is the default key type string keyType = response.KeyType ?? request.KeyType ?? serializationContext.TrustKeyTypes.Symmetric; // Encrypted keys and encrypted entropy are not supported, currently, as they should // only be needed by unsupported message security scenarios. if (response.RequestedProofToken?.EncryptedKey != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new NotSupportedException(SR.GetResourceString(SR.EncryptedKeysForProofTokensNotSupported)), EventLevel.Error); } // Bearer scenarios have no proof token if (string.Equals(keyType, serializationContext.TrustKeyTypes.Bearer, StringComparison.Ordinal)) { if (response.RequestedProofToken != null || response.Entropy != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.BearerKeyShouldNotIincludeAProofToken)), EventLevel.Error); } return(null); } // If the response includes a proof token, use it as the security token's proof. // This scenario will occur if the request does not include entropy or if the issuer rejects the requester's entropy. if (response.RequestedProofToken?.BinarySecret != null) { // Confirm that a computed key algorithm isn't also specified if (!string.IsNullOrEmpty(response.RequestedProofToken.ComputedKeyAlgorithm) || response.Entropy != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.RSTRProofTokenShouldNotHaveAComputedKeyAlgorithmOrIssuerEntropy)), EventLevel.Error); } return(new BinarySecretSecurityToken(response.RequestedProofToken.BinarySecret.Data)); } // If the response includes a computed key algorithm, compute the proof token based on requester and issuer entropy. // This scenario will occur if the requester and issuer both provide key material. else if (response.RequestedProofToken?.ComputedKeyAlgorithm != null) { if (!string.Equals(keyType, serializationContext.TrustKeyTypes.Symmetric, StringComparison.Ordinal)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.ComputedKeyProofTokensAreOnlySupportedWithSymmetricKeyTypes)), EventLevel.Error); } if (string.Equals(response.RequestedProofToken.ComputedKeyAlgorithm, serializationContext.TrustKeyTypes.PSHA1, StringComparison.Ordinal)) { // Confirm that no encrypted entropy was provided as that is currently not supported. // If we wish to support it in the future, most of the work will be in the WSTrust serializer; // this code would just have to use protected key's .Secret property to get the key material. if (response.Entropy?.ProtectedKey != null || request.Entropy?.ProtectedKey != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new NotSupportedException(SR.GetResourceString(SR.ProtectedKeyEntropyIsNotSupported)), EventLevel.Error); } // Get issuer and requester entropy byte[] issuerEntropy = response.Entropy?.BinarySecret?.Data; if (issuerEntropy == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.ComputedKeyProofTokensRequireIssuerToSupplyKeyMaterialViaEntropy)), EventLevel.Error); } byte[] requestorEntropy = request.Entropy?.BinarySecret?.Data; if (requestorEntropy == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.ComputedKeyProofTokensRequireRequesterToSupplyKeyMaterialViaEntropy)), EventLevel.Error); } // Get key size int keySizeInBits = response.KeySizeInBits ?? 0; // RSTR key size has precedence if (keySizeInBits == 0) { keySizeInBits = request.KeySizeInBits ?? 0; // Followed by RST } if (keySizeInBits == 0) { keySizeInBits = algorithmSuite?.DefaultSymmetricKeyLength ?? 0; // Symmetric keys should default to a length corresponding to the algorithm in use } if (keySizeInBits == 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.NoKeySizeProvided)), EventLevel.Error); } return(new BinarySecretSecurityToken(Psha1KeyGenerator.ComputeCombinedKey(issuerEntropy, requestorEntropy, keySizeInBits))); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new NotSupportedException(SR.GetResourceString(SR.OnlyPSHA1ComputedKeysAreSupported)), EventLevel.Error); } } // If the response does not have a proof token or computed key value, but the request proposed entropy, // then the requester's entropy is used as the proof token. else if (request.Entropy != null) { if (request.Entropy.ProtectedKey != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new NotSupportedException(SR.GetResourceString(SR.ProtectedKeyEntropyIsNotSupported)), EventLevel.Error); } if (request.Entropy.BinarySecret != null) { return(new BinarySecretSecurityToken(request.Entropy.BinarySecret.Data)); } } // If we get here, then no key material has been supplied (by either issuer or requester), so there is no proof token. return(null); }
internal static WCFSecurityToken CreateGenericXmlSecurityToken(WsTrustRequest request, WsTrustResponse trustResponse, WsSerializationContext serializationContext, SecurityAlgorithmSuite algorithmSuite) { // Create GenericXmlSecurityToken // Assumes that token is first and Saml2SecurityToken. RequestSecurityTokenResponse response = trustResponse.RequestSecurityTokenResponseCollection[0]; // Get attached and unattached references GenericXmlSecurityKeyIdentifierClause internalSecurityKeyIdentifierClause = null; if (response.AttachedReference != null) { internalSecurityKeyIdentifierClause = GetSecurityKeyIdentifierForTokenReference(response.AttachedReference); } GenericXmlSecurityKeyIdentifierClause externalSecurityKeyIdentifierClause = null; if (response.UnattachedReference != null) { externalSecurityKeyIdentifierClause = GetSecurityKeyIdentifierForTokenReference(response.UnattachedReference); } // Get proof token WCFSecurityToken proofToken = GetProofToken(request, response, serializationContext, algorithmSuite); // Get lifetime DateTime created = response.Lifetime?.Created ?? DateTime.UtcNow; DateTime expires = response.Lifetime?.Expires ?? created.AddDays(1); return(new GenericXmlSecurityToken(response.RequestedSecurityToken.TokenElement, proofToken, created, expires, internalSecurityKeyIdentifierClause, externalSecurityKeyIdentifierClause, null)); }