Search code examples
asp.net-web-api2claims-based-identityidentityserver3role-base-authorizationmembershipreboot

Identity Server 3 implicit grant, role based authorization


I have set up the Identity Server 3 with Membership reboot database as my authorization server and have also developed a Web Api project which will be accessed by a javascript web app.

Using the implicit flow, the client is able to log in and obtain id_token and access_token. Now I have a few questions, which I would appreciate some detailed answers too:

  1. What is the functionality of id_token? After obtaining it, what can I do with it?

  2. The roles of the users are stored in the database as claims (like for example, the key value of "role","admin"). How do I perform the role-based authorization at this point? It seems like the id_token contains those claims but the access_token does not. When sending my access_token as Bearer along my Api request, how does the api know which roles the sending user has?

  3. In a web api controller, I want to access the user's information using:

    var user = User as ClaimsPrincipal;

using this code, I cannot get pretty much anything about the user; username, id, etc. Also when I use user.Claims in the controller, I have no access to the claims stored in the database. How are there two sets of claims, one in the database one in the token?!

Any extra information is greatly appreciated.


Solution

    1. id_token should be used in the client. You can use it to access the claims at client side. AccessToken is to be used at the API.

    2. To the claims to be included in the access_token you need to create a scope with relevant claims and request that scope in the request. To create a scope(in the self-host sample add scope to Scopes.cs):

      new Scope 
      {
                  Name = "myApiScope",
                  DisplayName = "IdentityManager",
                  Type = ScopeType.Resource,
                  Emphasize = true,
                  ShowInDiscoveryDocument = false,
      
                  Claims = new List<ScopeClaim>
                  {
                      new ScopeClaim(Constants.ClaimTypes.Name),
                      new ScopeClaim(Constants.ClaimTypes.Role)
                  }
      }
      

    Ask for the scope in your authorization request(In Javascript implicit client - simple it is done as follows)

    function getToken() {
            var authorizationUrl = 'https://localhost:44333/core/connect/authorize';
            var client_id = 'implicitclient';
            var redirect_uri = 'http://localhost:37045/index.html';
            var response_type = "token";
            var scope = "myApiScope";
            var state = Date.now() + "" + Math.random();
    
            localStorage["state"] = state;
    
            var url =
                authorizationUrl + "?" +
                "client_id=" + encodeURI(client_id) + "&" +
                "redirect_uri=" + encodeURI(redirect_uri) + "&" +
                "response_type=" + encodeURI(response_type) + "&" +
                "scope=" + encodeURI(scope) + "&" +
                "state=" + encodeURI(state);
            window.location = url;
        }
    

    This will include Name and Role claims in your access token

    1. Configure your API with relevant middleware in the web API startup(in SampleAspNetWebApi sample it is done as follows)

      app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions { Authority = "https://localhost:44333/core", RequiredScopes = new[] { "myApiScope" } });

    Then you can access the claims as follows

                var principal = User as ClaimsPrincipal;
                return from c in principal.Identities.First().Claims
                       select new 
                       {
                           c.Type,
                           c.Value
                       };