使用IdentityServer4进行基于角色的Web API授权

时间:2018-05-10 05:32:14

标签: identityserver4 asp.net-core-identity

我正在使用带有.Net Core 2.0和Asp.Net核心身份的IdentityServer4(v2.2.1)。 我的解决方案中有三个项目。

  1. IdentityServer
  2. Web API
  3. MVC Web应用程序
  4. 我正在尝试在我的Web API上实现基于角色的授权,以便任何客户端都可以将访问令牌传递给Web API以访问资源。

    目前我可以在MVC应用程序控制器上实现Roles base授权,但我无法为WEB API Controller传递/配置相同的内容。

    以下是Identity Server文件: Config.cs

    public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                //SCOPE - Resource to be protected by IDS 
                new ApiResource("TCSAPI", "TCS API")
                {
                    UserClaims = { "role" }
                }
            };
        }
    
    
     public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
    new Client
                {
                    ClientId = "TCSIdentity",
                    ClientName = "TCS Mvc Client Application .",
                    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                    RequireConsent = false,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
    
                    RedirectUris = { "http://localhost:5002/signin-oidc" },
                    PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
    
                    AlwaysSendClientClaims= true,
                    AlwaysIncludeUserClaimsInIdToken = true,
    
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Email,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.OfflineAccess,
                        "TCSAPI",
                        "office",
                        "role",
                    },
                    AllowOfflineAccess = true
                }
      };
        }
    
    public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new IdentityResource[]
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                new IdentityResources.Email(),
                new IdentityResource
                {
                    Name = "role",
                    DisplayName="User Role",
                    Description="The application can see your role.",
                    UserClaims = new[]{JwtClaimTypes.Role,ClaimTypes.Role},
                    ShowInDiscoveryDocument = true,
                    Required=true,
                    Emphasize = true
                }
            };
        }
    

    Startup.cs

     public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    
            services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();
    
            // Add application services.
            services.AddTransient<IEmailSender, EmailSender>();
    
            services.AddMvc();
    
            // configure identity server with in-memory stores, keys, clients and scopes
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryPersistedGrants()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddAspNetIdentity<ApplicationUser>();
        }
    

    MVC WEB APP(角色基础授权适用于MVC WEB APP):

    RoleClaimAction.cs 使用此文件将角色添加到Identity。

    internal class RoleClaimAction : ClaimAction
    {
        public RoleClaimAction()
            : base("role", ClaimValueTypes.String)
        {
        }
    
        public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
        {
            var tokens = userData.SelectTokens("role");
            IEnumerable<string> roles;
    
            foreach (var token in tokens)
            {
                if (token is JArray)
                {
                    var jarray = token as JArray;
                    roles = jarray.Values<string>();
                }
                else
                    roles = new string[] { token.Value<string>() };
    
                foreach (var role in roles)
                {
                    Claim claim = new Claim("role", role, ValueType, issuer);
                    if (!identity.HasClaim(c => c.Subject == claim.Subject
                                             && c.Value == claim.Value))
                    {
                        identity.AddClaim(claim);
                    }
                }
            }
        }
    } 
    

    MVC WEB APP / Startup.cs

     public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
    
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            services.AddCors();
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
                .AddCookie("Cookies")
                .AddOpenIdConnect("oidc", options =>
                {
                    options.SignInScheme = "Cookies";
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;
    
                    options.ClientId = "TCSIdentity";
    
                    //HYBRID FLOW
                    options.ClientSecret = "secret";
    
                    options.ClaimActions.Add(new RoleClaimAction()); // <-- 
    
                    options.ResponseType = "code id_token token";
                    options.GetClaimsFromUserInfoEndpoint = true;
                    options.Scope.Add("TCSAPI");
                    options.Scope.Add("offline_access");
                    //END HYBRID FLOW
                    options.SaveTokens = true;
                    options.Scope.Add("role");
    
                    options.TokenValidationParameters.NameClaimType = "name";
                    options.TokenValidationParameters.RoleClaimType = "role";
                });
    
        }
    

    MVC WEB APP / HomeController.cs 这个动作方法适用于角色基础授权,但是当我尝试将令牌传递给Web Api以访问具有角色基本授权的任何事件时,它无法授权。例如 var content = await client.GetStringAsync(&#34; http://localhost:5001/user&#34;);

    [Authorize(Roles = "User")]
        [Route("user")]
        public async Task<IActionResult> UserAccess()
        {
    
            var tokenClient = new TokenClient("http://localhost:5000/connect/token", "RoleApi", "secret");
            var tokenResponse = await tokenClient.RequestClientCredentialsAsync("TCSAPI");
    
            var client = new HttpClient();
            client.SetBearerToken(tokenResponse.AccessToken);
            var content = await client.GetStringAsync("http://localhost:5001/user");
    
            ViewBag.Json = JArray.Parse(content).ToString();
            return View("json");
        }
        [Authorize(Roles = "Admin")]
        [Route("admin")]
        public async Task<IActionResult> AdminAccess()
        {
            var accessToken = await HttpContext.GetTokenAsync("id_token");
    
            var client = new HttpClient();
            client.SetBearerToken(accessToken);
            var content = await client.GetStringAsync("http://localhost:5001/admin");
            ViewBag.Json = JArray.Parse(content).ToString();
            return View("json");
        }
    

    的WebAPI / Startup.cs

     public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvcCore()
                .AddAuthorization()
                .AddJsonFormatters();
            services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;
                    options.ApiName = "TCSAPI";
                });
    
            services.AddCors(options =>
            {
                options.AddPolicy("default", policy =>
                {
                    policy.WithOrigins("http://localhost:5002")
                    .AllowAnyHeader()
                    .AllowAnyMethod();
                });
            });
        }
    

    WEB API / TestController.cs

    [Route("admin")]
        [Authorize(Roles = "Admin")]
        public IActionResult AdminAccess()
        {
            return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
        }
        [Route("user")]
        [Authorize(Roles = "User")]
        public IActionResult UserAccess()
        {
            return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
        }
        [AllowAnonymous]
        [Route("public")]
        public IActionResult PublicAccess()
        {
            return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
        }
    

0 个答案:

没有答案