WCF windows credentials - c#

my client on server A calls a service on B which calls a service on C.
In order to get the call working from B->C I have to do this:
channel.Credentials.Windows.ClientCredential =
new System.Net.NetworkCredential("WndowsUserName", "WindowsPassWord");
IService1 service = channel.CreateChannel();
etc...
the user name and password are the windows credentials used from A->B
Of course I do not want to hardcode this so how can I do this without hardcoding?
I tried, with no luck:
WindowsIdentity callerWindowsIdentity =
ServiceSecurityContext.Current.WindowsIdentity;
using (callerWindowsIdentity.Impersonate())

Use
System.Net.CredentialCache.DefaultNetworkCredentials
property. It represents the authentication credentials for the current security context in which the application is running. Details can be found here.

It seems to be a "double hop" authentication problem.
In short, NTLM doesn't alllow more than one "hop" with it's credentials (token). So user authenticates on server 1 with it's token, and in turn, server 1 tries to send the token to server 2. This won't work, unless Kerberos deleguation is allowed between server 1 and 2.
More details here : http://weblogs.asp.net/owscott/archive/2008/08/22/iis-windows-authentication-and-the-double-hop-issue.aspx
And here : http://blogs.msdn.com/nunos/archive/2004/03/12/88468.aspx

Perhaps the class
System.Net.CredentialCache
could be helpfull ...
It has the DefaultCredentials and DefaultNetworkCredentials properties that you can use.
Offcourse, you will have to make sure that your application runs under the credentials that you want (that is , the credentials of the current user).
This can be done by calling
AppDomain.CurrentDomain.SetPrincipalPolicy (PrincipalPolicy.WindowsPrincipal);
At the start of your program.
Then, when you initialize the WCF service, you can use the DefaultNetworkCredentials provided by the CredentialCache.
channel.Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
IService1 service = channel.CreateChannel();

Related

Error C# Dynamics CRM: The authentication endpoint Username was not found on the configured Secure Token Service

We're facing an error while trying to deploy a WCF webservice in a server. While connecting to Dynamics (CRM on premise) we get this error: The authentication endpoint Username was not found on the configured Secure Token Service
If we test it locally, it's working but if the deploy the webservice in the server, this is the code which performs the login:
Uri serviceUri = new Uri(OrgServiceUri);
proxy = new OrganizationServiceProxy(serviceUri, null, authCredentials, null);
proxy.EnableProxyTypes();
_service = (IOrganizationService)proxy;
Guid userid = ((WhoAmIResponse)_service.Execute(new WhoAmIRequest())).UserId;
if (userid != Guid.Empty)
{
Console.WriteLine(userid);
return true;
}
else
{
return false;
}
Any guess?
Thank you!!
First, make sure the user you have set up as the service account has Read/Write access to CRM and has a security role assigned that enables it to log into CRM remotely.
Next, make sure the Username endpoint is configured in the ADFS deployment that this CRM org is using:
Log onto the ADFS server and open the ADFS management console. Go to ADFS > Service > Endpoints
You’ll see a list of endpoint URLs here. Find the one for /adfs/services/trust/13/username of type WS-Trust 1.3
Make sure that this endpoint has “Yes” set for both the Enabled and Proxy Enabled settings.
If you have to make a change to this endpoint, after making the change re-start the ADFS server and the CRM server, then try to register again.
Lastly, if the above looks okay, it could be a resolution or routing issue blocking the connection. Make sure that there are external DNS entries for the path to your ADFS server. Also, make sure that your firewall permits external access to the ADFS server. If you are able to, try to use a computer that is outside of your domain to navigate directly to the ADFS server to test its accessibility.
This is a problem with the same error as you, and it has been resolved, you can refer to: The authentication endpoint Username was not found on the configured Secure Token Service
Finally we found it was an issue with ADFS service per-se, networking related, since it wasnt able to connect SSO site. After fixing that, it started to work as a charm.
If you are running ADFS on-prem, the ADFS windows service might be stopped (Because of a power failure / unexpected server restart).
You just need to start it.

How to pass default credentials in Windows Authentication

