My application uses Net 5.0 Microsoft.AspNetCore.ApiAuthorization.IdentityServer and IdentityServer4. If Windows Authentication is enabled in IIS, it issues an NTLM challenge to acquire a WindowsPrincipal from the HttpContext.User as described in the IdentityServer documentation: https://docs.identityserver.io/en/latest/topics/windows.html. My implementation is very similar though not exactly the same - it falls back to an in-app sign-in form, if Windows Authentication is not enabled in IIS.
This works fine as long as Anonymous Authentication is enabled in IIS, but not if Anonymous Authentication is disabled. To be precise:
Anonymous and Windows Authentication enabled: This works, user is signed in using username recovered from the WindowsPrincipal
Anonymous Authentication only enabled: This works, user signs in via the sign in form
Windows Authentication only enabled: This does not work, and this is what my question is about
Firstly, when Windows Authentication is enabled, there is this difference:
If Anonymous Authentication is disabled, there is an automatic negotiation taking place for all requests. This means that the browser and IIS automatically handles the NTLM challenge and negotiation. As a result, the HttpContext of the initial request arriving in the application already has an authenticated Windows Principal assigned to the HttpContext.User.Identity
If Anonymous Authentication is enabled, then this automatic negotiation does not take place and the application needs to handle the NTLM negotiation itself to get the authenticated WindowsPrincipal (as indeed described in the IdentityServer4 documentation in the link above)
The above is my understanding, please correct me if I am wrong.
Regardless of alternative 1 or 2, the application looks up the name of the WindowsPrincipal in IdentityServer (the Net 5.0 SignInManager) and - if found - does an automatic signin. This works, there is a correct redirect to the IdentityServer callback, and subsequently a redirect to the return url with a Token with all the necessary claims - all honky-dory.
The problem appears when the application running in the browser then makes a request to the IdentityServer userinfo endpoint. Again, no problem if Anonymous Authentication is enabled. But if Anonymous Authentication is disabled, then this request triggers a Windows Authentication 401 challenge causing the browser to prompt for (windows) credentials.
This challenge persists and does not accept any valid Windows credentials. Cancelling the challenge results in a 401, with the response header asking for a NTLM negotiation:
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
Importantly, this request to the userinfo does contain a valid bearer token, so the user has been authenticated and a valid token has been issued. It seems like the userinfo endpoint in IdentityServer4 requires Anonymous Authentication to be enabled.
Is there any way out of this? Or is it impossible to use IdentityServer4 in IIS without Anonymous Authentication?
Related
I develop an authentication by extrenal idps in the my application. For while I support two idps using OpenId Connect protocol: Azure AD and Okta. My login page has widget for entering user's credentials (for built-in users and for domain users imported from Active Directory) and two buttons: "Login with Microsoft" and "Login with Okta".
First time user is redirected to login page and he attempts to sign in by Okta (or Azure AD). If he has already signed in Okta (or Azure AD) before attempt he will be signed in my app autmatically without entring his credentials (SSO in action). But if he signed out from my app, the next time he will try to sign in by Okta he will be redirected to Okta consent page and required to enter his credentials.
Why do second and next attempts require user's credentials but not lead to automatic sign in?
Is this SSO concept?
I develop on Asp.net MVC and use OWIN (Katana).
Thanks!
A likely reason the user is signed out of the identity provider is that your code is intentionally doing that when you call SignOut.
For example, if you are calling:
HttpContext.GetOwinContext().Authentication.SignOut(AuthTypes.Okta, AuthTypes.Cookies);
You are explicitly saying that you want to trigger sign-out for AuthTypes.Cookies (which probably clears your app's own session cookies) and AuthTypes.Okta (which probably includes redirecting to Okta to end the session and clear cookies over there as well).
If you only want to end the session with your app (but not necessarily end the user's session with the identity provider), when you call SignOut, you should only indicate your app's authentication types:
HttpContext.GetOwinContext().Authentication.SignOut(AuthTypes.Cookies);
After this, when the user accesses the app again, the app will not consider the user signed in (because when the user's browser accesses the app, it will not be presenting any session cookies). However, if the user were to be sent off to Okta or Azure AD again, the identity provider's own session cookies for that user will still be there, and they will be able to SSO with no extra prompts.
Note: I'm making a few assumptions about how AuthTypes.Okta and AuthTypes.Cookies are configured, since that wasn't included in the question.
In an enterprise applications, how to seamless sign in to application without login page by reading the windows AD credentials using Spring boot and React.
Ex: if i login to my desktop using organisation AD credentials, can my spring boot react application read that and auto sign in with out login popup?
Yes that is possible. There are few necessary steps you need to perform.
Whenever user hits the application url, check Authorization header and verify if the kerberos ticket is present.
If the ticket is not present, respond with http header WWW-Authenticate and value Negotiate. Make sure the http status should be SC_UNAUTHORIZED(401). (note: usually spring kerberos filters should do it for you. If you are not using Spring kerberos filters, then you have to do this negotiation manually as stated above.
When browser receives this response, it understands that the application requires kerberos token. To ensure that the browser sends the kerberos token, trust the application url in browser settings. Check this link for exact steps.
Once browser sends the kerberos token, use Spring Secuiryt Kerberos libraries to accept the token and extract user principal out of it.
New to Azure AD... So please don't be too harsh if this is off target. :-)
Technology Stack - Latest Angular 2 with C# Middle tier and latest .Net Framework.
Ideally, What we want to do is use Azure AD B2C to store user credentials and to do the authentication - but we want our 'own' forms on our site to do the login Forms capture and logging - then pass the credentials through an API (REST?) Call (using MS Graph SDK?) to Azure AD B2C and then check the call return for the Authorization content message.
Couple of reasons - control of the application flow, Logging and the "flickering of the URL" (i.e. going from our site URL to login.microsoft... URL and then back to our sites URL).
Is this doable without doing a hack?
Thank you in advance for your help and patience!
You are looking for the "Resource Owner Password Credentials".
This is not currently supported for Azure AD B2C, but you can give user feedback to the B2C team that you want this through the Azure Feedback Forum: Add support for Resource Owner Password Credentials flow in Azure AD B2C and headless authentication in Microsoft Authentication Library
You should also see updates at that location if and when they implement this feature.
The resource owner password credentials flow is now in preview.
In Azure Active Directory (Azure AD) B2C, the following options are
supported:
Native Client: User interaction during authentication happens when
code runs on a user-side device. The device can be a mobile
application that's running in a native operating system, such as
Android, or running in a browser, such as JavaScript.
Public client flow: Only user credentials, gathered by an application, are sent in
the API call. The credentials of the application are not sent.
Add new claims: The ID token contents can be changed to add new claims.
The following flows are not supported:
Server-to-server: The identity protection system needs a reliable IP
address gathered from the caller (the native client) as part of the
interaction. In a server-side API call, only the server’s IP address
is used. If a dynamic threshold of failed authentications is exceeded,
the identity protection system may identify a repeated IP address as
an attacker.
Confidential client flow: The application client ID is
validated, but the application secret is not validated.
From here.
Note that one disadvantage of doing what you're requesting is precisely that you can do "login forms capture and logging", so your application has a chance to see the credentials and perhaps take copies of them; thus your users have to trust you to behave.
The normal web-based flow means that your application doesn't need to be trusted; it never even sees the password at all.
I'm writing an AngularJS SPA application which calls Rest full web service. Back-end is being written on JAX-RS, deployed on Tomcat 7. I'm using HTTPS, SSL for transferring data from SPA to JAX-RS
requirements
I have to make LDAP authentication. (I will send username & password to web service and it should make authentication)
I have to do user's session management (because, when authenticated user sends request to web service, user doesn't have to authenticate again)
problems
I think there are two options for doing LDAP authentication:
Make LDAP authentication using core java http://docs.oracle.com/javase/jndi/tutorial/ldap/security/ldap.html
Use Spring security (I'm not familiar with it and not sure if it's possible. I think I should send username & password to rest service. Rest service will have spring security library injected and it'll be possible to use authentication functionality. Am I right?)
Manage user sessions. Once user is authenticated, it should be saved somewhere, so that user can do operations until its logon is not expired.
How can I do it?
Which way should I choose? How should I make LDAP authenticating and session management?
Can anyone give any suggestion or example links?
So,
LDAP Authentication using JNDI works just fine, you could also use the neat UnboundID LDAP Java API. A simple LDAP Bind example can be found here: https://code.google.com/p/ldap-sample-code/source/browse/trunk/src/main/java/samplecode/bind/SimpleBindExample.java .
Note also that you could use a Node.JS module as your backend, the Passport.JS Authentication framework for example, provides lots of features/capabilities relative to authentication and Federation (i.e., do things like 'Login with Google', etc...). See: passportjs.org.
On the Angular/frontend side,your best bet is to use a JWT token. It's all explained in detail with examples here: http://code.tutsplus.com/tutorials/token-based-authentication-with-angularjs-nodejs--cms-22543.
In essence:
your backend Authentication REST should return a JWT Token in the response, once the user successfully binds to LDAP. This Token would contain some user data, and should be encrypted (see link above).
Your Angular App should set that token as a cookie on the client Browser ("set-cookie" response header) upon successful login (so in the Controller of your Login view).
The Client will then present that cookie/JWT Token on every request it makes to your app.
Your app will then need to validate the token presented on every request (in the controller of your SPA). You may also want to add the user authentication data to your $scope so you can use it in your view.
Hope it helps...
I have a basic question regarding SAML2. Typical flow is that user requests a resource from SP that is protected. SP checks if the user has a security context (say cookie ?), if it does not find a security context, it constructs the AuthRequest and then redirects the browser to the IdP. Now IdP likewise first checks if the user has an existing security context. How does the IdP do this? Does the IdP also use a cookie for this purpose?
Yes. For SAML Web SSO Profile the session is almost always kept as a cookie in the browser at the IDP and SP. However, there are no rules on how to manage this. The IDP could choose to not keep an active session and prompt the user to login for each SSO transaction.
Ian
#Ian - Great Answer. However if the IDP does not maintain a session cookie [B/W Browser and Identity Provider (IDP)] than you miss out on a significant benefit of single sign on (SSO). The SSO User Experience (UX) feature that would be lost is described in the following scenario:
0) Assume IDP is registered with Google Apps and Salesforce.
1) Open Browser. NOTE: SAML is browser based. You need a browser for SAML to work.
2) Try to go to Google Apps; (you have no existing session cookie [B/W Browser and Google Apps]) who then Re-directs you to the IDP.
3) You sign on with your valid IDP credentials.
4) the IDP then stores a session cookie [B/W Browser and IDP] in your browser. (This is the step that #Ian mentioned can be skipped by the IDP)
5) The IDP then redirects you back to Google Apps (via HTTP POST) with SAML token embedded in the POST. You are now in Google Apps. (Now you have a session cookie [B/W Browser and Google Apps] stored on your browser)
5) Try to go to Salesforce.
6) Salesforce sees you have no active session cookie[B/W Browser and Salesforce], so they redirect you to the IDP.
* here is my point of added User Experience (UX) *
7) The IDP will look for a session cookie [B/W Browser and IDP], if the IDP is configured to not store maintain one you have to enter your Single Sign On (SSO) aka IDP Credentials AGAIN.
Discussion on Step7: Entering the SSO credentials for each separate service an extra-step times the number of services you are using. I think the main draw of the implementation is to enter credentials only once and get access to everything (the topic of security aside). However if the IDP does not store a session cookie [B/W Browser and IDP] you are still only using one set of credentials (instead of separate credentials for each service), so life is still easier.
#Ajava - You seem to be confused as to how cookies are used. I hope you can follow my steps above and get better idea of how cookies are used with SAML.
Here is also a good link i found that explains cookies: http://lifehacker.com/5461114/fact-and-fiction-the-truth-about-browser-cookies