Setting up ADFS for Dynamics CRM - dynamics-crm

I'm in the process of setting up IFD for CRM, and can't get past the internal login part of the claims based setup. I can browse both the adfs and crm metadata. When I try to browse to the internal crm url (https://internalcrm3.XXX.com:447/crm2013) I get prompted for credentials to adfs ("Enter username and password for htts://adfs3.xxx.com"). The url has changed to the adfs url (https://adfs3.xxx.com/adfs/ls/wia?....) at this point upon the login failure. There are no errors in the adfs event long, not sure where to check for this failure. The crm site worked prior to me setting up claims based authentication. I'm using windows 2012r2, I'm running crm on port 447.
Fiddler shows a 200 from internalcrm3, and a 200 for adfs3 (it shows adfs3 is on 443, but I haven't set up anything in IIS for this, as it's the 2012r2 version of adfs)
If I browse https://adfs3..com/adfs/ls/idpinitiatedsignon, I am prompted and can login wit the same credentials I'm trying above.

Related

Trouble configuring ADFS + OWA on Exchange Server 2019

Overview:
We're trying to configure SSO for OWA on Exchange 2019 server (on-premise), using ADFS. When going to https://mail.domain.com/owa we're experiencing multiple redirects between ADFS and OWA before we get an error in ADFS, followed by an error in the Windows Event logs that says:
Encountered error during federation passive request.
Additional Data
Protocol Name:
wsfed
Relying Party:
https://mail.domain.com/owa/
Exception details:
Microsoft.IdentityServer.Web.InvalidRequestException: MSIS7042: The same client browser session has made '6' requests in the last '0' seconds. Contact your administrator for details.
at Microsoft.IdentityServer.Web.Protocols.PassiveProtocolHandler.UpdateLoopDetectionCookie(WrappedHttpListenerContext context)
at Microsoft.IdentityServer.Web.Protocols.PassiveProtocolHandler.ProcessCommonCookiesInLastAuthenticationStage(ProtocolContext context)
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.SendSignInResponse(WSFederationContext context, MSISSignInResponse response)
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.Process(ProtocolContext context)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.ProcessProtocolRequest(ProtocolContext protocolContext, PassiveProtocolHandler protocolHandler)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)
Steps to reproduce:
Install Exchange Server 2019
Install ADFS and configure SSO exactly following the steps outlined on the following article (click here)
Navigate to https://mail.domain.com/owa.
Troubleshooting so far:
Confirmed that ECP and OWA External URLs match the audiences set in Powershell.
Confirmed that the user I'm attempting to sign in as is able to authenticate using FBA.
Confirmed that OWA is working as expected.
Servers + configuration:
Exchange Server 2019 15.02.0221.017 configured with a self-signed certificate
ADFS 4.0 configured with a self-signed certificate
Question(s):
Where can I go to get the OWA logs detailing why OWA is redirecting back to ADFS?
Is there anything in the above-linked article that's incorrect?
After a bit more testing we found that if we used IE11, the problem went away. The problem only existed for Chrome or Edge Chromium.
We decided to update to Exchange 2019 CU10, and there were no further issues.

Not able to capture request response for CRM Dynamics 365 app using Jmeter

While system proxy is set with Jmeter, CRM Dynamics 365 app is prompting for credentials repeatedly until it gives "HTTP 401.1 - Unauthorized: Access is denied" error at last. Without the proxy, users can access the CRM application at ease over browsers. Following steps are already taken, but no luck yet.
Jmeter root certificate is installed
Domain admin credentials are used for login
For authentication, NTLM service provider is set at IIS
Any help is appreciated!
In recorder advanced tab , switch Http request implementation to Java and try again.
If it doesn’t work, investigate wether it’s ntlm or keeberos.
Alternatively you can start authenticating without proxy setuo and once done, you switch browser to use jmeter proxy.
You can record test cases over BlazeMeter then import them into JMeter. That is worked for me.

Why does CRM Online return 401 unauthorized in my scenario?