I'm developing UWP application using C#.net and it has WCF service with Windows Authentication enabled. I struggling to pass default NetworkCredential after consume a service call using Add service reference option.
Please find below my examinations.
When I pass correct windows authentication credentials, it is working as expected.
var service = new ServiceReference.Service1Client();
service.ClientCredentials.Windows.ClientCredential =new NetworkCredential("pradeep","****");
var test = await service.GetDataAsync(1);
but, I wanted pass default network credentials while using my service methis
var service = new ServiceReference.Service1Client();
service.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
var test = await service.GetDataAsync(1);
I also tried below option.
service.ClientCredentials.Windows.ClientCredential = (NetworkCredential)CredentialCache.DefaultCredentials;
When I pass default credentials. I'm getting below exception.
The HTTP request is unauthorized with client authentication scheme
'Negotiate'. The authentication header received from the server was
'Negotiate, NTLM'.
I tested same service call with default NetworkCredential in WPF application which is working as expected.
In order to pass the default credentials for the WCF Windows Authentication in UWP by using the System.Net.CredentialCache.DefaultNetworkCredentials, first please make sure that you have added the Enterprise Authentication and Private Networks(Client & Server) capabilities as following:
For the Enterprise Authentication capability, it is because that Windows domain credentials enable a user to log into remote resources using their credentials, and act as if a user provided their user name and password. The enterprise Authentication special capability is typically used in line-of-business apps that connect to servers within an enterprise.
For the Private Networks(Client & Server) capability, it is because that currently in Windows Runtime we can only pass the default credential in the Intranet. For the Internet we have to use the Username and Password as credential.
For more information about the Capabilities, please check:
https://msdn.microsoft.com/en-us/library/windows/apps/hh464936.aspx .
After that please try to use your Computer name or Fully Qualified Computer name instead of the IP address for your WCF Services like this: http://YourComputerName:YourPortNumber/Service1.svc.
At last please use another computer as client to test the WCF Windows Authentication in UWP with the System.Net.CredentialCache.DefaultNetworkCredentials, then it should work fine.
Thanks.

How to provide credentials for Digest Authentication in Silverlight 5 and WCF

We currently have a Silverlight 5 Out-of-browser application calling a number of WCF webservices.
I wish to secure these services using Digest authentication, however I'm failing to get Silverlight to actually submit the credentials.
// step one - find and remove default endpoint behavior
var defaultCredentials = channelFactory.Endpoint.Behaviors.Find<ClientCredentials>();
channelFactory.Endpoint.Behaviors.Remove(defaultCredentials);
// step two - instantiate your credentials
ClientCredentials loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = "myusername";
loginCredentials.UserName.Password = "mypassword";
// step three - set that as new endpoint behavior on factory
channelFactory.Endpoint.Behaviors.Add(loginCredentials); //add required ones
When I use this code, the client first makes and anonymous request, the server responds with a 401 result code, and Silverlight then prompts me for credentials.
In other parts of the application I make a WebRequest to a Rest service, and in this instance I can supply credentials for Digest authentication and it works.
What is even more strange, is that if I first make a WebRequest with credentials, Silverlight seems to cache those credentials and uses them for the WCF call. But after a few seconds those credentials become invalid, and subsequent WCF calls present the prompt again.
Is there any way to use Digest authentication with WCF in Silverlight 5?

WCF same Identity as on client?

