ADFS Token generation working in C# but NOT in VB.Net - c#

Below is code in c# to get token from server.
The code in C# is working fine and I am able to receive the token from server but when I write same syntax in VB.net then I get exception.
The framework for the code is same "4.6.2". App config of both the code are same.
var sEndPointAddress = "url";
WS2007HttpBinding binding = new WS2007HttpBinding();
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory(binding, new EndpointAddress("https://IPAddress/adfs/services/trust/13/usernamemixed"));
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
trustChannelFactory.Credentials.UserName.UserName = "username";
trustChannelFactory.Credentials.UserName.Password = "password";
RequestSecurityToken requestToken = new RequestSecurityToken(RequestTypes.Issue);
requestToken.AppliesTo = new EndpointReference(sEndPointAddress);
WSTrustChannel tokenClient = (WSTrustChannel)trustChannelFactory.CreateChannel();
var token = tokenClient.Issue(requestToken);
I have converted the same code in VB.Net but I am receving exception error.
The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.
Below is code in VB.Net
Dim sEndPointAddress As String = "url"
Dim binding As New WS2007HttpBinding()
binding.Security.Message.EstablishSecurityContext = False
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName
binding.Security.Mode = SecurityMode.TransportWithMessageCredential
Dim trustChannelFactory As New WSTrustChannelFactory(binding, New EndpointAddress("https://IPAddress/adfs/services/trust/13/usernamemixed"))
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13
trustChannelFactory.Credentials.UserName.UserName = "username"
trustChannelFactory.Credentials.UserName.Password = "password"
Dim requestToken As New RequestSecurityToken(RequestTypes.Issue)
requestToken.AppliesTo = New EndpointReference(sEndPointAddress)
Dim tokenClient As WSTrustChannel = CType(trustChannelFactory.CreateChannel(), WSTrustChannel)
Dim token As Object = tokenClient.Issue(requestToken)

Related

How to access MongoDB using GSSAPI authentication mechanism?

I am trying to connect to the MongoDB server through a ssl certificate using c#. I am getting a System.TimeoutException (A timeout occurred after 30000ms selecting a server using the CompositeServerSelector).
I started with connection via MongoClientSetting object. Here is the code:
MongoClientSettings settings = new MongoClientSettings();
settings.MaxConnectionLifeTime = new TimeSpan(12, 0, 0);
settings.UseSsl = true;
settings.VerifySslCertificate = false;
var cert = new X509Certificate2("mongoDBCAFile.cer");
settings.SslSettings = new SslSettings{
ClientCertificates = new[] { cert }
};
settings.Servers = new[]{
new MongoServerAddress("xyz1.intranet.companyname.com", 12345),
new MongoServerAddress("xyz2.intranet.companyname.com", 12345)
};
settings.ReplicaSetName = "replicaName";
var cred = MongoCredential.CreateGssapiCredential("username#intranet.companyname.com").WithMechanismProperty("SERVICE_NAME", "servicename");
settings.Credential = cred;
var client = new MongoClient(settings);
var database = client.GetDatabase("DatabaseName");
var collection = database.GetCollection<BsonDocument>("CollectionName");
//This is the place of error
var count1 = collection.CountDocuments(new BsonDocument());
I tried playing around with ConnectTimeout, SocketTimeout, and wTimeOut but the error was same.
I also tried doing the same thing using the connection string as mentioned here but I wouldn't figure out how to create a connection string with these many parameters.
Found the solution.
The issue was with authentication of the user with external server. MongoDB server was waiting for the clearance from this external server, but Because the authentication was never successfully, MongoDB always lead to System.TimeoutException.
Here is the fix code.
settings.ReplicaSetName = "replicaName";
SecureString pwd = new NetworkCredential("intranet/userName", "myPassword").securePassword;
var cred = MongoCredential.CreateGssapiCredential("username/intranet.companyname.com", pwd).WithMechanismProperty("SERVICE_NAME", "serviceName").WithMechanismProperty("CANONICALIZE_HOST_NAME", "true");
settings.Credentials = cred;

Receiving error "ID3037: The specified request failed adfs" when requesting token from adfs server

