【问题标题】:IdentityServer4 and Code with PKCE testing with PostmanIdentityServer4 和使用 Postman 进行 PKCE 测试的代码
【发布时间】:2020-05-03 07:40:44
【问题描述】:

我开始使用 IdentityServer4,并通过资源所有者流程完成了它,但由于不再推荐使用 PKCE,我决定更改它。我收到以下错误消息,这很明显,因为我不再使用 GrantTypes.ResourceOwnerPassword

fail: IdentityServer4.Validation.TokenRequestValidator[0]
      Client not authorized for resource owner flow, check the AllowedGrantTypes setting{ client_id = trusted }, details: {
        "ClientId": "trusted",
        "ClientName": "Dayum Client",
        "GrantType": "password",
        "Raw": {
          "grant_type": "password",
          "username": "Admin",
          "password": "***REDACTED***",
          "scope": "openid profile offline_access api1",
          "client_id": "trusted"
        }
      }

我没有找到太多信息,因为它是新的,但我应该如何使用 Postman 对其进行测试?我曾经使用资源所有者流程执行以下操作:

POST http://localhost:58508/connect/token
grant_type = password
username=Admin
password=123456
scope=openid profile offline_access api1
client_id=trusted

我知道我不能再使用带有 PKCE 的代码来做到这一点。如何请求访问和刷新令牌,如何使用 Postman 对其进行测试?

代码:

public static class Config
{
    public static IEnumerable<IdentityResource> GetResources() =>
        new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile()
        };

    public static IEnumerable<ApiResource> GetApis() =>
        new List<ApiResource>
        {
            new ApiResource("api1", "My API")
        };

    public static IEnumerable<Client> GetClients() =>
        new List<Client>
        {
            new Client
            {
                ClientId = "trusted",
                ClientName = "Dayum Client",
                //ClientSecrets = { new Secret("xxxxxxxxxxxxxxxxxxxxxxx".Sha256()) },

                RequireConsent = false,
                RequireClientSecret = false,
                AllowedGrantTypes = GrantTypes.Code,
                RequirePkce = true,

                AllowAccessTokensViaBrowser = true,
                RedirectUris = { "http://localhost:58508" },
                PostLogoutRedirectUris = { "http://localhost:58508" },

                AllowedScopes =
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    IdentityServerConstants.StandardScopes.OfflineAccess,
                    "api1"
                },

                AccessTokenType = AccessTokenType.Jwt,  
                AccessTokenLifetime = 900,

                AllowOfflineAccess = true,
                RefreshTokenExpiration = TokenExpiration.Absolute,
                RefreshTokenUsage = TokenUsage.OneTimeOnly,
                AbsoluteRefreshTokenLifetime = 1800
            }
        };
}

public class Startup
{
    public IWebHostEnvironment Environment { get; }
    public IConfiguration Configuration { get; }

    public Startup(IWebHostEnvironment environment, IConfiguration configuration)
    {
        Environment = environment;
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration["ConnectionStrings:DayumConnection"],
                optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));

        services.AddIdentity<ApplicationUser, IdentityRole>(options =>
        {
            options.Password.RequireDigit = false;
            options.Password.RequireLowercase = false;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = false;
            options.Password.RequiredLength = 6;
        })
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddIdentityServer(options =>
        {
            options.Events.RaiseErrorEvents = true;
            options.Events.RaiseInformationEvents = true;
            options.Events.RaiseFailureEvents = true;
            options.Events.RaiseSuccessEvents = true;
        })
            .AddSigningCredential(new X509Certificate2(Configuration["Certificates:Default:Path"], Configuration["Certificates:Default:Password"]))
            .AddConfigurationStore(options =>
            {
                options.ConfigureDbContext = builder => builder.UseSqlServer(Configuration["ConnectionStrings:DayumConnection"],
                    optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName));
            })
            .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = builder => builder.UseSqlServer(Configuration["ConnectionStrings:DayumConnection"],
                    optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName));

                options.EnableTokenCleanup = true;
            })
            .AddProfileService<ProfileService>()
            .AddAspNetIdentity<ApplicationUser>();
    }

    public void Configure(IApplicationBuilder app)
    {
        using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
        {
            serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();

            var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
            context.Database.Migrate();
            if (!context.Clients.Any())
            {
                foreach (var client in Config.GetClients())
                {
                    context.Clients.Add(client.ToEntity());
                }
                context.SaveChanges();
            }

            if (!context.IdentityResources.Any())
            {
                foreach (var resource in Config.GetResources())
                {
                    context.IdentityResources.Add(resource.ToEntity());
                }
                context.SaveChanges();
            }

            if (!context.ApiResources.Any())
            {
                foreach (var resource in Config.GetApis())
                {
                    context.ApiResources.Add(resource.ToEntity());
                }
                context.SaveChanges();
            }
        }

        if (Environment.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseIdentityServer();

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

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

【问题讨论】:

    标签: c# asp.net-core identityserver4 asp.net-core-3.1


    【解决方案1】:

    首先,最新版本的 Postman 应用程序 (v7.23.0) 提供了对 OAuth 2.0 的 PKCE 支持,请将您的 Postman 更新到最新版本。

    然后在 Postman 的 Authorization 标头中,将 Type 设置为 OAuth2 并单击 Get New Access Token 按钮,将 Grant Type 设置为 Authorization code(With PKCE) 并设置端点/客户端信息如下:

    Auth url/Access Token Url 是您的身份服务器 4 的端点,并将 Callback url 替换为您的客户端应用程序的重定向 url 。我注意到在您的代码中,您在身份服务器和客户端中设置了相同的端点/url 主机(http://localhost:58508),请根据您的实际需求进行修改。

    【讨论】:

    • 您在一个应用程序中制作身份服务器应用程序和客户端应用程序?并删除 openid profile 范围,因为您使用的是 oauth2 ,用户未通过身份验证您是否配置并输入正确的用户凭据?
    • 问题是我想在没有前端的情况下测试它,我还没有在 ASP.NET Core 中内置 Angular。我只在范围内留下了 api1,因为我在我的配置中有它。这次我做了一个gif,因为有点难以解释i.imgur.com/S0y2GF2.gif。返回错误:No client identifier foundpastebin.com/zNrMR4mT
    • 看来你已经获得了访问令牌。所以当将令牌发送到 web api 时会导致这个问题?您的 Web api 在哪里以及如何保护它?还要解码令牌并检查其中的客户端 ID 是什么,
    • 其实我切换到这个模板github.com/jasontaylordev/CleanArchitecture/tree/master/src是因为它支持angular + IS4(AddApiAuthorization方式)并且它还使用了推荐使用的PKCE和更少的代码(dotnet new angular --auth Individual)。这些是我的邮递员设置:i.imgur.com/bH5NYsZ.png,这是结果:pastebin.com/0YUE67J1(显示登录:用户未通过身份验证)。它会将我重定向到登录页面。这是正常行为吗?
    猜你喜欢
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 1970-01-01
    • 2021-04-06
    • 2021-07-23
    • 2018-05-18
    • 1970-01-01
    相关资源
    最近更新 更多