【问题标题】:Getting Claims from Google in ASP.Net Core 2.1 using OpenIdDict使用 OpenIdDict 在 ASP.Net Core 2.1 中从 Google 获取声明
【发布时间】:2019-05-18 11:00:02
【问题描述】:

我在使用 OpenIdDict 在 ASP.Net Core 2.1 Web API 中从 Google 获取声明时遇到了一些问题。

我在 ASP.Net MVC 模板中选择了“无身份验证”,因为我对自己存储用户名/密码没有兴趣。我将依赖外部提供商(例如 Google)进行身份验证。客户端是 SPA,所以我使用的是 Implicit Flow。

我的代码基于遵循本教程(使用 Google 而不是 GitHub 除外): https://www.jerriepelser.com/blog/implementing-openiddict-authorization-server-part-2/

Google 正在返回一个令牌 - 但当我检查 JWT 时,它不包含任何声明信息。 我错过了什么?

我的 Startup.cs 看起来像:

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)
    {

        // Register OpenIdDict database (EF Core)
        services.AddDbContext<PD.Server.DataAccess.AuthorizationDbContext>(o => 
            { 
                o.UseSqlServer(Configuration.GetConnectionString("AuthorizationDbContext"));
                o.UseOpenIddict();
            });

        // Authentication
        services.AddAuthentication(auth =>
        {
            auth.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            auth.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            auth.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        }).AddCookie()
        .AddGoogle(o =>
        {
            o.ClientId = Configuration["Authentication:Google:ClientId";
            o.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
            o.CallbackPath = "/signin-google";
        });

        services.AddOpenIddict()
        .AddCore(o => o.UseEntityFrameworkCore().UseDbContext<AuthorizationDbContext>() )
        .AddServer(o =>
        {
            o.UseMvc();                                                                 // Register MVC Binder
            o.EnableAuthorizationEndpoint("/connect/authorize")
             .EnableLogoutEndpoint("/connect/logout");                                  // Enable the Authorization end-point

            o.RegisterScopes(OpenIddictConstants.Scopes.Email, 
                             OpenIddictConstants.Scopes.Profile,
                             OpenIddictConstants.Scopes.Roles);

            o.AllowImplicitFlow();                                                      // Enable Implicit Flow (i.e. OAuth2 authentication for SPA's)

            o.EnableRequestCaching();

            o.DisableHttpsRequirement();                                                // DEV ONLY!
            o.AddEphemeralSigningKey();                                                 // DEV ONLY!

        })
        .AddValidation();

        // Cors
        services.AddCors();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }


    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseCors(builder =>
        {
            builder.WithOrigins("https://localhost:5001");
            builder.WithMethods("GET");
            builder.WithHeaders("Authorization");
        });

        app.UseAuthentication();
        app.UseMvcWithDefaultRoute();
        app.MigrateDatabase();

        // Configure the OpenIdDict Database (not shown)
        InitializeAsync(app.ApplicationServices, CancellationToken.None).GetAwaiter().GetResult();
    }

还有我的 Authenticate 方法:

    [HttpGet("~/connect/authorize")]
    public IActionResult Authorize(OpenIdConnectRequest request)
    {
        if (!User.Identity.IsAuthenticated) return Challenge("Google");

        var claims = new List<Claim>();
        claims.Add(new Claim(OpenIdConnectConstants.Claims.Subject, User.FindFirstValue(ClaimTypes.NameIdentifier), OpenIdConnectConstants.Destinations.IdentityToken));
        claims.Add(new Claim(OpenIdConnectConstants.Claims.Name, User.FindFirstValue(ClaimTypes.Name), OpenIdConnectConstants.Destinations.IdentityToken));
        claims.Add(new Claim(OpenIdConnectConstants.Claims.Email, User.FindFirstValue(ClaimTypes.Email), OpenIdConnectConstants.Destinations.IdentityToken));
        claims.Add(new Claim(OpenIdConnectConstants.Claims.EmailVerified, "true", OpenIdConnectConstants.Destinations.IdentityToken));
        var identity = new ClaimsIdentity(claims, "OpenIddict");            
        var principle = new ClaimsPrincipal(identity);

        // Create a new Authentication Ticket
        var ticket = new AuthenticationTicket(principle, new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme);

        return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
    }

提前致谢。

【问题讨论】:

  • 智威汤逊令牌,你的意思是身份令牌?您是否尝试启用日志记录(并将默认日志级别降低到 Trace)以查看日志消息中是否有任何内容可以让您走上正轨。
  • 是的,ID 令牌(我正在使用 jwt.io 检查)。日志中有几件事可能是我沮丧的根源: dbug: OpenIddict.Server.Internal.OpenIddictServerHandler[0] 'email' 已从身份令牌声明中排除。信息:Microsoft.AspNetCore.Cors.Infrastructure.CorsService[5] 策略执行失败。信息:Microsoft.AspNetCore.Cors.Infrastructure.CorsService[6] 请求来源jwt.io 没有访问资源的权限。
  • 宽松的 CORS - 所以 jwi.io 请求成功。但在 jwt.io 中仍然没有显示名称或电子邮件声明。

标签: jwt asp.net-core-2.1 openiddict


【解决方案1】:

您的索赔目的地设置不正确。

当使用带有 3 个参数的 Claim 构造函数时,实际设置的是声明值类型,而不是目标(这是 OpenIddict 特有的概念)。

考虑使用以下语法:

claims.Add(new Claim(OpenIdConnectConstants.Claims.Email, User.FindFirstValue(ClaimTypes.Email)).SetDestinations(OpenIdConnectConstants.Destinations.IdentityToken));

【讨论】:

  • 谢谢! .SetDestinations 代替了 OpenIdConnectConstants.Destinations 常量。
猜你喜欢
  • 2020-01-07
  • 2019-05-14
  • 2020-01-17
  • 2023-03-23
  • 2019-03-07
  • 2019-04-15
  • 2020-07-27
  • 2018-06-16
  • 2017-09-17
相关资源
最近更新 更多