11

I have two different web application built with ASP.net MVC. This two application may not be running in the same server nor in the same domain.

I would like that if a user login in one of them, automatically should be login in the other. The same should work with logout.

Which do you think is the best solution? Do you know about some example code?

Thanks!

--- EDITED WITH MORE INFO ---

Use case scenario:

The user has the web application A opened on a tab, and at some point of the app there is a link that redirects the user to the web application B. If he is logged in on A, I would like to show him the full page, and if he is not, redirect him to the login form.

Why I need to do it:

Applications A and B are already built. Apparently, the only way of accessing B is clicking on the link located in A, that only is shown if you have previously logged. The problem is that if you know the URL of some page of B (are long and complex, but still) you can write it on the browser and access B, which it means a security problem.

Ignacio
  • 806
  • 1
  • 10
  • 29
  • 1
    is your database is centralize for both the application? – Ubiquitous Developers Jul 30 '15 at 10:23
  • No, they have different databases. – Ignacio Jul 30 '15 at 10:31
  • 1
    will they be sharing the same login details on both applications? will they be sharing the same aspnetdb ? do you expect them to have both applications open at the same time in different browser tabs or in a different instance of the browser? can you provide a use case scenario? tbh this sounds like a bad idea. – user1666620 Jul 30 '15 at 10:32
  • 1
    @Ignacio are you serious? is it works ? – Chandrashekar Jupalli Jul 30 '15 at 10:37
  • Ok, maybe I should have provided more information. The user has one web application open on a tab, and at some point of the application there is a link that redirects the user to the second web application. If he is logged in the first application, I would like to show him the full page, and if he is not, redirect him to the login form. – Ignacio Jul 30 '15 at 10:41
  • ok, so you can pass userid or email from application A to application B anyhow by localdb or cookie. if the same email or userid is available on second database, allow him to login or else ask for login – Ubiquitous Developers Jul 30 '15 at 13:05
  • Using cookies is not an option, because the applications are in different domains. See http://stackoverflow.com/questions/4781353/sharing-cookies-across-different-domains-and-different-applications-classic-asp – Ignacio Jul 30 '15 at 13:51
  • What about using window.postMessage - it allows cross-domain? https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage – Nikolay Aug 04 '15 at 08:21
  • @Nikolay as I have understood the postMessage method only works if both applications are open at the same time and in different tabs/windows. When the user login in the A application, the other one is not opened (is running, but migth be not open in a tab) yet. Maybe I have miss understood the doc, tell me if Im wrong. – Ignacio Aug 04 '15 at 09:37
  • 1
    how about single sign-on (SSO)? https://www.simple-talk.com/dotnet/asp.net/introducing-single-sign-on-to-an-existing-asp.net-mvc-application/ http://stackoverflow.com/questions/15128624/how-to-implement-single-sign-on-in-mvc4 https://auth0.com/docs/tutorials/aspnet-mvc4-enterprise-providers – Daniel Gpe Reyes Aug 04 '15 at 13:58

6 Answers6

8

My Answer may not be the the best one, However you can use some tricky mechanism like

  1. whenever you are going on another application you need to pass one token from application A to B.
  2. Validate this token on B site.
  3. and Authorized that user based on token. (i mean apply silent or backdoor login)
Kaushik Thanki
  • 3,334
  • 3
  • 23
  • 50
7

I assume you cannot communicate between applications A and B using any shared store. (This could allow some shared session implementation).

The more industry standard way (OpenID Connect) of doing that is like some of the other answers have hinted at. I will try and give more details to get you on the right track.

Both application A and B should relay the authentication process to a trusted 3rd party (which could be hosted in withe A, B or a different application altogether) - Let's call it C

When the user arrives at either A or B (no matter that B has weird complicated URLs, she can always bookmark those) his request should contain an authorization token. If it doesn't, she is not authenticated and would be redirected to C and presented with some login mechanism - say user/pass form.

After successful login, she is redirected back to A/B (depending on where she came from) to complete what ever she was doing with the authentication token. Now, having the authentication token present she is authenticated.

If she is authenticated with A and then redirected to B, this redirect should contain the token as well, B would know how to trust that token.

Now, If he just opens opens up a new tab, B would not see any token, and so she would be redirected to C, only to be redirected back (she is already authenticated, remember?) to B with the token, and now all is good.

What I described is a common flow using OpenID connect, and if using .net, I really suggest using IdentityServer from Thinktecture to do the hard work for you and be your "C".

Another option, is to pay for such "C" hosted as a SaaS application - check out Auth0

Yoad Snapir
  • 528
  • 2
  • 10
5