For an experimenting project I'am struggling with a service. The client is an ASP.NET MVC 4 and the service will be build with WCF. For now all the systems are in a trusted subsystem so SSL/certificates is not necessarily.
The problem I'am currently dealing with is: Is het possible when I create a new GenericIdentity like:
IIdentity newIdentity = new GenericIdentity("Test", "Custom authentication");
string[] newRoles = { "TestRole" };
IPrincipal testPrincipal = new GenericPrincipal(newIdentity, newRoles);
Thread.CurrentPrincipal = testPrincipal;
It is possible to have the created user when I'am on the WCF service calling the following code:
ServiceSecurityContext.Current.WindowsIdentity;
Or
ServiceSecurityContext.Current.PrimaryIdentity;
Or
Thread.CurrentPrinicpal;
I get the user which I created in the client? Or do I have to write a WCF extensibility for this?
I'm currently using a WsHttpBinding and security mode Transport and clientCredentialType: Windows. Maybe something wrong about the configuration?
On server side (WCF), the security context will have the username value you have used to authenticate to the service.
This means, that if you have defined on client side windows authentication, WCF will find the security context filled with the username of the windows identity you used.
In order for you to authenticate to the servive with windows account, you can use the following code
on client side :
channelFactory.Credentials.Windows.ClientCredential =
new NetworkCredential(username, password, domain);
Having used this code, you can access the identity on server side with the below code :
OperationContext.Current.ServiceSecurityContext.PrimaryIdentity
In general, try to be explicit on client side authentication info. Currently, you seem to
be simply using the default behavior of windows authentication schema, by setting identity
on current thread.
I hope this helps.
I discovered to achieve this automatically in WCF that you must specify a certificate...
In the messages that are sent to the WCF service I created a few properties with the information in the datacontracts that is necessary to create a GenericPrinicpal (in this the username en the roles). Because I have an trusted subsystem I don't want to authenticate the user on each WCF-service (to much overhead for my scenario). See also Trusted subsystem
With this I created a WCF extension that implemented a parameter inspector and with reflection I set the credentials from the CurrentPrincipal in the specified properties of the contract. For more information about parameter inspectors and how to apply it

How to do Authentication between a webservice and a mobile phone?

I want to make a windows mobile 6 cellphone application. This application will talk to a web service that I want to make.
I don't know much about web services and programming app for phones so I got a couple questions.
How do I do authentication? Like my user loads up my app and goes to the login page. They type in their credentials. This gets sent to the server and authenticated. Now what do I send back? Is there some sort of FormsAuthentication?
After they log in do I have to keep doing checks to see if they are logged in? Like in asp.net mvc I have AuthorizeAttributes on all my tags. That way no one can just type in the url to that action method and be able to access it. But since this is an application I am not sure if they could (say) go your login form (first form) and then somehow, without logging in, get to your main form (the one after the login form).
Do web services have Authorize tags like asp.net mvc? Since I probably need something along those lines to ensure no one types in their web brower my webservice path and get access to all those methods I made in it.
I am making a asp.net mvc application right now and when the user types their credentials on my site. It is sent what I am guessing is clear text? to the server hashed and then checked. I know maybe one day when I can afford it maybe to get ssl to make it more secure.
So my question how about with sending the credentials from the phone to the server will it be less secure than what I have for my website right now? About the same? What can be done to make it more secure (is it SSL again?).
Thanks
You could also use SOAP headers to pass around user credentials or the authentication token. You can find an article on how to do this on Authentication for Web Services (using SOAP headers), but to summarize, you create a header class:
using System.Web.Services.Protocols;
public class AuthHeader : SoapHeader
{
public string Username;
public string Password;
}
You define a public property on the web service
public AuthHeader AuthenticationInfo;
and add some attributes to any web methods you would like to be only accessible to authenticated users:
[SoapHeader ("AuthenticationInfo", Required=true)]
[WebMethod]
public string HelloSecretWorld()
{
if(!(AuthenticationInfo.UserName == "Hello" && AuthenticationInfo.UserName.Password == "World"))
throw new AuthenticationException();
return "Hello World";
}
The client code would look like:
MyWebService ws = new MyWebService();
ws.AuthenticationInfo = new AuthHeader {Username = "Hello", Password = "World"};
Console.Out.WriteLine(ws.HelloSecretWorld());
This way you don't need to modify the signatures of the methods to add authentication.
i've had to address this issue several times in connecting from hand held (Windows Mobile) applications to web services. The solution i've used is to create a cookie based on a hash of the user's login name and IP address once the authentication process has succeeded. e.g. User ID and pwd matches persisted credentials on the server. You then pass this cookie back to the client which will then be passed along with all web service requests for the rest of the session. e.g. The first parameter of any web method is the cookie.
pseudocode:
string cookie = webServiceInstance.Authenticate("userName", "password");
double balance = webServiceInstance.GetBalance(cookie, someId);
Of course you do want to use SSL so as to avoid passing your user id and pwd in plain text.

Categories