FormsAuthentication.SetAuthCookie via service(or other remote means) - c#

We're currently migrating a portion of intranet apps to MojoPortal(an open source cms app). MP uses FormsAuth by default and we've set it to authenticate against our current Active Directory store.
All that being said, we are looking to automatically log in users from the current system to the new system to create a seamless experience. New system(mojo) residing on a different server than the current system. Both live under the same "company.com" domain, with different subdomains.
Mojo, checks authentication via a FormsAuthentication cookie that is created when a user logs in through the mojo interface. We're looking to recreate this functionality remotely. I realize FormsAuth is based on MachineKey and lives inside a single IIS Web Instance, but am curious for any ideas the community may have.
The current "best" guesses we've come up with here are:
Create a WCF web service that lives in a virtual directory under the mojo site, accepts a username/password and creates the cookie. This is untested as we are unsure if this will actually affect the client.
Redirect the user to an intermediate page under mojo which accepts a username/password and creates the cookie, after which redirects the user again to the desired mojo page.
This does use MojoPortal as a provider, but the real issue is how to create a FormsAuthentication cookie remotely.
Additional background info:
Current system already authenticates against the same AD store, so there is no concern over creating cookies for users that are non-existent. Both servers lie in the same AD domain(they're physically next to each other). The current system's source code is available to us and able to be modified as well.

If I understand correctly you are trying to have a single sign-on between your legacy system and mojo? I've done something similar in the past. Our legacy system creates an authentication token and passes it to the second system. A web service call is then made back to the legacy system to validate the token (you'll want to add some rules around what makes a token authentic. For example: one time use, time outs, etc..). If the legacy system validates the token then the cookie is set.
FormsAuthentication.SetAuthCookie(, true)
from there redirect back to your mojo main page.

Related

Generate a token based on the windows user who makes the request

