We currently have a website which has formsauthentication implemented on it.
One of the client requested us to implement a single sign on solution to this website with basic authentication and we want to keep formsauth for the rest of the clients.
So I created a new SSO folder, SSO/SSODefault.aspx page, which will be accessed by only one client and I configured basic authentication in IIS (enabled basic auth and disabled anonymous).
How do I configure/code at application level so that if a user access ~/SSO/SSODefault.aspx I need to perform basic authentication and if user access ~/Login.aspx or ~/any other page except the above SSO page I need to do FormsAuthentication.
You'll still do FormsAuthentication, but in your SSO page, you'll generate a ticket that the FormsAuthentication method will look at, discover that it is already authenticated, and let that user in. This blog post should get you started in the right direction.
Related
I have 3 ASP.NET MVC websites running with Entity Framework on SQL-Server. Each site runs as an independent app with independent databases. I want to enable business clients to create "Passports" aka tokens that allow them to login into one site while simultaneously logging them into other sites. In order to log into a site, the passport must have a valid"Visa" issued via the Passport system, Passports can be administrated with a Passport Site Manager, which can be used by administrators to access user account information from websites A,B, and C and do admin stuff. In a sense, a Passport can be thought of as having one-to-one correspondence with people's real identity.
Here are my questions, how do I pass a user login attempt from site A to check it with the passport database, and return the result to Website A? How do I keep this communication hidden? In other words, so that only the Website apps A,B,C can check a login attempt with the passport database? Should there be another app that provides that interface? Would it be an ASP.NET Web API?
The second part of my question, once a user logs into site A, they should not have to retype their credentials to get into sites B and C. Instead, upon logging into site A they create sessions with sites B and C, or generate a key that can authorize sessions with sites B and C. What would this process look like?
I'm not looking for a complete solution, but If you can point me towards an example, towards the documentation for the technologies/libraries/objects I would find useful.
What you are looking for is available in Windows Identity Foundation. Look through the developer kit on the site and what you want is fairly easily accomplished.
Your "Passport Site" is referred to as a Security Token Service(STS). Website A,B and C are called Relying Parties (RP). Considering a simple case where you implement your STS using ADFS 2.0 (all your users are maintained in Active Directory). Windows Identity Foundation (WIF) has ASP.NET authentication modules that can work out of the box with ADFS 2.0 over SAML. The STS represents user information in form of "Claims" and creates a X509 signed token with all the claims and provides that as a cookie to the user. RPs can read the token, verify the signature and use the claims for their authentication and authorization purposes.
A sample flow is explained below:
a. User visit's Website A for first time
WIF module checks cookies for a valid token. Since user has not logged in, there is no token.
WIF does a HTTP redirect of the user's browser to the STS site using a special URL that conveys who the intentions (login/logout, RP name, etc.).
STS site checks for the token and since it is not present, displays the login page.
User Logs in and is given a token with the user's claims. There is also a second token specific to the RP's name given (this indicates login for the RP). STS redirects back to the requesting RP.
WIF module on Website A now recognizes the token and uses it for AuthN and AuthZ.
b. Consider now that the user visits Website B.
WIF module checks for a valid token. Since it is not present there is no token.
WIF does a HTTP redirect to the STS again with different paramters (RP changed)
STS checks for login token. Since User has already logged in, it is present.
STS creates a token for the Website B and redirects back to Website B.
Website B WIF module recognizes the token and uses it for AuthN and AuthZ
User did not have to log in again with his user name and password.
The complexity of this system is handling individual site log outs and communicating log out of a user across multiple RPs. There is also a need for maintaining the correct SSL certificates as the whole system relies on it.
Some cases also have an "Active" scenario (the one I described was "Passive" with the browser doing all the running around) where programmer has to code the redirects.
I am currently working on a project that has a requirement that is causing me some issues and I want to know the best way of handling it.
Essentially we would like internal users to be able to access the MVC application and be authenticated through AD, this we want to be pretty much like SSO, they sign on to their computer navigate to the site and they are in.
The second type of users are outside partners that do not exist in our AD and we want to manage through our SQL Server. For these users we want to display a login page and do forms authentication.
My thoughts at first were simple, let IIS try and authenticate with windows authentication and if it fails (401) redirect to a login page. I don't currently have an environment to test this in but from my understanding in IIS7 it is not that simple and requires a little bit of a "hack" to accomplish. I need to avoid anything like that I need a solution that works as the system was designed to work and not by tricking it.
I have looked into ADFS and WIF but ADFS only supports AD not SQL and from what I've seen there is no STS that supports SQL Server. I have contemplated hosting both an internal application that used windows authentication and external application that used forms authentication but I want to avoid this if possible.
Ideally the flow that we want is user navigates to the MVC application IIS tries to do windows authentication, if it fails (401) redirect them to the login page. From there the login page will authenticate the user credentials against the SQL Database. What is the best way of accomplishing this all within 1 MVC application?
Thank you!
I would just implement my own authentication on top of FormsAuthentication or OWIN if you are using ASP.NET MVC 5. It is really simple and you will have full control over where you go to authenticate users. Trust me it isn't as scary as it sounds. I've written a few posts about it that you might find interesting.
MVC 5
http://www.khalidabuhakmeh.com/asp-net-mvc-5-authentication-breakdown-part-deux
MVC 4
http://tech.pro/tutorial/1216/implementing-custom-authentication-for-aspnet
I currently use the MVC 4 method to authenticate against an Active Directory domain with great success. The only thing I would recommend is you Cache your calls to Active Directory as it can be unreliable at times.
There is the STS that supports sql server, it is the IdentityServer.
https://github.com/thinktecture/Thinktecture.IdentityServer.v2
It even supports custom membership providers which give you quite a lot of different possibilities. I am not sure however if it supports automatic fallback to forms when integrated authentication fails. If not, there are two options: a custom sts or two explicit stses and an explicit choice for users. We have implemented the latter scenario once with ADFS - there were two adfses, one with Forms, the other one with integrated auth, first one federated with the other. This gives an explicit choice on the home realm discovery page - ".would you like to log in with username/password or try the integrated authentication"
You could create a project that uses "On-Premises Authentication" which uses ADFS to authenticate users. The on-premises authority URI will be:
https://yourADFSservername/federationmetadata/2007-06/federationmetadata.xml
After your project is loaded, you can to goto your ADFS settings and create a new "Relying Party Trust" and pass on HTTPS URL that your MVC app will be using. Setup to used LDAP attributes as claims and that will sort out AD authentication easily as it will navigate users to organisational sign-in page just like Office 365. Then if authentication fails for certain users, take the user to send the user to normal sign-in/signup page that exists independently of AD and connected to SQL server. You could skip windows authentication altogether by using on-premises authentication.
I already have a working CAS and other sites has the capability to for single sign on. But there is this one site, that does not login automatically. It redirects me to the sites login page though I have successfully signed on in CAS.
Is it possible that SSO do not work on other sites? And why is that? What are the requirements so that SSO will work on that site?
SSO works for all other service site. The above scenario. that you described is only happen if you passed renew=true parameter with you serviceUrl.
For example: your request url to CAS server look like this
https://www.yourcasserver.com/cas/login?service=http://youwebapp.com&renew=true
In this case, parameter renew=true, It allows a client to advise the CAS server login to always authenticate a user regardless of whether a single sign on session already exists.
And this is the useful feature of CAS server, because certain services that would like to use CAS as the authentication mechanism but allow access to sensitive material. They can force CAS to reauthenticate a user to ensure that they are signing in the correct user (and its not a pre-existing SSO session that wasn't terminated.
To use CAS SSO service for all client application, you have to set "renew=false" parameter or you have not pass any renew parameter to CAS login page URL.
I'm enabling an windows identity foundation on an existing webapp.
I want to mess as little as possile with the existing code so I would like to the login page which uses formsauthentication left in the application and I just connect with the STS if the user enters the application via a specific page e.g "im_comming_from_some_other_site.aspx".
in the "im_comming_from_some_other_site.aspx" the code would be like:
Page_Load(...)
{
if(verifyAgainstSTS()
{
FormsAuthentication.SetAuthCookie(<some_STS_Userid), ...)
Response.Redirect("default.aspx")
}
else
{
Response.Redirect("http://<STS_server_name/<STS_service...etc>")
}
}
Is there someone who knows if this may be done and how? Any links to example code (if available) deeply appreciated.
(Of course some code would be needed when to determine what to do when the authentication is timed out; either go to local login page or goto STS-login page)
I know this may seem like a bad design, not going all the way with STS, but I need to implement this ASAP and I want to keep the original site as untouched as possible.
It is not a bad design, it's your requirement and you try to fulfill it. We have working system built like that and it's not a rocket science. The only difference is that we switch it to forms/sam statically (via global settings), not dynamically.
Anyway, you keep your forms authentication in web.config so that when there's no authorization for current user, forms redirects the request to the login page.
In the login page you have two options. One creates the forms cookie somehow.
The other option involves WIF's FederatedPassiveSignIn control.
If a user follows forms authentication, the cookie is set and you are done.
If a user follows the STS login control, sooner or later he/she will come back with valid SAML token. The FederatedPassiveSignIn will pick it up automatically and you just handle the redirect in the SignedIn event.
You will even not need the if you mention in your question.
There's one caveat from what I remember. When a user is authenticated by STS, the WS-Federation cookie is created, you can read claims etc. Everything works.
However, if a user is authenticated by forms, the SAM (SessionAuthenticationModule) will REPLACE forms cookie by the WS-Federation cookie in ASP.NET pipeline upon EACH request (I guess it's because the SAM is later in the pipeline that forms authentication module).
This will NOT blow up your context.User.Identity.IsInRole(...) also authorization works correctly because SAM will copy user roles to corresponding claims.
However, if at any place in your code you try to extract information directly from the forms cookie (instead of using general APIs), you could find out that the forms cookie is not present even if the user was authenticated by forms in first place (and the cookie is not present because it will be replaced by the WS-Federation cookie).
I have a two web application and a sts server. when user calls first web app it is redirected to sts server for validation. on validation the user logs in to the 1st web app. In my 1st web app there is a button when clicked should open the 2nd web app without me asking for
validation from sts server. Since I have added reference of sts in my second web app it is asking for validation again from sts server.
Can anyone please help me.
Thanks
Nilesh
It seems that your STS does not retain the information about user being logged in. The STS itself has to use some authentication mechanism and ask users to log in only the FIRST time they visit the STS.
It could also be a sync issue how are you verifying that the information is being authenticated and passed back, are the users perhaps not setup properly on one of the passthrough servers in regards to SSO authentication..? I would look at Session Variables and see if those are being kept or whiped.. just an idea..
also sounds like the users are not in that domain / authenticated group where you have setup SSO that's probably why it's popping up a user/login I've seen this before when I worked a Chase