Below is the code I'm using to request "Symmetric" token type from Adfs and I receive the error as mentioned in the title.
A quick google search points out that, it is because of the absence of token signing certificate but I do have it defined in the Adfs.
Do I need to explicitly assign it to "Relying party" or having it in ADFS 2.0 works?
Please can anybody point me to right direction or have somebody knows step to associate token signing certificate to relying party if it is required?
WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential);
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.EstablishSecurityContext = false;
binding.BypassProxyOnLocal = true;
binding.UseDefaultWebProxy = true;
System.ServiceModel.Security.WSTrustChannelFactory factory = new System.ServiceModel.Security.WSTrustChannelFactory(
binding, new EndpointAddress(userNameMixedRequest.GetUserNameMixedUrl));
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.SupportInteractive = false;
factory.Credentials.UserName.UserName = "domain\username"
factory.Credentials.UserName.Password = "password"
System.IdentityModel.Protocols.WSTrust.RequestSecurityToken request = new System.IdentityModel.Protocols.WSTrust.RequestSecurityToken
{
RequestType = RequestTypes.Issue,
AppliesTo = new EndpointReference(userNameMixedRequest.ClientUri),
KeyType = KeyTypes.Symmetric
};
System.ServiceModel.Security.IWSTrustChannelContract channel = factory.CreateChannel();
channel.Issue(request)

.NET SOAP does not send BASIC auth in request header

Wanting to communicate with a SOAP webservice, I had C# classes created by SvcUtil.exe from the wsdl file.
When sending the Request below to a secure server (HTTPS with BASIC auth) I receive a System.ServiceModel.Security.MessageSecurityException and when checking the HTTP request by having traffic go though a Burp proxy I see that no BASIC auth information is passed. Is anything missing for the SOAP request in the C# code or what could be the problem that the BASIC auth does not work?
var binding = new WSHttpBinding();
binding.MessageEncoding = WSMessageEncoding.Mtom;
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Name = "BasicAuthSecured";
SearchServicePortClient searchClient = new SearchServicePortClient(binding, new EndpointAddress("https://myUrl:Port/myService"));
searchClient.ClientCredentials.UserName.UserName = "username";
searchClient.ClientCredentials.UserName.Password = "pw";
query soap = new query();
//...
queryResponse response = searchClient.query(soap);
Thanks in advance
This is another approach, don't know if it is the best though
using (var client = _clientFactory.GetClient())
{
var credentials = Utils.EncodeTo64("user123:password");
client.ChannelFactory.CreateChannel();
using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
{
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials;
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
//operation
client.Send(request);
}
}
Try to use TransportWithMessageCredential:
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;

The HTTP request is unauthorized with client authentication scheme 'Anonymous' (Write via C# basic authentication)

I get server error when I trying connect to webService. Do you know why?
Error
{System.Collections.Generic.SynchronizedReadOnlyCollection}
Code
BasicHttpBinding basicbinding = new BasicHttpBinding();
basicbinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
basicbinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
basicbinding.Name = "HTTP_Port";
WSPI.InvoiceCheck_OutClient invoiceCheck_OC = new WSPI.InvoiceCheck_OutClient(basicbinding, new EndpointAddress(new Uri("http://example.example.eu:51200/XISOAPAdapter/MessageServlet?senderParty=&")));
invoiceCheck_OC.ClientCredentials.UserName.UserName = "Login";
invoiceCheck_OC.ClientCredentials.UserName.Password = "Password";
WSPI.InvoiceCheck invoiceCheck = new WSPI.InvoiceCheck();
WSPI.InvoiceCheck_OutRequest invoiceCheck_OR = new WSPI.InvoiceCheck_OutRequest();
WSPI.InvoiceConfirm invoiceCheck_IC = new WSPI.InvoiceConfirm();
invoiceCheck.InvoiceNo = "1000000";
invoiceCheck.IssueDate = "2014-01-01";
invoiceCheck.VatNo = "88090302342";
invoiceCheck.Username = "SuperRafal";
string response = invoiceCheck_OC.InvoiceCheck_Out(invoiceCheck).Response.ToString();
Code working correct there was a problem with link :) Sorry

Creating Headers (wsse) Section of WCF Client Programmatically in C#