I am trying to implement server-to-server integration with Dynamics CRM Online 2016 and BizTalk 2013 R2. I am using the WebHttpBinding to call the CRM web API, which requires a bearer token supplied as an http header:
Authorization: Bearer [base64string]
I have written a client message inspector which calls Azure AD using ADAL to acquire an access token. This is secured with a client assertion certificate, which is assigned to the registered app in our AD tenant:
var token = context.AcquireTokenAsync(this.ResourceUri, assertionCert).Result;
ResourceUri is https://[myorganisation].crm4.dynamics.com
assertionCert is a ClientAssertionCertificate created using the app registration application ID and an x509 certificate in the machine certificate store that is registered to the app as a KeyCredential
This 'works' in that it returns a token and I can decode this token to inspect the claims - there are a fair number of them, I have no way of telling whether this is the set of claims that CRM requires.
The AD app registration is configured with delegated permissions to the CRM instance.
I have set the application ID in the CRM local user to that of the app registration.
Upon calling the webAPI and supplying this token, CRM responds with 401 unauthorized.
I have repeated the same process in a powershell script and in PostMan, all of which appear to show the same behaviour.
What else am I supposed to do to make CRM accept my access token?
edit #1: Tried hardcoding the authority URI to https://login.windows.net/[my-tenant-id]/oauth2/token rather than what comes out of dynamically acquiring the authority through AuthenticationParameters - this is the same value except ending with /authorization instead of /token. This makes zero difference.
edit #2: An administrator I am working with pointed out to me that the application user I am expecting to use had no user roles assigned - this has been amended to have a role which should allow API access, but this also made no difference.
edit #3: Set oauth2AllowImplicitFlow to true in the manifest for the app registration. This doesn't make any difference.
edit #4: Made some progress by creating a new app registration, this time as a Native app rather than a web app. I managed to get a token using a client secret, and this was accepted - BUT when assigning a certificate to the app, and presenting a ClientAssertionCertificate as before, I get the response from the authority:
Error validating credentials. AADSTS50012: Client is public so a client_assertion' should not be presented.
WHY? What does 'Client is public' mean? Just work!
Hrrrmph!
Turns out that the original situation I had tried and failed with, now works.
Web application registration with delegated permissions to CRM Online
Install a client certificate on the client machine, and register this same certificate to the app using New-AzureADApplicationKeyCredential
Link the app registration to a CRM Application User created for this purpose (they are fundamentally different to interactive users) - n.b. this screen is not easy to find
Call AcquireTokenAsync() from ADAL
Just works
I am at a loss to explain why this didn't work the first time I tried it, as CRM doesn't supply any information as to why token validation failed.

Impersonation in ASP.NET web application does not work when running on IIS

I am working on ASP.NET 4.0 MVC3 web application that works in intranet environment. The application makes use of Windows authentication. Its application pool is run by domain user that has spn set on a domain controller. Authentication works using Kerberos (on IE and Firefox after some additional configuration).
Now I want to upload files to sharepoint, but it's important for me to upload the file as the user currently logged in into the application (so the file is created on Sharepoint with his/her credentials).
I have the following code in ResourceExists(Uri uri) function:
'...
Dim identity As System.Security.Principal.WindowsIdentity = HttpContext.User.Identity
Dim impersonationContext = identity.Impersonate()
response = request.GetResponse()
impersonationContext.Undo()
'...
This works when running locally, but when I deploy to the server I get the exception:
System.Net.WebException: The remote server returned an error: (401) Unauthorized.\r\n at WebDav.WebDavClient.ResourceExists(Uri uri)\r\n at Website.Website.WebdavController.Upload(HttpPostedFileBase file, UploadViewModel vm)
I read something about passing on the credentials, that is not possible with NTLM, but I am sure I am using Kerberos (I checked the headers with wireshark and fiddler) and I see the following:
Authorization: Negotiate YIIFpQYGKwYBBQUCoIIFmTCCBZWgJDAiBgkqhkiC9x...
Any ideas why the impersonation does not work when running on the IIS server?
I found the answer here:
http://support.microsoft.com/kb/810572
"Kerberos does not work in a load-balanced architecture and IIS drops back to NTLM authentication. Because you cannot use NTLM for delegation, any applications or services that require delegation do not work. For more information, click the following article number to view the article in the Microsoft"
And that was exactly the case. I tried now with another machine that is not load-balanced and it works.
The only thing that still surprises me is that ImpersonationLevel of the identity is still Impersonate not Delegate...
After setting <identity impersonate="true"/> in your web.config try the following:
using (((WindowsIdentity)User.Identity).Impersonate())
using (var client = new WebClient { Credentials = CredentialCache.DefaultNetworkCredentials })
{
string result = client.DownloadString("http://sharepoint");
}
you need to configure your site correctly in IIS for impersonation to work.
see Configure ASP.NET Impersonation Authentication (IIS 7)

IIS 7 and windows authentication from outside the web server's domain

I've deployed my site in IIS 7, and can browse to it fine on the web server.
I've set it to windows authentication (only), and when browsing from outside the domain, I want to be challenged for credentials, and gain access when entering a domain\username & password combination that exists in the AD.
401 - Unauthorized: Access is denied due to invalid credentials. My iis logs
I put a dummy site in IIS and set it to anonymous, I can browse to this no problem also.
I checked that windows auth was installed/set up on the web server, and it is.
What set of config parameters do I need to get this working?
*yes, I know I should use some sort of custom authentication provider with accounts stored in a database, but I don't want to go through that yet.
Thanks for any advice, words of wisdom.
I think your only option is to enable basic authentication. The user should then enter the full domain\username with the password. Beware though that basic authentication uses just base64 which can be very easily decoded. So if you enable basic authentication you have to use SSL/TLS as well.
In Internet Explorer, you can get it to prompt you by: Internet Options > Security > Custom level > User authentication > Logon > Prompt for username and password.

Resources