The main idea:
I have windows application (maybe IIS site, maybe standalone) that
natively accepts Kerberos authentication and impersonates user.
Kerberos token sent by client to app already has information about
user's groups SIDs, user's SID, etc.
On each request, from
HttpContext.Current.User I get information about user's groups'
SIDs, user SID, translate it to 'plaintext' and pass to non-windows
backend (as header, for example).
Backend (which can not do kerberos)
can read claims added by App from proxied request and send answer, which will be
passed to app and then to user (backend->app->user)
Well, what's wrong with this concept?
Why I can not find any existing apps that can work similar way?
The only thing I found is FASTCGI\CGI, which sets REMOTE_USER variable, but this is not enough - frontend had Kerberos with huge amount of data which is dropped by the way to backend.
I'm asking this question on the back of a previous question I raised, as the scope of the question has changed somewhat but that might be worth reading first for background info.
I'm trying to programatically obtain data out of our Dynamics CRM instance, using a single set of admin credentials within a Node powered Express app. This Express app is hosted on a separate server outside of our network where CRM is hosted. The app will then request, process and serve CRM data back to any logged in user who has access (controlled by roles/permissions within the app), meaning an end user only has to login into the Express app.
From my web browser, if I visit our on-premise CRM endpoint: https://my.crm.endpoint, I get prompted for a username and password.
If I provide correct credentials, I am authenticated and have full access to the CRM, allowing me to query the API.
Example
https://my.crm.endpoint/api/data/v8.2/contacts?$select=fullname,contactid
This returns a lovely JSON object containing all the data I want :)
NOW! Under the covers, I can see that it is using NTLM to authenticate, of which I have little knowledge :/ Having read up a little and watched a few YouTube videos, I have a basic understanding of the challenge/response mechanism but I'm still unsure as to how to proceed.
NB: I have read this from Microsoft which describes the mechanism, but doesn't give any specific examples. I don't even know what hashing algorithm should be used, or what headers to set etc.
Question Can anyone provide any sort of detail as to how I can authenticate with our CRM using NTLM from a Web App (Express in my case)?
Steps I can see the browser making...
Visit https://my.crm.endpoint
302 Redirected to: https://fs.our.domain/adfs/ls/?wa=wsignin1.0&wtrealm=https%3a%2f%2fmy.crm.endpoint%2f&wctx=rm%3d1%26id%3dfaf0791c-6a3a-4c4e-9e69-9dfa8fd4c2e8%26ru%3d%252fdefault.aspx&wct=2018-04-20T10%3a12%3a37Z&wauth=urn%3afederation%3aauthentication%3awindows
Prompted for user credentials
** enter credentials**
A whole bunch of stuff happens here and I get a little lost but looks like it gets a couple of 401's then a POST is made to the https://my.crm.endpoint. Another 302 is shown, then finally a GET to the actual default.aspx page.
I then have access to CRM.
NB: Once authenticated, I can see three cookies that have been set and which are sent when querying the api example above. These cookies are MSISAuth, MSISAuth1 and ReClientId.
If I'm missing any crucial info, please let me know and I'll provide what I can!
UPDATE
I have just installed httpntlm module and attempted to authenticate using this...
let httpntlm = require('httpntlm');
httpntlm.get({
url: 'https://my.crm.endpoint',
username: '<my.email#address.com>',
password: '<mypassword>',
workstation: '', // unsure what to put here if anything?
domain: '' // unsure what to put here if anything?
}, function (err, res){
if(err) return err;
console.log(res.headers);
console.log(res.body);
});
The response I get is this...
{ location: 'https://fs.our.domain/adfs/ls/?wa=wsignin1.0&wtrealm=https%3a%2f%2fmy.crm.endpoint%2f&wctx=rm%3d1%26id%3d93a4c6fd-5b17-4a2b-965f-07af5e96b08f%26ru%3d%252fdefault.aspx&wct=2018-04-20T14%3a08%3a00Z&wauth=urn%3afederation%3aauthentication%3awindows',
server: 'Microsoft-IIS/8.5',
req_id: '298acefc-53aa-46fa-96c4-e5d8762b1fd2',
'x-powered-by': 'ASP.NET',
date: 'Fri, 20 Apr 2018 14:08:00 GMT',
connection: 'close',
'content-length': '397' }
<html><head><title>Object moved</title></head><body>
<h2>Object moved to here.</h2>
</body></html>
Anyone able to shed any light on what I actually need to be doing?! :-/
UPDATE 2
Following #markgamache comment, and having read the suggested docs, we are indeed using WS-Fed! As the Wa=signin1.0 parameter informs the browser to pop up a login box, does this make it impossible to achieve this programmatically, without additional user interaction?
Based on my following understanding:
You are using CRM on premises with claims authentication (ADFS). This means that when an user accesses CRM, the user is redirected to ADFS for authentication (if the user is in the internal network, by default ADFS uses integrated Windows authentication) and then the user is redirected back to CRM.
You must call a CRM endpoint from an external (node.js) application. That call is NOT "client side" (i.e. via browser/javascript) but "server side" (i.e. from the web server hosting the application)
The ideal solution would be to apply here the S2S (server to server) scenario which involves an application user in CRM which in turn is used to call a CRM API using the OAuth client credentials flow (client id + secret). Problem is, as far as I know, currently the application user concept is only supported in CRM online, not on premises.
So then you can try one of these 3 options:
Despite the fact that you are using claims authentication in CRM, you can still use integrated Windows authentication (IWA). How? If you check the CRM IIS site, you must have an HTTPS binding. If you add an HTTP binding (i.e. port 80 no host header), you can access http://CRM_Server_Name/api/data/v8.2/contacts using IWA. So in this scenario, the httpntlm module you already tried could work. Please note that CRM supports one HTTPS IIS binding and one HTTP IIS binding - so make sure to not to add more of one binding of each type.
Mimic (programmatically of course) the authentication flow you observed in the browser. What does this mean? Generate an IWA authenticated request to https://fs.our.domain/adfs/ls/?wa=wsignin1.0&wtrealm=https%3a%2f%2fmy.crm.endpoint%2f&wauth=urn%3afederation%3aauthentication%3awindows. ADFS will authenticate you and will give you some cookies. You will need to store those cookies to make a subsequent request to https://my.crm.endpoint/api/data/v8.2/contacts. Not a great solution but should work.
Use OAuth. Problem is that as I described at the beginning, the ideal OAuth flow for this scenario (client credentials) is not available for CRM on prem as far as I know. So then you must use the Authorization Code Grant flow, described here. First you will need to register an ADFS application and then again, you will need to make several HTTPS calls (one of them will be a call to the ADFS IWA authentication endpoint) to finally obtain a token that you can use to make calls to the CRM endpoint.
that is a redirect to an ADFS server for claims based authentication. That page, or the next redirect, will ask you to authenticate with either cert, forms, or windows integrated (NTLM or Kerberos). If you pass auth, your browser will be given a token to send to https://my.crm.endpoint. The URL suggest the claims will be via WS*. https://blogs.technet.microsoft.com/askpfeplat/2014/11/02/adfs-deep-dive-comparing-ws-fed-saml-and-oauth/
I've been reading for the last hour but it's still not clear for me how to automatically authenticate the current windows user in my node js application.
On my office PC, I'm already authenticated with my AD user when I access our company portal in Chrome (as it was added as a trusted sites). So the main question for me is what do I have to do to automatically detect/authenticate the user in my nodejs app if I add my site to the trusted sites? I'm pretty sure the browser must do half of the job as it probably sends some kind of data (hash) in the request, based on which the application must authenticate the user. I suspect this is the "www-authenticate: negotiate" header as I noticed this sends a hash in the request when I access the portal.
So far, the only tracks I'm still investigating are:
https://gist.github.com/charlesdaniel/1686663
But it's still not very clear for me how this automatic authentication works and what are the leads I should follow next. The entire process is still unclear to me
I appreciate any advices on this or at least a mid-level explanation on what happens behind the scenes when I access a page in Chrome and it automatically authenticates me. Thanks
We are implementing CA Site minder on external server for single sign on.
We did all necessary configuration on our server as well as on policy server.
When I hit my URL request get interrupted by ISAPI Filter and Site Minder Replace it with Log in Page Then I put credentials and click log in.
This request goes to policy server and after authenticating site minder redirect me to original url that I hit early on but somehow i am not getting SMSESSION Cookie.
I check FRT log and found that cookie is there in Request Header which mean site minder able to generate and pass the cookie to request but not set in Response header So its getting removed from response.
I tried to find why its getting removed or response not setting SMSESSION Cookie but not able to find any reason.
I am using Integrated pipeline mode and the same setup is working fine with classic mode but since my application is MVC I can't use that and i have to use integrated mode.
The SMSESSION cookie is not provided to the application from SiteMinder. It is initialized in the client browser after login and should be included when the authenticated request arrives back at your application.
I suggest monitoring the client side to ensure the SMSESSION is received after login and sent back out in the application request.
I'm developing an extension that, as part of its processing, needs to access the user's message headers. Since they aren't contained in the HTML, a call is made to a servlet running in our server, which is hosted by Amazon Web Services, that connects to the Gmail IMAP server using the user's credentials. However, the first time the user runs the extension, Google sends a warning email to the user asking if it's OK to let the connection happen and blocks the connection until the user OKs it.
Is there any way for the user to OK the connection in advance and if not, how can else I get at the headers?