I'm currently looking for a nice solution for the problem above. We'll probably run form authentication on the .NET one.
I have an ASP.NET MVC app running on a.mydomain.com and a Java based app running on b.mydomain.com.
What is the best approach so that I don't have to log in to each app. Say, when I log into the a.mydomain.com and then open the Java b.mydomain.com, and it will check and see that I'm already logged in?
Would the WCF AuthenticationService class work for this? Could I do an AJAX request from the JavaScript of b.mydomain.com to check if I'm logged in already in the .NET app?
As long as mydomain.com is not in the public suffix list ( http://publicsuffix.org/list/ ), a.mydomain.com can put a domain cookie for .mydomain.com
( note that you can only go down one level in putting cookie : a.b.mydomain.com can not put a .mydomain.com cookie )
The cookie will be sent to b.mydomain.com (as well as *.mydomain.com and mydomain.com) and can be used as a token to open a session. So be sure to control the whole *.myDomain.com subdomain and make it httpOnly and secured (https)
Response.SetCookie(new HttpCookie("myCookieName", "myCookieValue") { HttpOnly = true, Domain = ".myDomain.com", Secure=true });
Some parts of the Atlassian Crowd solution http://www.atlassian.com/software/crowd/overview are based on this cookie mechanism
So you might :
Enable forms authentication on a.domain.com
upon successfull login build a myToken cookie which value contains userId and hashed userId with hashing key known by a.myDomain.com and b.myDomain.com
set the cookie with domain .myDomain.com
when user enters b.myDomain.com, check the cookie server side (in java) for matching between userId and hashed value
if the cookie is correct, open session for user userId
Note that you won't be able to access the cookie client side (so no js cookie handling, except if it is server side js, for example nodejs)
Using a Java or .NET existing solution is not likely to function on the other platform. You need several capabilities:
Tracking the client with an identifier for recognition (session, cookie).
Have both the Java and .NET application be able to get the related information.
How can you do these?
This is actually quite easy. You're using the same domain so you can place a cookie on the browser for all domains, meaning that requests to a* and b* will both have the cookie sent to the server. Both Java and .NET have excellent facilities for cookie placement.
This is dependent on your back-end. What are the systems using for persistent storage? If you have something like a MySQL database which both systems are connected to, you can make a table with login information for each stored identifier for authentication. If you take this route, have some sort of time-out as well to invalidate old authentications.
If you have both those pieces of information, you can do the authentication on each system.
I recommend using one of enterprise sso protocols, Oauth2 or ws-federation. This gives you maximum flexibility in composing your services, you can not only federate these two but then, later, easily expand your application environment. Both protocols do not need apps to be on the same domain.
Although this could sound overcomplicated for your simple needs, you do it once and have the sso problem solved forever, no matter what happens in future to your applications.
Related
I Will try to describe this as detailed as possible.
For using the SPA, you need to be logged-in, every request is authenticated by JWT. Login is a simple form with Username and Password fields, which are sent to the server. On the server, there are two types of login (kinda) - AD and Password (determinated by the user type):
API check if username exists and determine its Type
a) if type is Password: Check if password matches the data in Database
b) if type is AD: verify password on the LDAP server
successful login returns generated JWT, which is used for all further requests.
This App is available all over the internet, not just inside the same network as the server.
I would like to have some kind of "automatic login" with Windows account (so you dont need to manually type the username/pass, but the SPA tries to login automatically when u open the Login page).
I tried many guides for something like this, but nothing seems to work properly.
I heard that Kerberos/Auth0 should do the work, but I dont know how to implement it. Also I would still need to get that JWT for further requests. Do I need some kind of Microsoft request? Azure? Anything else? (If is needed, I can create another IIS application just with Login controller).
I hope you understand what I mean, and will be able to help!
Most Modern Browsers speak SPNEGO
Simple and Protected GSSAPI Negotiation Mechanism (SPNEGO), often pronounced "spenay-go", is a GSSAPI "pseudo mechanism" used by client-server software to negotiate the choice of security technology.
It just so happens that one of those client-server security technologies it can speak is Kerberos. (Windows machines generally have kerberos availble by default.).
So to actually get .NET to use kerberos authentication you really need to enable delegation for IIS as that's what speaks to the browser.
I currently have a .net core application that uses Identity Server 4 to authenticate users. We have two different applications; an MVC portion of our site that users can login to, and a SPA that users have to login to as well. Is it possible to make it so that anytime the user logs out of one of those areas, that it logs out of both?
This is the main idea of Single Sign-On. Not only single login, but also single logout. Identity Server 4 fully support this, but you just need to configure both your clients (the MVC app and SPA) with their proper configurations. This is the official documentation about signing out. It works.
EDIT
PS: Have in mind that Identity Server does not invalidate the access token, once you are logged out. In other words - if you, by any chance, still have the access token, you will be able to use it, as long as it is valid (its validity period has not expired). This is why usually the access token is set to have a shorter lifetime.
There are 2 front channel ways to acheive this and I'd recommend using both.
1) Front channel log out which uses an endpoint registered against each client. When you sign out of IDS4 (assuming it's implemented properly) it will make a request to the registered endpoint for each app that was signed into during the current session. http://openid.net/specs/openid-connect-frontchannel-1_0.html
2) The session monitoring spec which uses a bit of javascript and cross-domain iframe magic to notify the client app when the user's session changes on the IDP. Using this you can immediately respond to changes and do any cleanup you need to. http://openid.net/specs/openid-connect-session-1_0.html
As mentioned in m3n7alsnak3's answer this will not invalidate any JWT access tokens (you can use the revocation endpoint to revoke refresh or reference tokens however). Therefore I'd recommend having the client applications to the best job they can of clearing up any state they can, i.e. clearing all cookies, session/local storage etc.
I am looking for single sign on for my application which is built on javascript (no server side language).
Requirement:
Agent log in to Windows (user integrated to Active directory)
Open my web page
Based on who logged in to windows, my application goes to AD and pull some user
specify data (eg email, phone)
How shall I go about it?
As per my understanding I will require ADFS for this.
So:
User goes to my web page
My web page calls some Web services or web application (which is build on c#)
That will authenticate against AD FS and get claim
Either get phone number and email in claim or get username and query AD for phone and email
Return the data to my web page (build on javascript)
It seems there something wrong in my understanding!!
Please suggest more appropriate solution based on my requirement
Frankly, I can't think of a way to make it work without a server side processing. This is because the ws-federation protocol ADFS uses is not just about returning claims.
It is about returing a SAML token. The token contains claims but what is most important about it is that it is signed using the XMLDsig. How are you going to validate the token is a first big question. But there are surely external libraries that allow that.
But then, such authentication can easily be bypassed by modifying scripts in the browser. This is because the ws-federation stops where you get the token and then it is up to you to exchange the token for the actual identity. And this won't work when processed only at the client side.
ADFS 3 does not support the OAuth2 implicit profile, which would be an option, but still you would need to verify the token on the server to avoid session fixation.
You can setup something like AuthorizationServer that supports Oauth2/OpenID Connect implicit profile
http://leastprivilege.com/2013/09/19/adding-oauth2-to-adfs-and-thus-bridging-the-gap-between-modern-applications-and-enterprise-back-ends/
Another option is to use something like Auth0 (Disclaimer: I work for Auth0) which also supports OAuth2/OpenID Connect implciit profile. In that case you wouldn't need ADFS, there is a connector/agent that you install on your network that does not require opening firewalls or anything and it supports implicit profile that is suited to JavaScript apps. This is an example of a single page app tutorial (if you create an account it will tailor the doc with your credentials):
https://docs.auth0.com/singlepageapp-tutorial
I have an ASP.NET solution that acts as the primary customer portal for my customers. On this website the users can log-in access their important financial information and more. The website uses a custom authentication scheme that checks the user's username (their email) and their password (salt-hashed) against a Users table in a local database.
I am building a new MVC.NET solution that is more of a web-app tool to be used by these same customers for ordering. I want to re-use the sign-on mechanism of the ASP.NET portal to authenticate users. The goal is to save the user from remembering two log-ins or even having to supply the same log-in twice.
What are my options for allowing users who sign on to the ASP.NET solution to then be auto authenticated to the MVC.NET solution? I've listed some ideas below but are these "bad" or is there a more elegant solution? I'd love your input.
Common Cookie I could create a common cookie that the ASP.NET site creates and the MVC.NET site looks for. But is that secure enough?
Token in Query String I could create a token id on the ASP.NET site that is stored in the local database and is then passed in the query string of the link to the MVC.NET site which takes the token id and validates it against the same database.
Hybrid A bit of both?
Other? Got a better idea?
I've recently done something quite similar (the major difference being that it was internal to the company rather than for external customers) using OpenId.
The implementation of OpenId for .NET is called DotNetOpenAuth which should be suitable for your purposes.
It did take me a while to implement; but it works very well, is very flexible, and extremely secure.
More information about openid (from Wikipedia):
OpenID is an open standard that allows users to be authenticated by certain co-operating sites (known as Relying Parties or RP) using a third party service, eliminating the need for webmasters to provide their own ad hoc systems and allowing users to consolidate their digital identities.
Users may create accounts with their preferred OpenID identity providers, and then use those accounts as the basis for signing on to any website which accepts OpenID authentication. The OpenID standard provides a framework for the communication that must take place between the identity provider and the OpenID acceptor (the "relying party").2 An extension to the standard (the OpenID Attribute Exchange) facilitates the transfer of user attributes, such as name and gender, from the OpenID identity provider to the relying party (each relying party may request a different set of attributes, depending on its requirements).
The OpenID protocol does not rely on a central authority to authenticate a user's identity. Moreover, neither services nor the OpenID standard may mandate a specific means by which to authenticate users, allowing for approaches ranging from the common (such as passwords) to the novel (such as smart cards or biometrics).
Oh, and if you'd like further encouragement, Stack Exchange uses it!
#Jmrnet: in response to your last comment:
Perhaps I was unclear. OpenId in and of itself is simply for validating credentials from one location to another (more or less). It's entirely possible to implement as an SSO model where users do nothing different whatsoever - they don't have to choose a provider, or register, or anything like that. For example, in my setup, the user enters a username and password in a web portal, and then clicks a button to launch another site being automatically logged in by OpenId. Nothing different for the user at all! OpenId can be used with any initial authentication model you can think of (note the bolded section in the snippet from wikipedia).
Take a look at SAML:
http://en.wikipedia.org/wiki/Security_Assertion_Markup_Language
It works using XML and supports encryption.
I am currently implementing two SSO solutions for the same project.
In one, we are interfacing with an external partner and are using SAML.
In the other, we are allowing logged in users access to our Sharepoint and using the "Token in Query String" approach, since we trust Sharepoint to access our membership tables. This approach is much easier than dealing with SAML tokens.
There are many methods you can use, Mansfied described OpenID and RandomUs1r described SAML. Also, you can store relevant information in localStorage or in the session. I believe you should store relevant information with session.
It is not safe to put this in the query string, because if I register and log in, I will see something like UserID=1234 in the URL. If I change that to UserID=1235 and the ID is existent, then I can do some things in the name of the other user. This is called identity theft, which should be prevented by any means possible. So you should never have this kind of info in your URLs. Also, if you store the id of the user, you should obfuscate it somehow. For instance if you store the value in local storage and instead of 1234 you store encrypt(1234, salt), then the consistency of user action will be maintained.
I have been tasked with developing a single Login and Dashboard page that user can login too, the user will then be shown all the systems (we developed) that they have access based to based on some roles stored in our databases.
If they logged in we would like that "User Session" (not sure of correct terminology) to be carried to which ever system they are redirected too.
To illustrate a very rough overview of what I want to achieve:
alt text http://www.pcbg.co.za/attachment.php?attachmentid=12165&d=1268903524
Is there a way that a user can login in one site, and then carry over that login to the other sites?
Help, Advice, Link will be much appreciated.
Sorry I am not experienced at ASP.net but have a good understanding of Silverlight, C#, WPF.
Thanks in advance.
You can use the concepts of single-sign on. You can manage your session data as out-proc, i.e. in a SQL server or a State server. Here are couple of links which will give you some pointers:
ASP Allaince
MSDN
Edit: Alo look at this question in SO:
One method that I would use is that you implement your own authentication system - almost like the ASP.NET 1.x days. However, the trick is that you establish a cookie for each domain (host part of the URL) with an authentication cookie.
If all of those systems are running on the same server, I am sure you will be able to use all the FormsAuthentication methods and the Membership API. If they are not [edit: hosted on the same server], then ensure that they configured to encrypt the authentication cookies with the same keys. Implementation of this bit will be by what mileage you need to do...
One thing to notice is that you may also establish only one cookie is sent to the browser but shared by all the applications. Imagine that you have the following URL's:
dashboard.com
myapp1.dashboard.com
myapp2.dashboard.com
myapp3.dashboard.com
Setting a single cookie to the domain "dashboard.com" will send and share the same cookie to all the other domains.
The shared session states as described by the other posters will not work. The way session variables work on the server is that an unique key is generated on the server for your data storage (whatever the medium is: in proc, out of proc, SQL server). That unique key is stored in a cookie where it is sent to your browser as the host part.
I hope that gives you some insight on how to go about tackling the single sign in solution that you are making.
One way would be to use the session state service that ASP.NET provides. Basically once the user logs in, that session could be stored on a separate process (and not be a part of aspnet_wp). All your applications would need to be modified to go to that machine to fetch user authentication status. Search Google/MSDN for Session Management techniques.