How to pass default credentials in Windows Authentication - c#

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.

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.

TFS API TF30063: You are not authorized to access http://

I have an asp.net site on IIS using windows authentication (pass through) and I am trying to connect to the TFS API programmatically.
When I run it on my dev machine all is fine but once the site is on IIS I keep getting {"TF30063: You are not authorized to access http://mytfsserver."}
I have debugged the live site and it seems like it always takes the user as "NT SYSTEM" instead of the actual logged in user.
If I put my account details for the application pool it works as expected.
Any idea on how I can bypass this?
Code where it fails:
Uri collectionUri = new Uri(rootWebConfig.AppSettings.Settings["TFS_TEST_URI"].Value); //TEST ENV
tpc = new TfsTeamProjectCollection(collectionUri, CredentialCache.DefaultNetworkCredentials);
tpc.Authenticate();
workItemStore = tpc.GetService<WorkItemStore>();
You are hitting a standard active directory double hop authentication issue.
You have two options:
Username & password - if you ask the user to physically enter their username and password you can authenticate as them.
Kerberos - if you enable and configure Kerberos you can enable passthrough authentication. You need properly configured SPN: http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx
I would go with kerberos tokens. It's a pain to configure but works a treat. Your only other alternative is to run your web app on the TFS server and bypass double hop.

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

SharePoint search web service error (NTLM) when called from HttpHandler

Here is my scenario: I have a SharePoint site I am working on, and it is on one server farm. In this site, I have created an HttpHandler that uses a SharePoint search webservice that is located on a different server. So that looks something like this:
SharePoint Server A, where my site lives
Has a service reference to SharePoint search web service on Server B
Has an http handler that uses the service reference to call the search service
SharePoint Server B, where the search service lives
My code looks like this:
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
QueryServiceSoapClient _queryService = new QueryServiceSoapClient(binding, new EndpointAddress("http://easearch.ea.com/_vti_bin/search.asmx"));
_queryService.ClientCredentials.Windows.AllowNtlm = true;
_queryService.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
_queryService.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
//_queryService.ClientCredentials.Windows.ClientCredential = new NetworkCredential("MyUsername", "MyPassword", "MyDomain"); //This is the only way it seems to work
//NetworkCredential userCredential = CredentialCache.DefaultCredentials.GetCredential(_queryService.Endpoint.ListenUri, "NTLM");
//_queryService.ClientCredentials.Windows.ClientCredential = userCredential;
string status = _queryService.Status();
If I use this code from a console application on my dev box, it works as expected. But when I try to use the same code from my http handler, it gives the error
The HTTP request is unauthorized with
client authentication scheme 'Ntlm'.
The authentication header received
from the server was 'NTLM'.
I've tried a number of different combinations of the code above and the only one that works from my HttpHandler is when I directly provide my credentials. Anyone have any ideas?
Thanks.
NTLM cannot delegate credentials to a remote server.
This is known as the "double hop" issue. http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx
You'll have to configure Kerberos. Basically:
Configure SharePoint to use Kerberos (in "authentication provider" in central administration)
Create a SPN for SharePoint on your application pool account (with command line "setspn")
Create a SPN for the website runnong on server B on the application account running this site
Configure delegation between the 2
Yes, Kerberos is not that easy to put in place...

WCF windows credentials

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();

Categories