Core 2.0 上的 IdentityServer4 从 API 获取 401(未经授权)

Posted

技术标签:

【中文标题】Core 2.0 上的 IdentityServer4 从 API 获取 401(未经授权)【英文标题】:IdentityServer4 on Core 2.0 Getting 401 (Unauthorized) from the API 【发布时间】:2018-05-02 08:16:20 【问题描述】:

在尝试迁移到最新版本的 IdentityServer4 和 .NET Core 2 后,我的 Web API 项目突然出现 401 错误。上周,我做了很多更改,但我没有不知道是对是错了。

我有一个小3项目解决方案:

    IDSRV:https://localhost:44300 网络应用:https://localhost:44301 API 应用程序:https://localhost:44302

这是我的代码来配置存储在我的数据库中的 IDSV:

public class Config

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

    public static IEnumerable<ApiResource> GetApiResources()
    
        return new List<ApiResource>
        
            new ApiResource()
                Name = "api.oc.com",
                Description = "OC Api",
                Scopes = new[] new Scope("api.oc.com")
            
        ;
    

    public static IEnumerable<Client> GetClients()
    
        return new List<Client>
        
            new Client
            
                ClientId = "oc.com",
                ClientName = "OC Website",
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                AlwaysIncludeUserClaimsInIdToken = true,                    
                ClientSecrets =
                
                    new Secret("SomeReallyStrongPassword1!".Sha256())
                ,
                RedirectUris =  "https://localhost:44301/signin-oidc" ,
                PostLogoutRedirectUris =  "https://localhost:44301/signout-callback-oidc" ,
                AllowedScopes =
                
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "api.oc.com",
                    "offline_access"
                ,                    
                AllowOfflineAccess = true
            
        ;
    

在我的 WEB API Startup.cs 中。我在 ConfigureServices 中有这个。我相信我的配置方法没问题。

        services.AddAuthentication(options =>
        
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        ).AddJwtBearer(o =>
        
            o.Authority = "https://localhost:44300";
            o.RequireHttpsMetadata = false;
            o.Audience = "api.oc.com";
        );

        services.AddMvcCore()
            .AddAuthorization()
            .AddJsonFormatters();

这将我带到了 WEB 前端,试图对 WEB API 进行身份验证。 我已经尝试过使用访问令牌和 ID 令牌,但似乎都没有。

使用访问令牌:

  var accessToken = await HttpContext.GetTokenAsync("access_token");
  var client = new HttpClient();
  client.SetBearerToken(accessToken);
  var result = await client.GetStringAsync("https://localhost:44302/api/text/welcome");

或使用客户端凭据流:

  var disco = await DiscoveryClient.GetAsync("https://localhost:44300");
  var tokenClient = new TokenClient(disco.TokenEndpoint, "oc.com", "SomeReallyStrongPassword1!");
  var tokenResponse = await tokenClient.RequestClientCredentialsAsync();

  var client = new HttpClient();
  client.SetBearerToken(tokenResponse.AccessToken);
  var result = await client.GetStringAsync("https://localhost:44302/api/text/welcome");

如果有人对此有任何煽动,我由衷地感谢。看了这么久的安全码,我的眼珠子都要爆炸了!哈哈。

谢谢, 迈克库什纳

【问题讨论】:

我要做的第一件事(在浪费时间将我的所有代码放在 SO 上之前)就是查看 API 中的日志。它们将包含有用的信息。 好吧,像往常一样多米尼克...你是个天才! :) 有几件事,我必须在 ConfigureServices 中设置策略并更改 UseMVC 的顺序。谢谢@leastprivilege,你让我走上了正确的道路,我的 IDP 现在正在工作! 【参考方案1】:

经过一些干预......并添加了一个真正的证书,这似乎在我创建了一些策略之后才起作用,而不仅仅是使用 [Authorize] 属性。 请注意,我也再次使用 IdentityServer4.AccessTokenValidation。

    public class Startup

    public void ConfigureServices(IServiceCollection services)
    
        services.AddMvc();
        services.AddAuthorization((options) => 
            options.AddPolicy("MustBeValidUser", policybuilder =>
            
                policybuilder.RequireAuthenticatedUser();
                policybuilder.Requirements = new[]  new MustBeValidUserRequirement() ;
            );
        );
        services.AddSingleton<IAuthorizationHandler, MustBeValidUserHandler>();
        services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
        .AddIdentityServerAuthentication(options =>
        
            options.Authority = "https://localhost:44300";
            options.RequireHttpsMetadata = true;
            options.ApiName = "api.oc.com";
        );
    

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    
        loggerFactory.AddConsole();
        app.UseDeveloperExceptionPage();
        app.UseAuthentication();
        app.UseMvc();
    

【讨论】:

以上是关于Core 2.0 上的 IdentityServer4 从 API 获取 401(未经授权)的主要内容,如果未能解决你的问题,请参考以下文章

.NET Core 2.0 正式发布信息汇总

protobuf-net 端口到 .net core 2.0 [关闭]

在grails 2.2.4 spring security core 2.0中配置ldap?

Azure Functions .NET Core 中的 EF Core 2.0 连接字符串

.Net Core 2.0 Windows 服务

如何在 Core 2.0 的 ConfigurationBuilder 中设置 BasePath