繁体   English   中英

IdentityServer:检查 OpenId Connect 中的身份验证策略中是否存在范围

[英]IdentityServer: Check if scopes present in a policy for authentication in OpenId Connect

我有一个基于策略的身份验证的控制器:

[ApiController]
[Route("[controller]")]
[Authorize(Policy ="SomePolicy")]
public class BankController : ControllerBase
{
...    
}

说明“范围”的策略身份验证代码应该是“读取”或“完全访问”。 见下面的代码:

services.AddAuthorization(options =>
{
    options.AddPolicy("SomePolicy", policy =>
    {
        policy.RequireClaim("scope", "read", "fullaccess");
    });
});

“读取”和“完全访问”是在 appsetting.json 上定义的 ApiScopes,并从那里提供给 IdentityServer 4。

"IdentityServerSettings": {
  "ApiScopes": [
    {
      "Name": "read"
    },
    {
      "Name": "fullaccess"
    }
  ],
  ...
}

该代码在邮递员测试中运行良好。

问题是如何在 OpenId Connect 上实现。 我所有的尝试似乎都失败了。

我试过了:

.AddOpenIdConnect("oidc", options =>
{
     options.Authority = "https://localhost:5001";
     options.ClientId = "postman";
     options.ResponseType = "code";
     
     options.Scope.Add("read");
     options.Scope.Add("fullaccess");

     options.SaveTokens = true;
 });

但它不起作用? 请帮忙?

我想我可以在这里分享我的集成步骤来帮助您解决问题。

单击此处查看相关博客

首先,我创建了一个 asp.net core 3.1 mvc 项目,并安装了这些包:

<ItemGroup>
    <PackageReference Include="IdentityServer4" Version="4.1.2" />
    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.17" />
  </ItemGroup>

然后添加一个名为Config.cs的文件,请注意在我的项目中,https的默认端口是5001,参见launchSetting.json:

using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using System.Collections.Generic;
using System.Security.Claims;

namespace WebApplication1
{
    public class Config
    {
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                new IdentityResource
                {
                    Name = "role",
                    UserClaims = new List<string> {"role"}
                }
            };
        }

        public static IEnumerable<ApiScope> GetApiScopes()
        {
            return new List<ApiScope>
            {
                new ApiScope("api1.read", "Read Access to API #1"),
                new ApiScope("api1.write", "Write Access to API #1")
            };
        }

        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource> {
                new ApiResource
                {
                    Name = "api1",
                    DisplayName = "API #1",
                    Description = "Allow the application to access API #1 on your behalf",
                    Scopes = new List<string> {"api1.read", "api1.write"},
                    ApiSecrets = new List<Secret> {new Secret("ScopeSecret".Sha256())},
                    UserClaims = new List<string> {"role"}
                }
            };
        }

        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                // other clients omitted...

                new Client
                {
                    ClientId = "oidcClient",
                    ClientName = "Example Client Application",
                    ClientSecrets = new List<Secret> {new Secret("SuperSecretPassword".Sha256())}, // change me!
    
                    AllowedGrantTypes = GrantTypes.Code,
                    RedirectUris = new List<string> {"https://localhost:5001/signin-oidc"},
                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,
                        "role",
                        "api1.read"
                    },

                    RequirePkce = true,
                    AllowPlainTextPkce = false
                },
                new Client
                {
                    ClientId = "oauthClient",
                    ClientName = "Example client application using client credentials",
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets = new List<Secret> {new Secret("SuperSecretPassword".Sha256())}, // change me!
                    AllowedScopes = new List<string> {"api1.read"}
                }
            };
        }

        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>
            {
                new TestUser {
                    SubjectId = "5BE86359-073C-434B-AD2D-A3932222DABE",
                    Username = "tiny",
                    Password = "111",
                    Claims = new List<Claim> {
                        new Claim(JwtClaimTypes.Email, "tiny@gmail.com"),
                        new Claim(JwtClaimTypes.Role, "admin")
                    }
                }
            };
        }
    }
}

接下来,我们可以使用powershell运行命令在我们的项目中安装默认身份服务器4 ui ,用于登录部分。 因为它还会提供一个HomeController.cs,所以我们可以在创建项目的时候重命名或者删除原来的HomeController。 进入项目根目录,打开powershell,运行:

iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/main/getmain.ps1'))

然后我们需要修改startup.cs,这是我的文件:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication1
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryApiScopes(Config.GetApiScopes())
                .AddInMemoryClients(Config.GetClients())
                .AddTestUsers(Config.GetUsers());
            services.AddControllersWithViews();

            //If we only need to enable the token validation for api, use the code commented below
            //services.AddAuthentication("Bearer")
            //.AddIdentityServerAuthentication("Bearer", options =>
            //{
            //    options.ApiName = "api1";
            //    options.Authority = "https://localhost:5001";
            //});

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "cookie";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("cookie")
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = "https://localhost:5001";
                options.ClientId = "oidcClient";
                options.ClientSecret = "SuperSecretPassword";

                options.ResponseType = "code";
                options.UsePkce = true;
                options.ResponseMode = "query";

                options.CallbackPath = "/signin-oidc"; // default redirect URI

                // options.Scope.Add("oidc"); // default scope
                // options.Scope.Add("profile"); // default scope
                options.Scope.Add("api1.read");
                options.SaveTokens = true;
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseIdentityServer();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

最后,让我们评论 HomeController 中的[AllowAnonymous]属性,并为隐私页面添加一个操作:

[Authorize]
public IActionResult Privacy() => View();

我们还可以添加一个新控制器使其像 api 一样工作并在该控制器上添加[Authorize] ,例如

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication1.Controllers
{
    [Authorize]
    public class HelloController : Controller
    {
        public string Index()
        {
            return "hello world";
        }
    }
}

然后启动程序,我们可以直接看到首页,但是如果我们访问https://localhost:5001/hello/index , https://localhost:5001/home/privacy ,会重定向到登录页面,之后登录(用户名和密码在 config.cs 中定义)我们可以看到私人页面或响应消息。

在此处输入图片说明 在此处输入图片说明 在此处输入图片说明 在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM