2

I am trying to get saml token by passing certificate authentication following this article How to pass a certificate to WSTrust to get Saml Token

I am getting following error when I make a call like this

var token = factory.CreateChannel().Issue(rst) as GenericXmlSecurityToken;

Unable to cast object of type 'System.Security.Cryptography.DSACryptoServiceProvider' to type 'System.Security.Cryptography.RSA'

I tried cryptoconfig solution mentioned in this article https://dusted.codes/how-to-use-rsa-in-dotnet-rsacryptoserviceprovider-vs-rsacng-and-good-practise-patterns

It didn't solve the problem

Here is the complete stack trace

Server stack trace: 
 at System.Security.Cryptography.RSAPKCS1SignatureFormatter.SetKey(AsymmetricAlgorithm key)
at System.Security.Cryptography.SignatureDescription.CreateFormatter(AsymmetricAlgorithm key)
at System.Security.Cryptography.RSAPKCS1SignatureDescription.CreateFormatter(AsymmetricAlgorithm key)
at System.IdentityModel.Tokens.X509AsymmetricSecurityKey.GetSignatureFormatter(String algorithm)
at System.IdentityModel.SignedXml.ComputeSignature(SecurityKey signingKey)
at System.ServiceModel.Security.WSSecurityOneDotZeroSendSecurityHeader.CompletePrimarySignatureCore(SendSecurityHeaderElement[] signatureConfirmations, SecurityToken[] signedEndorsingTokens, SecurityToken[] signedTokens, SendSecurityHeaderElement[] basicTokens, Boolean isPrimarySignature)
at System.ServiceModel.Security.WSSecurityOneDotZeroSendSecurityHeader.CreateSupportingSignature(SecurityToken token, SecurityKeyIdentifier identifier)
at System.ServiceModel.Security.SendSecurityHeader.SignWithSupportingToken(SecurityToken token, SecurityKeyIdentifierClause identifierClause)
at System.ServiceModel.Security.SendSecurityHeader.SignWithSupportingTokens()
at System.ServiceModel.Security.SendSecurityHeader.CompleteSecurityApplication()
at System.ServiceModel.Security.SecurityAppliedMessage.OnWriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota)
at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
at System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message, Boolean shouldRecycleBuffer)
at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at System.ServiceModel.Security.IWSTrustContract.Issue(Message message)
at System.ServiceModel.Security.WSTrustChannel.Issue(RequestSecurityToken rst, RequestSecurityTokenResponse& rstr)
at System.ServiceModel.Security.WSTrustChannel.Issue(RequestSecurityToken rst)
at TestClient.Program.GetSamlToken() 

Here is the code

private static string GetSamlToken()
    {
        "Requesting identity token".ConsoleYellow();
        var stsBinding = new WS2007HttpBinding();
        stsBinding.Security.Mode = SecurityMode.TransportWithMessageCredential;
        stsBinding.Security.Message.EstablishSecurityContext = false;
        stsBinding.Security.Message.NegotiateServiceCredential = false;
        stsBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate; 

        var factory = new WSTrustChannelFactory(
           stsBinding,
           "https://sometestservice.com/service");
        factory.TrustVersion = TrustVersion.WSTrust13;
        factory.Credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, System.Security.Cryptography.X509Certificates.StoreName.My,
            System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, "<cert_thumbprint_removed>");


        var rst = new RequestSecurityToken
        {
            RequestType = RequestTypes.Issue,
            KeyType = KeyTypes.Bearer,
            TokenType = TokenTypes.Saml2TokenProfile11,
            AppliesTo = new EndpointReference("urn:webapisecurity")
        };

        var token = factory.CreateChannel().Issue(rst) as GenericXmlSecurityToken;
        return token.TokenXml.OuterXml;
    }

What am I missing?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Esen
  • 973
  • 1
  • 21
  • 47
  • who ever downvoted, care to explain why? – Esen May 09 '18 at 03:05
  • Not really an answer but what version of .NET are you using because what you are using has been deprecated as stated [here](https://msdn.microsoft.com/en-us/library/microsoft.identitymodel.protocols.wstrust.wstrustchannelfactory.aspx). – CodingYoshi May 09 '18 at 03:35
  • my application is in .net 4.6.1 – Esen May 09 '18 at 11:33

2 Answers2

1

Just goes to show the amount of legacy assumptions in core libraries. It seems that you have to create your own extension of X509AsymmetricSecurityKey ,X509SecurityToken, SecurityTokenProvider and ClientCredentialsSecurityTokenManager like described in How to: Change the Cryptographic Provider for an X.509 Certificate's Private Key.

Gerrit
  • 861
  • 6
  • 11
1

Recently had same issue. The OAuth2 library uses a different cryptography provider for one framework vs another.

see line 30 here

Our solution was to change our .dll from 4.61 to NetStandard.

JM.
  • 678
  • 12
  • 23