Brett
Brett

Reputation: 12007

Best way to authenticate a C# MVC web app using an access token from my API

I have an API that is built on top of OWIN and Identity (I followed the tutorial here). This works great, and I have a http://my.domain.com/token endpoint that returns a bearer access token.

I am now building an MVC we app that will access the API to log a user in via a standard jQuery ajax call. But once the http://my.domain.com/token endpoint is called and an access token is returned from the API, how do I store this value in a way that my MVC web app knows the user is authenticated?

I would like my web app to be able to take advantage of the MVC Identity features, such as Roles, so that I can do something like the following code:

    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }


        [Authorize]
        public ActionResult CompanySecrets()
        {
            return View();
        }


        [Authorize(Users="Stephen")]
        public ActionResult StephenSecrets()
        {
            return View();
        }


        [Authorize(Roles = "Administrators")]
        public ActionResult AdministratorSecrets()
        {
            return View();
        }

    }

So my question is: how can I store a returned access token from my web API and tell my MVC web app that the authentication was successful???

Upvotes: 4

Views: 5594

Answers (4)

Alejandro Ocampo
Alejandro Ocampo

Reputation: 266

I am facing the same scenario for a project. In my case, I've been able to implement what you might be trying to accomplish by following this tutorial: http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/

If you look at the link above you will find very useful information and also concept clarification about OAuth (which really helped me). The next thing I did was to create a Web App using this configuration

    public void ConfigureAuth(IAppBuilder app)
    {
        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login")
        });
        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    }

Then, in my Account Controller I just make an instance of Microsoft.AspNet.Identity.UserManager and at the Login action I have this:

   [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Login(LoginModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            var user = await UserManager.FindAsync(model.UserName, model.Password);
            if (user != null)
            {
                await SignInAsync(user, model.RememberMe);
                return RedirectToLocal(returnUrl);
            }
            else
            {
                ModelState.AddModelError("", "Invalid username or password.");
            }
        }

        return View(model);
    } 

The problem with this approach is that the UserManager I am implementing is going directly to the database in order to find information about the user. In other words, I am not using the API, neither an access token. The Web Api is providing me access tokens but I am using them only for Mobile Devices and other stuff.

The approach in my mind right now is:

  1. At the Login action, make an http request to the Web Api to get the token
  2. Once I have a valid token, I can set the System.Security.Claims.ClaimsIdentity for current user using the information from the token
  3. Then I could use HttpContext.GetOwinContext().Authentication.SignIn method to indicate the user has been authenticated
  4. Finally, I could save the AccessToken and its Refresh token locally using HTML5 storage API. That way I can continue consuming the Web Api directly from javascript and having Authorization features working on my Web App

This is only in my mind. I'm still in the process of research but I will have to implement something soon. I hope this can give you some more clues and maybe something come to your mind better than this (and you share it with us).

Upvotes: 2

Taiseer Joudeh
Taiseer Joudeh

Reputation: 9043

How about to look at my latest post in the series you depend on to build you Web API, you can consider your MVC app as your Resource Server, but in my solution I'm only using bearer tokens for authentication, there is no cookies in my resource server. I believe it should work as well you can benefit from the roles for Authorization.

Upvotes: 1

arpan
arpan

Reputation: 1

You can use AuthenticationManager.SignIn method by adding token in claims. Then those claims could be use across MVC application

Example

AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, 
await user.GenerateUserIdentityAsync(UserManager));

Upvotes: 0

Ryanb58
Ryanb58

Reputation: 351

I suggest you look into the pre-release by the Identity team to push faster prototyping.

Other than that I suggest you start here, it will give you a great base for MVC and .NET. : http://www.asp.net/mvc/tutorials/mvc-5/introduction/getting-started

Upvotes: 0

Related Questions