Blazor 客户端中的 Identityserver4 未授权 api

Posted

技术标签:

【中文标题】Blazor 客户端中的 Identityserver4 未授权 api【英文标题】:Identityserver4 not authorized api in blazor client 【发布时间】:2021-02-26 22:34:05 【问题描述】:

我将身份服务器 4 与 blazor 服务器端客户端一起使用

一切正常,但令牌未授权 api 方法,但令牌在服务器授权控制器中工作

授权类型或代码流有问题吗?

服务器配置类:

 public static class Configurations
    
        public static IEnumerable<IdentityResource> GetIdentityResources() =>
            new List<IdentityResource>
            
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
            ;

        public static IEnumerable<ApiResource> GetApis() =>
            new List<ApiResource> 
                new ApiResource("api1")
            ;

        public static IEnumerable<ApiScope> GetApiScopes()
        
            return new List<ApiScope>
            
                // backward compat
                new ApiScope("api1")
            ;
        

        public static IEnumerable<Client> GetClients() => new List<Client>
        
        new Client
            
                ClientId = "client",
                AllowedGrantTypes = GrantTypes.Code,
                ClientSecrets =
                
                    new Secret("secret".Sha256())
                ,
                AllowedScopes =  
                        "api1" ,
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                ,
                RedirectUris =  "https://localhost:44372/signin-oidc" ,

                AlwaysIncludeUserClaimsInIdToken = true,

                AllowOfflineAccess = true,
                RequireConsent = false,
                RequirePkce = true,
            
        ;

     
    

服务器启动类:

  public void ConfigureServices(IServiceCollection services)
        

            services.AddDbContext<AppDbContext>(config =>
            
                config.UseInMemoryDatabase("Memory");
            );

            // AddIdentity registers the services
            services.AddIdentity<IdentityUser, IdentityRole>(config =>
            
                config.Password.RequiredLength = 4;
                config.Password.RequireDigit = false;
                config.Password.RequireNonAlphanumeric = false;
                config.Password.RequireUppercase = false;
            )
                .AddEntityFrameworkStores<AppDbContext>()
                .AddDefaultTokenProviders();

            services.ConfigureApplicationCookie(config =>
            
                config.Cookie.Name = "IdentityServer.Cookie";
                config.LoginPath = "/Auth/Login";
                config.LogoutPath = "/Auth/Logout";
            );



            services.AddIdentityServer()
                .AddAspNetIdentity<IdentityUser>()
               //.AddInMemoryApiResources(Configurations.GetApis())
               .AddInMemoryIdentityResources(Configurations.GetIdentityResources())
               .AddInMemoryApiScopes(Configurations.GetApiScopes())
               .AddInMemoryClients(Configurations.GetClients())
               .AddDeveloperSigningCredential();

            services.AddControllersWithViews();
        

api 启动类:

            services.AddAuthentication("Bearer").AddIdentityServerAuthentication(option =>
            
                option.Authority = "https://localhost:44313";
                option.RequireHttpsMetadata = false;
                option.ApiName = "api1";
            );

blazor 服务器端启动类:

services.AddAuthentication(config =>
            
                config.DefaultScheme = "Cookie";
                config.DefaultChallengeScheme = "oidc";
            )
                .AddCookie("Cookie")
                .AddOpenIdConnect("oidc", config =>
                
                    config.Authority = "https://localhost:44313/";
                    config.ClientId = "client";
                    config.ClientSecret = "secret";
                    config.SaveTokens = true;
                    config.ResponseType = "code";
                    config.SignedOutCallbackPath = "/";
                    config.Scope.Add("openid");
                    config.Scope.Add("api1");
                    config.Scope.Add("offline_access");
                );

            services.AddMvcCore(options =>
            
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser() // site-wide auth
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            );

【问题讨论】:

您能否尝试重新表述该问题?我无法理解问题 @nahidf 我想将 api1 添加到 api 范围并在身份服务器中进行身份验证后使用它。在身份服务器版本 3 中一切正常,但在版本 4 中返回 401 【参考方案1】:

要解决此问题,您有 2 个选项:

1-(推荐)将范围添加到 API 资源,如下所示:

public static IEnumerable<ApiResource> GetApis() =>
            new List<ApiResource> 
                new ApiResource("api1")
                
                    Scopes = new [] "api1" 
                
            ;

        public static IEnumerable<ApiScope> GetApiScopes()
        
            return new List<ApiScope>
            
                // backward compat
                new ApiScope("api1")
            ;
        

2- 在 API 上更改您的代码以设置 ValidateAudience = false,如下所示:

services.AddAuthentication("Bearer").AddJwtBearer("Bearer",
   options =>
   
      options.Authority = "http://localhost:5000";
      options.Audience = "api1";
      options.RequireHttpsMetadata = false;
      options.TokenValidationParameters = new 
         TokenValidationParameters()
         
            ValidateAudience = false
         ;
   );

这是我关于将 IdentityServer4 迁移到 v4 的博客https://nahidfa.com/posts/migrating-identityserver4-to-v4/

【讨论】:

谢谢它的工作我怎样才能了解其他流程? 现在建议使用的唯一流程是代码 + PKCE 和客户端凭据(用于服务器到服务器) - 这里有一些有用的链接:oauth.net/2/pkceoauth.net/2/grant-types/client-credentials【参考方案2】:

我实际上并没有在 API 中使用AddIdentityServerAuthentication,但你可以试试下面的代码。从技术上讲,它是一样的,但也许这会起作用。

将您的 api 身份验证从 AddIdentityServerAuthentication 更改为 AddJwtBearer

   services.AddAuthentication("Bearer").AddIdentityServerAuthentication(option =>
            
                option.Authority = "https://localhost:44313";
                option.RequireHttpsMetadata = false;
                option.ApiName = "api1";
            );

   services.AddAuthentication("Bearer")
           .AddJwtBearer("Bearer", option =>
           
               option.Authority = "https://localhost:44313";
               option.Audience = "api1";
               option.SaveToken = true;
           );

【讨论】:

不起作用我将身份服务器版本从 4 更改为 3,一切正常,但在版本 4 中未授权

以上是关于Blazor 客户端中的 Identityserver4 未授权 api的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Blazor 生成和保存文件客户端?

如何从 Blazor 中的 HttpClients 关闭浏览器控制台中的“信息”登录?

为 Blazor WebAssembly 中的所有 blazor 页面实例化一个对象?

如何在 Blazor WASM 客户端中访问 Httpclient 标头

[Inject] 有问题,不能在 C# 类 (Blazor) 中工作

Blazor 客户端调试