簡體   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