You can implement OAuth in A Project. You can get more help here: http://www.openauthentication.org/about

Bashir Mahmoudi
  • 176
  • 1
  • 15
5

OWIN OAuth 2.0 Authorization Server http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server

Ebubekir Dirican
  • 386
  • 4
  • 12
4

I think what you are after is CAS (Central Authentication Service) https://en.wikipedia.org/wiki/Central_Authentication_Service

there are numbers of CAS provider available. I would recommend you to check this out https://wiki.jasig.org/display/CAS/Home

it will give you number of out-of-the-box solutions exist to enable web services written in a specific language, or based on a framework, to use CAS. This will help you implement a SSO solution in a matter of hours

vijay shiyani
  • 766
  • 7
  • 19
4

Thanks to the answer of @Kaushik Thanki I have implemented some code that fix my problem. I will post here the solution that it works for me, even if it is not the optimus.

First of all, I have implemented in A a method to make a Post request to B. Inside this method I take the id of the user and I make a hash of it with some other parameter and passwords. Then, I send to B the user id, the hash, and a boolean to choose between login and logout.

private void SendPostRequest(bool login)
        {
            // Create the combine string
            string data = // userId combined with more stuff

            // Create the hash of the combine string
            HashAlgorithm algorithm = MD5.Create();
            byte[] hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(data));
            StringBuilder sb = new StringBuilder();
            foreach (byte b in hash)
                sb.Append(b.ToString("X2"));

            string encriptedData = sb.ToString();

            // Fill the url with the path and the data
            string url = "http://localhost/xxx/yyy/ExternalAuthentication/Login?id=" + _cachedCustomer.Id + "&hash=" + encriptedData + "&login=" + login.ToString();

            // Make the Post request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream resStream = response.GetResponseStream();
        }

After it, I have created in B a new class to handle the login logic. I have use a HttpContext.Current.Application variable to store the status of the authentication:

public class ExternalAuthenticationController : Controller
        {

            public ActionResult Index()
            {
                return View();
            }

            public ActionResult Login(string id, string hash, string login)
            {
               // Create the combine string
               string data = //user id + same stuff than in A;

               // Create the hash of the combine string
               HashAlgorithm algorithm = MD5.Create();
               byte[] hashArray =    algorithm.ComputeHash(Encoding.UTF8.GetBytes(data));
               StringBuilder sb = new StringBuilder();
               foreach (byte b in hashArray)
                  sb.Append(b.ToString("X2"));
               string originalHash = sb.ToString();

               // Compare the two hash. If they are the same, create the variable
               if (hash.CompareTo(originalHash) == 0)
               {

               if (System.Web.HttpContext.Current.Application["Auth"] == null)
               {
                   System.Web.HttpContext.Current.Application["Auth"] = false;
               }

               if (Convert.ToBoolean(login))
               {
                   System.Web.HttpContext.Current.Application["Auth"] = true;
               }

              else
              {
                  System.Web.HttpContext.Current.Application["Auth"] = false;
              }
             }
         }

Probably, the answer provided by @vijay shiyani is better and more generalistic, but from my point of view it requires a lot of time to implement it.

Ignacio
  • 806
  • 1
  • 10
  • 29
  • Yes it works for me. To who should I give the bounty? One of the answer give a good solution that probably help more people and the other one guide me to a solution even when it is not full... – Ignacio Aug 05 '15 at 14:20
  • I think I can not split it, and with the reputation I lost with this bounty I lost the priviledge to start a new one haha – Ignacio Aug 05 '15 at 14:31
  • jokes a part , If you think my idea helped you to get solution for your problem you can give your bounty to me. After all at last it is your decision (: – Kaushik Thanki Aug 05 '15 at 14:34
  • 1
    @Ignacio MD5 hashs are not secure - they're fairly easy to spot and cheap to brute force, especially as the secure token is basically just an MD5 of the user details. Instead use a slow, expensive to brute force hash like PBKDF2 (.Net has built in support with `Rfc2898DeriveBytes`). Also you have no validation of the source of the request - really you want Application B to only ever accept login requests from Application A. If they both have access to the same DB this is easiest with some kind of key, stored in the DB and changed regularly, that B can use to check that the request came from A. – Keith Aug 07 '15 at 08:35
  • @Keith Thanks you, I did not know that about MD5, I will change it. Regarding to the validation, they do not share the BBDD. Probably the architecture of the full system is bad designing, but It can not be changed now. – Ignacio Aug 07 '15 at 15:00
  • @Ignacio without a shared DB you should still be able to do something - add a signature to your user data using a private key on A, and have the corresponding public key on B to verify it. – Keith Aug 07 '15 at 15:23