How can I send authorization information back to my client app when using AngularJS, WebAPI 2 and Oauth 2? How can I send authorization information back to my client app when using AngularJS, WebAPI 2 and Oauth 2? asp.net asp.net

How can I send authorization information back to my client app when using AngularJS, WebAPI 2 and Oauth 2?


The short answer to your question is ApplicationOAuthProvider.CreateProperties method. Its created for you by default and is found under WebApi2/Provider/ApplicationOAuthProvider.cs, By default it only sends the userName

//WepApi2/Providers/ApplicationOAuthProvider.cspublic static AuthenticationProperties CreateProperties(string userName){    IDictionary<string, string> data = new Dictionary<string, string>    {        { "userName", userName }    };    return new AuthenticationProperties(data);}

I would make the following update (in case I need to send more user data later on):

public static AuthenticationProperties CreateProperties(string userName, ClaimsIdentity oAuthIdentity){   IDictionary<string, string> data = new Dictionary<string, string>  {      { "userName", userName},      { "roles",string.Join(",",oAuthIdentity.Claims.Where(c=> c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray())}  };  return new AuthenticationProperties(data);}

If you haven't made major changes to the WebApi project, ApplicationOAuthProvider.CreateProperties is only referenced in two places, just update the calling code to pass the oAuthIdentity along with user.UserName and you'll get the user roles sent along with the access token response:

{ "access_token": "ZpxAZyYuvCaWgShUz0c_XDLFqpbC0-DIeXl_tuFbr11G-5hzBzSUxFNwNPahsasBD9t6mDDJGHcuEqdvtBT4kDNQXFcjWYvFP7U2Y0EvLS3yejdSvUrh2v1N7Ntz80WKe5G_wy2t11eT0l48dgdyak8lYcl3Nx8D0cgwlQm-pePIanYZatdPFP9q5jzhD-_k9SF-ARTHgf0ePnbvhLBi1MCYQjvfgPKlbBHt0M5qjwGAeFg1IhSVj0gb4g9QTXoiPhRmxGBmjOpGgzxXixavmrpM7cCBFLoR3DCGnIJo6pwT-6VArxlB8-ZyyOZqh_6gGtptd0lIu8iJRUIGwO9HFNkROdoE9T4buwLnhPpWpy9geBjPVwsB1K3xnbch26YbklhxIHVybBxeIVXd17QTw_LjlQ5TJdqpAYfiZ5B9Nx2AFYYYe3--aemh4y1XOIvN", "token_type": "bearer", "expires_in": 1209599, "userName": "MK", "roles": "Admin,Public", ".issued": "Fri, 23 May 2014 17:36:54 GMT", ".expires": "Fri, 06 Jun 2014 17:36:54 GMT"}

Now you have the roles available, you can use Angular conditional directives to show/hide actions according to user roles.

If you need more clarification, please let me know.

Edit:

Decorating your controller methods with Authorize attribute is valid, since the HttpContext.Current.User.Identity is actually a ClaimsIdentity. But as not to hard code security logic inside the application, I prefer using ClaimsAuthorizationManager

public ActionResult Secure(){  if(!ClaimsPrincipalPermission.CheckAccess("resource", "action"))    return new HttpUnauthorizedResult();  ViewBag.Message = "You are allowed to perform action on resource.";  return View();}

Roles creation using RoleManager:

RoleManager roleManger = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>());roleManager.Create(new IdentityRole() { Name = "Admin" });

Roles assignment using UserManager:

userManager.AddToRole(user.Id, "Admin");


There are 2 ways I see you can approach your problem.

  1. include the "Role" Information to the token by a hash or a simple string append as you are the one generating the token, then you can decipher it on the angular.

  2. it seems you want to use ASP.NET Identity system and store and retrieve the role information there. If that is the case you can go through this post pay attention to "Initialize the database to create Admin Role and Admin User" section.

IMO, #1 will give you more flexibility on how you store and use your user data as #2 you are following Microsoft's IdentityUser , although it look magic sometimes and it tend to post limitation and you need to spend time to understand how it works behind the scene and make it work for your project.

To know more about the "Individual User Accounts" you pick during the WebAPI project you created, you can go to http://www.asp.net/visual-studio/overview/2013/creating-web-projects-in-visual-studio#indauth


I have a very similar scenario as yours, but instead of using tokens to authenticate, I use an Identity Server (Thinktecture) to handle my authentication. My app redirects to the Identity Server to authenticate and it comes back with some very basic claims (username and email). This happens as soon as someone tries to first browse to the page. Once the user is authenticated and redirected to my app I make another call to the server to get the user's permissions. These permissions are stored inside a Security service (AngularJS) which also exposes a "hasPermissions" method. I then use ng-if to decide if I am going to display certain parts of the page - including menu items. Something to this effect:

var service = {    currentUser: ...,    isAuthenticated: function() {        return ...;    },    checkAccess: function(permission) {        return service.isAuthenticated() ?            !!(service.currentUser.permissions.indexOf(permission) > -1) : false;    }}

Remember that all all the permissions and html elements are visible to anyone who decides to hit the dev tools button and take a peek. You have to do the same checks on the server side before you perform any action. We have a custom Authorization attribute based off of this that checks if the user has the necessary permissions to execute the MVC/WebAPI action before it is executed for simple cases or actually check it within the Action or the HTTP resource before doing anything that needs elevated privileges.

If you want the client to not see any html elements or certain sections of your site you can either point your templates to a MVC action that will authenticate and then return the HTML template or redirect to another page (not the SPA realm) and have them authenticated on the server before the response is served back.