I have searched all over for an answer to this, and not found anything that seems to answer my question. Which feels like it should be an easy one (but clearly isn't).
I have an API which authenticates using a token. This token I generate from my application - more specifically, I have a new Token Generation web call that will return a token. Currently, I pass in a cookie with the user and password information, and it uses this to identify who I am and what I should be allowed to do. This is all working absolutely fine and hunky-dory.
I am achieving this process by making the Token Generation use OWIN Cookie Authentication, which means that the cookie is read and the Identity is set. I am then able to use this identity to confirm whether the user is allowed to access the system.
What I now want to do is replace this Cookie Authentication process by authenticating against a Windows User (everything is windows based, and this will be an option so non-windows users can still use the cookie authentication route). But I cannot discover how to straightforwardly do this.
Note that I don't actually need to validate that the user is genuine or refer back to the AD at all. If you provide a windows user that matches a user in the system, you can log in.
So how can I - easily - get the requesting user into the Identity Name? Or is this not possible?
If you are looking for information on the current user accessing your program, assuming the program is running on the user's machine and is windows based, you can simply query windows for the user's username or any other publicly available information about the user.
Refer to https://learn.microsoft.com/en-us/dotnet/api/system.environment?view=netframework-4.8 for information on the Enviroment class and what it's features are.
If you could provide some code or further clarity I could help you further.

In Identity Server 4, is it possible to make logging out of one application log that user out in all applications?

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.

How to get one login page for multiple systems?

I have four systems running on the same server. I want to let the users to log in once for all the systems. I made one user-management system to create users and edit them.
I tried to save in the session but it didn't help.
Any suggestions? I am working on asp.net.
There are two approaches.
Most resolve around the login happening at a central site, which then returns with an identity information field (login token) that the target site uses to retreive the user.
When you go to another site, the site redirects you shortly to the central site and if you are logged in (persistent cookie) you get back the identity of you.
Alternatively you can do a lot with referrers and playing around.
YOu want to do some research on the internet - what you loo kfo is "Single Sign On".
http://www.codeproject.com/Articles/27576/Single-Sign-on-in-ASP-NET-and-Other-Platforms
has some technical discussions.
Across complete separate websites (domains) you can read up on
http://aspalliance.com/1513_Cross_Site_Authentication_and_Data_Transfer
howw to do it - obviously shared cookies will not work there.
The best way to do this is with Federated Security. If you were using Windows Authentication then you could use Active Directory Federation Services (ADFS). In this model, users reference a Web application and the principal on the current thread is checked. If the value is null then information stored in the web.config will redirect the request to a login page automatically. This is assuming there is no a Windows security context, otherwise the user can be automatically logged in.
After the user is successfully logged into the environment, the principal on the thread is populated and a set of claims are issued that are specific for that user. Since the claims are associated with the principal and not with a specific application, they can be used across the board by any claims aware application.
If you aren't using Windows Authentication, you can still accomplish the same thing, the only problem is that you cannot use ADFS. Instead, you'll have to implement your own Identity Provider to replace ADFS. The .NET Framework does provide base classes and interfaces to help you accomplish that.
I would suggest looking into ActiveDirectory or any LDAP server for single signon to access all applications. If you cannot (or do not wish to) use LDAP, you could implement similar functionality (but with more development work/time spent) with any memory/disk store. If this is not possible, please share why as it might be useful to others.
Hope this helps.

WCF, active directory authentication|authorization and user profiles in sql combination

I'm developing a WCF service that will host business logic of the application. The application is mostly for intranet, but can be accessed from internet. We have an active directory domain up and running, so I plan to authenticate and authorize users according to their username and groups they are in. This service will be used mostly be an ASP.NET MVC site
So, first question is how to authenticate and authorize users based on their AD profile?
Secondly, I need to store additional info about each user. The problem is that I can't modify AD scheme. The number of added fields is about 10 or so.
Can I somehow use SQL server for profile storage? Of course I can, but how to tie this with AD auth?
You can use WIF for this.
You would configure your WCF service for WIF in the normal way and then use a custom ClaimsAuthenticationManager class deriving from the base ClaimsAuthenticationManager and overriding its Authenticate method. This is a normal extensibility point of WIF. WIF will
get hold of the security token from the incoming request and add claims for each of the relevant AD properties. In your override of the Authenticate method, you will add new claims to represent your extra properties.
The basic use of WIF for WCF services is described here:
http://msdn.microsoft.com/en-us/library/ee748476.aspx
To see how to use ClaimsAuthenticationManager, start here:
http://msdn.microsoft.com/en-us/library/ee748211.aspx
Well, I think you have a couple of choices here, but you will have to carefully consider the implementation.
The primary issue with using active directory authentication is that by default a user's credentials can only be passed successfully between two machines. In the case of a web application, this means that the user's credentials can travel between the end user's machine and the web server, but no further.
However, this behavior can be changed through the use of Kerberos authentication, which essentially allows an authentication ticket to be passed among all of the trusted machines in the chain (i.e. from the web server to the application server to the database, for example). Successfully configuring Kerberos can be extremely challenging, especially if you have had no prior experience with it.
I think your best bet is to configure your web site to accept only Windows Authentication. This means that IIS will perform the validation of the user against active directory. In your ASP.Net application you can pickup the domain name of the authorized user from Request.ServerVariables("logon_user").
At this point, you can log the user on with FormsAuthentication, for example, without requiring them to login again.
You could then either implement the SQL Server Membership Provider or create your own interface to your database for further user validation and extra information storage. We have used both mechanisms, but I prefer the self-built one due to the additional control it provides and, in this case, you won't need a lot of the functionality (password reset, recovery, etc) that the membership provider offers.

global admin page for multiple applications in ASP.Net

I was wondering if anybody could give advice on a secure way to implement a global login. I have an admin page that accesses active directory admin groups after typing in your username and password.
current logged in account (on computer) does not matter
user in web browser goes to web app, redirects to global login page with query string of app name
types user name and password of an account in AD (not necessarily current computers logged in user)
authenticates (looks up user, pass etc and authentication is valid)
redirects back to original web app.
Once redirection happens, how do I securely tell the original web app that this user is ok until the original web session dies?
The way I'm thinking of implementing it:
My original thought was to pass the session ID of original app to the login page as well as the app
name. Store that session in a DB once authentication is checked. Master page of the other app validates on page load that the session ID matches. On session close, remove current session ID from DB.
You cannot depend on sessionID accurately in some cases. SessionID only becomes a constant value after a (any) page makes a request for a session variable, if you dont have Session_Start not defined in global.asax. If you log the user in and the default page does not access session, you will end up with a different session id for the subsequent requests until a request to session is made. Usually it is always constant as there is a default empty session_start event in global.asax.
But similar to your model, you could generate a GUID (or make sure you access session on login/authentication) and store it in the user table with an expiration. Your web sites can check this key and if currently valid, auto sign the user in.
You also cannot depend on session_end event since there is no real accurate way of detecting it (eg: user closing browser). So, you should store this ID with an expiration time along with it, preferably the same as session timeout. Just like session, you will need to extend this, something like a sliding expiration. This way, this id will be expired after a period of inactivity.
also, this Claims-Based Single Sign-On for the Web may be of interest to you.
What you're describing sounds like it would be better implemented using Windows Identity Foundation and Active Directory Federation Services 2.0. I don't know the extent of all your requirements, but it might be valuable to check out what these will give you out of the box.
You could use a cookie. If you pass the name of the application to the login page, you can set that application name to the PATH property of the formsauthentication cookie. By setting the PATH property, you're effectively limiting the readability of the cookie to the pages within that path. Because it's a common login interface, this may require some code being done perhaps in a common page base class that handles the parsing of the cookie information.
You can share authentication tokens between .NET applications, even between .NET CLR's if you want to. I think this will give you the single sign on you're looking for.
At a high level you need to share a machine key between the applications. You can generate the machine key using the key generator app code example found on this link, and providing you then reference the same key in each application the sign on can be shared:
http://msdn.microsoft.com/en-us/library/ms998288.aspx
There are some consideration when looking at things across domains or accross machines/web farms etc, but if all apps are on the same box it's not too hard.
The harder side of things is sharing things like session state which I don't believe can be done accross app pools. (I ended up recreating the session object on the new app manually last time I did it :( but that was between 1.1 and 2.0 apps )
EDIT: I did a rough write up of it last year and was using it as a test for a demo article on my site, might be worth a read through if you want things broken down a bit more (Ignore the unfinished site!):
http://www.dougmcdonald.co.uk/test/html5/v5/articles/2010/05/10/Sharing-forms-authentication-between-applications/

Categories