title: Integrating IdentityServer4 With WebAPI
body: <p>I am trying to integrate IdentityServer4 with ASP.NET MVC WebAPI.I want to achieve role based authorization. I have the following projects running.</p>
  
  <ol>
  <li>IdentityServer4 [a separate project]</li>
  <li>WebApi </li>
  <li>Javascript Application [using Extjs]</li>
  </ol>
  
  <p>I have implemented the <strong>ResourceOwnerPassword</strong> flow and what I am trying to do is, </p>
  
  <ol>
  <li>Make a <strong>post</strong> request to <strong>AccountController</strong> of the WebApi containing username and password</li>
  <li>Inside the AccountController call the IdentityServer token endpoint for an access token and return the access token to the client (javascript app)</li>
  <li>Make a request to the WebApi containing the access token.</li>
  </ol>
  
  <p>For the above part I am success full, here is the code</p>
  
  <p><strong>POSTMAN call for Login</strong></p>
  
  <p><a href="https://i.stack.imgur.com/ikjkm.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ikjkm.png" alt="enter image description here"></a></p>
  
  <p><strong>AccountController</strong></p>
  
  <pre><code> [ActionName("Login")]
      [AllowAnonymous]
      [HttpPost]
      public async Task&lt;BaseModel&gt; Login(LoginModel model)
      {
          model.RememberMe = false;
          var status = await _security.Login(model.Email, model.Password, model.RememberMe);
  
          if (status.Status == LoginStatus.Succeded)
          {
              return new BaseModel { success = true, message = "login", data = status.Data };
          }
      }
  </code></pre>
  
  <p><strong>SecurityService</strong></p>
  
  <pre><code>  public async Task&lt;LoginResponse&gt; Login(string userName, string password, bool persistCookie = false)
      {
          // discover endpoints from metadata
          var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
  
          // request token
          var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
          var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(userName, password, "api1");
  
          if (tokenResponse.IsError)
          {
              return new LoginResponse { Status = LoginStatus.Failed, Message = tokenResponse.Error };
          }
  
          return new LoginResponse { Status = LoginStatus.Succeded, Data = tokenResponse.Json };
      }
  </code></pre>
  
  <p><strong>Security the API</strong></p>
  
  <p>I have two more actions inside the AccountController (just for testing) namely:</p>
  
  <ol>
  <li>values() [returns success and requires no authentication]</li>
  <li><p>SecureValues [returns success and requires authentication]</p>
  
  <pre><code>[HttpGet]
  public BaseModel values()
  {
      return new BaseModel
      {
          success = true
      };
  }
  
  [Authorize]
  [HttpGet]
  public BaseModel SecureValues()
  {
      return new BaseModel
      {
          success = true
      };
  }
  </code></pre></li>
  </ol>
  
  <p>calling <strong>"Values"</strong> action returns the success which is quite obvious, calling the <strong>"SecureValues"</strong> gives following</p>
  
  <p><a href="https://i.stack.imgur.com/emfSB.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/emfSB.png" alt="enter image description here"></a></p>
  
  <p>Which means that the user is not Authenticated.</p>
  
  <p>My <strong>IdentityServer4</strong> configuration is as follows:</p>
  
  <pre><code> public class Config
  {
      // scopes define the resources in your system
      public static IEnumerable&lt;Scope&gt; GetScopes()
      {
          return new List&lt;Scope&gt;
          {
              StandardScopes.OpenId,
              StandardScopes.Profile,
  
              new Scope
              {
                  Name = "api1",
                  Description = "My API",
                  DisplayName = "API Access",
                  Type = ScopeType.Resource,
                  IncludeAllClaimsForUser = true,
                  Claims = new List&lt;ScopeClaim&gt;
                  {
                      new ScopeClaim(ClaimTypes.Name),
                      new ScopeClaim(ClaimTypes.Role)
                  }
              },
             new Scope
             {
                 Enabled = true,
                 Name  = "role",
                 DisplayName = "Role(s)",
                 Description = "roles of user",
                 Type = ScopeType.Identity,
                 Claims = new List&lt;ScopeClaim&gt;
                 {
                     new ScopeClaim(ClaimTypes.Role,false)
                 }
             },
             StandardScopes.AllClaims
          };
      }
  
      // clients want to access resources (aka scopes)
      public static IEnumerable&lt;Client&gt; GetClients()
      {
          // client credentials client
          return new List&lt;Client&gt;
          {
              new Client
              {
                  ClientId = "client",
                  AllowedGrantTypes = GrantTypes.ClientCredentials,
  
                  ClientSecrets =
                  {
                      new Secret("secret".Sha256())
                  },
                  AllowedScopes = { "api1" }
              },
  
              // resource owner password grant client
              new Client
              {
                  ClientId = "ro.client",
                  AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
  
                  ClientSecrets =
                  {
                      new Secret("secret".Sha256())
                  },
                  AllowedScopes = { "api1" }
              },
  
              // OpenID Connect implicit flow client (MVC)
              new Client
              {
                  ClientId = "mvc",
                  ClientName = "MVC Client",
                  AllowedGrantTypes = GrantTypes.Implicit,
  
                  //flow
  
                  RedirectUris = { "http://localhost:5002/signin-oidc" },
                  PostLogoutRedirectUris = { "http://localhost:5002" },
  
                  AllowedScopes =
                  {
                      StandardScopes.OpenId.Name,
                      StandardScopes.Profile.Name,
                      "role"
                  }
              },
              //for hybrid flow
              new Client
              {
                  ClientId = "mvchybrid",
                  ClientName ="mvc hybrid client",
                  AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                  ClientSecrets =
                  {
                      new Secret("secret".Sha256())
                  },
  
                  RedirectUris = {"http://localhost:5003/signin-oidc"},
                  PostLogoutRedirectUris = {"http://localhost:5003"},
  
                  AllowedScopes =
                  {
                      StandardScopes.OpenId.Name,
                      StandardScopes.Profile.Name,
                      StandardScopes.OfflineAccess.Name,
                      "api1"
                  }
              },
              new Client
              {
                  ClientId = "js",
                  ClientName = "javascript client",
                  AllowedGrantTypes = GrantTypes.Implicit,
                  AllowAccessTokensViaBrowser= true,
                  RedirectUris = {"http://localhost:5004/callback.html"},
                  PostLogoutRedirectUris = {"http://localhost:5004/index.html"},
                  AllowedCorsOrigins = {"http://localhost:5004"},
  
                  AllowedScopes =
                  {
                      StandardScopes.OpenId.Name,
                      StandardScopes.Profile.Name,
                      "api1",
                      "role",
                      StandardScopes.AllClaims.Name
                  }
              },
              //aspnet identity client
              new Client
              {
                  ClientId = "mvcIdentity",
                  ClientName = "Mvc Identity Client",
                  AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                  RequireConsent = false,
                  ClientSecrets =
                  {
                      new Secret("secret".Sha256())
                  },
                  RedirectUris = {"http://localhost:5005/signin-oidc"},
                  PostLogoutRedirectUris = {"http://localhost:5005"},
                  AllowedScopes =
                  {
                       StandardScopes.OpenId.Name,
                       StandardScopes.Profile.Name,
                       StandardScopes.OfflineAccess.Name,
                       "api1"
                  }
              }
          };
      }
  
      public static List&lt;InMemoryUser&gt; GetUsers()
      {
          return new List&lt;InMemoryUser&gt;
          {
              new InMemoryUser
              {
                  Subject = "1",
                  Username = "alice@yahoo.com",
                  Password = "password",
  
                  Claims = new List&lt;Claim&gt;
                  {
                      new Claim("name", "Alice"),
                      new Claim("website", "https://alice.com"),
                      new Claim(ClaimTypes.Role,"FreeUser")
                  }
              },
              new InMemoryUser
              {
                  Subject = "2",
                  Username = "bob@yahoo.com",
                  Password = "password",
  
                  Claims = new List&lt;Claim&gt;
                  {
                      new Claim("name", "Bob"),
                      new Claim("website", "https://bob.com"),
                      new Claim(ClaimTypes.Role,"PaidUser")
                  }
              }
          };
      }
  }
  </code></pre>
  
  <p><strong>WebApi configuration</strong></p>
  
  <pre><code> public void ConfigureAuth(IAppBuilder app)
      {
  
          app.UseIdentityServerBearerTokenAuthentication(new IdentityServer3.AccessTokenValidation.IdentityServerBearerTokenAuthenticationOptions
          {
              Authority = "localhost:5000",
              RequiredScopes = new[] { "api1" },
              ClientId = "ro.client",
              ClientSecret = "secret",
              PreserveAccessToken = true
          });
         }
  </code></pre>