how do make a the following section of Service Settings of app.config in C# programmatically:
<client>
<endpoint address="https://someServiceUrl"
binding="basicHttpBinding" bindingConfiguration="Contact"
contract="ServiceReference.PostingWebService" name="PostingWebServicePort">
<headers>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>someusername</wsse:Username>
<wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>somepassword</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</headers>
</endpoint>
</client>
I have managed to generate binding section (not included above) and endpoint section from C#. I am unable to create the headers section.
The error that comes up is: (this is because I don't have headers section when I generate everything from C#)
This service requires <wsse:Security>, which is missing.
the headers section is important, as if I exclude it from the config and run the code using config it also gives the above error.
I don't want to use web.config/app.config. I have to run every thing from C#. (the above app.config works fine, but I want to do that same through C#)
NOTE: THE UPDATES BELOW ARE BASED ON THE SOLUTION PROVIDED BELOW PLEASE GO THROUGH THE COMMENTS ON THE SOLUTION BELOW, FOR BETTER UNDERSTANDING
UPDATE 1: (programmatically using BasicHttpBinding first)
BasicHttpBinding binding = new BasicHttpBinding();
binding.Name = "Contact";
binding.CloseTimeout = TimeSpan.FromMinutes(1);
binding.OpenTimeout = TimeSpan.FromMinutes(1);
binding.ReceiveTimeout = TimeSpan.FromMinutes(10);
binding.SendTimeout = TimeSpan.FromMinutes(1);
binding.AllowCookies = false;
binding.BypassProxyOnLocal = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MaxBufferSize = 524288;
binding.MaxBufferPoolSize = 524288;
binding.MaxReceivedMessageSize = 524288;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = System.Text.Encoding.UTF8;
binding.TransferMode = TransferMode.Buffered;
binding.UseDefaultWebProxy = true;
binding.ReaderQuotas.MaxDepth = 32;
binding.ReaderQuotas.MaxStringContentLength = 65536;
binding.ReaderQuotas.MaxArrayLength = 131072;
binding.ReaderQuotas.MaxBytesPerRead = 32768;
binding.ReaderQuotas.MaxNameTableCharCount = 131072;
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
binding.Security.Transport.Realm = "";
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Default;
CustomBinding customBinding = new CustomBinding(binding);
SecurityBindingElement element = customBinding.Elements.Find<SecurityBindingElement>();
// Remove security timestamp because it is not used by your original binding
//element.IncludeTimestamp = false; (element is NULL in my case)
EndpointAddress endpoint = new EndpointAddress("https://myserviceaddress");
PostingWebServiceClient client = new PostingWebServiceClient(customBinding, endpoint);
client.ClientCredentials.UserName.UserName = "myusername";
client.ClientCredentials.UserName.Password = "mypassword";
client.getActiveChannels(new getActiveChannels());
Using Custom Bindgin Directly:
SecurityBindingElement securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
securityElement.IncludeTimestamp = false;
TextMessageEncodingBindingElement encodingElement = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
HttpsTransportBindingElement transportElement = new HttpsTransportBindingElement();
CustomBinding customBinding = new CustomBinding(securityElement, encodingElement, transportElement);
EndpointAddress endpoint = new EndpointAddress("https://myserviceaddress");
PostingWebServiceClient client = new PostingWebServiceClient(customBinding, endpoint);
client.ClientCredentials.UserName.UserName = "myusername";
client.ClientCredentials.UserName.Password = "mypassword";
client.getActiveChannels(new getActiveChannels());
You don't have to configure header directly in this case because your scenario should be supported by BasicHttpBinding or CustomBinding directly.
If you need to configure it from C# you must create binding in code:
// Helper binding to have transport security with user name token
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
// Rest of your binding configuration comes here
// Custom binding to have access to more configuration details of basic binding
CustomBinding customBinding = new CustomBinding(binding);
SecurityBindingElement element = customBinding.Elements.Find<SecurityBindingElement>();
// Remove security timestamp because it is not used by your original binding
element.IncludeTimestamp = false;
EndpointAddress address = new EndpointAddress("https://...");
ProxyWebServiceClient client = new ProxyWebServiceClient(customBinding, address);
client.ClientCredentials.UserName.UserName = "...";
client.ClientCredentials.UserName.Password = "...";
Other solution is building custom binding directly instead of starting with basic binding:
SecurityBindingElemetn securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
securityElement.IncludeTimestamp = false;
TextMessageEncodingBindingElement encodingElement = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
HttpsTransportBindingElement tranportElement = new HttpsTransportBindingElement();
// Other configurations of basic binding are divided into properties of
// encoding and transport elements
CustomBinding customBinding = new CustomBinding(securityElement, encodingElement, transportElement);
EndpointAddress address = new EndpointAddress("https://...");
ProxyWebServiceClient client = new ProxyWebServiceClient(customBinding, address);
client.ClientCredentials.UserName.UserName = "...";
client.ClientCredentials.UserName.Password = "...";
Look at the accepted answer to this StackOverflow question. It shows how to programatically add client credentials to the proxy. It also shows adding the headers in the client endpoint configuration XML which I hadn't seen before.

Categories