Google OAuth 在我的 ASP.NET Core 7 WEB Api 项目中显示 OAuth 状态丢失或无效。

huangapple go评论70阅读模式
英文:

Google OAuth is showing oauth state was missing or invalid on my ASP.NET Core 7 WEB Api project

问题

I am trying to use IdentityServer on my asp.net core web api project with Google OAuth. So, my service configuration is:

我正在尝试在我的ASP.NET Core Web API项目中使用IdentityServer与Google OAuth。因此,我的服务配置如下:

public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration)
{
    if (configuration.GetValue<bool>("UseInMemoryDatabase"))
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseInMemoryDatabase("DreamBookDb"));
    }
    else
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                builder => builder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
    }

    services.AddScoped<IApplicationDbContext>(provider => provider.GetRequiredService<ApplicationDbContext>());
    services.AddScoped<ApplicationDbContextInitialiser>();

    services
        .AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddIdentityServer()
        .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

    services.AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = IdentityServerJwtConstants.IdentityServerJwtBearerScheme;
        x.DefaultChallengeScheme = IdentityServerJwtConstants.IdentityServerJwtBearerScheme;
    })
        .AddIdentityServerJwt()
        .AddGoogle(googleOptions =>
        {
            googleOptions.ClientId = configuration["Authentication:Google:ClientId"];
            googleOptions.ClientSecret = configuration["Authentication:Google:ClientSecret"];
            googleOptions.SignInScheme = IdentityServerJwtConstants.IdentityServerJwtBearerScheme;
        });

    return services;
}

I am using swagger to test it:

我使用Swagger进行测试:

static void AddSwaggerServices(IServiceCollection services, IConfiguration configuration)
{
    services.AddSwaggerGen(setup =>
    {
        setup.SwaggerDoc("v1", new OpenApiInfo { Title = "DreamBook", Version = "v1" });
        setup.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
        {
            Type = SecuritySchemeType.OAuth2,
            Flows = new OpenApiOAuthFlows()
            {
                AuthorizationCode = new OpenApiOAuthFlow()
                {
                    AuthorizationUrl = new Uri("https://accounts.google.com/o/oauth2/v2/auth"),
                    TokenUrl = new Uri("https://oauth2.googleapis.com/token")
                }
            }
        });
        setup.AddSecurityRequirement(
               new OpenApiSecurityRequirement
               {
                {
                    new OpenApiSecurityScheme{
                        Reference = new OpenApiReference{
                            Id = "oauth2", //The name of the previously defined security scheme.
                            Type = ReferenceType.SecurityScheme
                        },
                        Type=SecuritySchemeType.OAuth2
                    },
                    new List<string>()
                }
               });
    });
}

So, building configuration like this:

因此,构建配置如下:

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.OAuthClientId(builder.Configuration["Authentication:Google:ClientId"]);
        c.OAuthClientSecret(builder.Configuration["Authentication:Google:ClientSecret"]);
        c.OAuthScopes("https://www.googleapis.com/auth/userinfo.profile");
        c.OAuth2RedirectUrl("https://localhost:44385/signin-google");
        c.OAuthUsePkce();
    });
    // Initialize and seed database
    using (var scope = app.Services.CreateScope())
    {
        var initialiser = scope.ServiceProvider.GetRequiredService<ApplicationDbContextInitialiser>();
        await initialiser.InitialiseAsync();
        await initialiser.SeedAsync();
    }
}
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

My project type is Web Api based on Clean Architecture (Jayson Taylor). It doesn't have a controller for managing accounts since account management (creating, deleting, signing in, signing up, etc.) will be managed by the identity server (or maybe not. I am not sure here):

我的项目类型是基于Clean Architecture(Jayson Taylor)的Web API。它没有用于管理账户的控制器,因为账户管理(创建、删除、登录、注册等)将由Identity Server进行管理(或者可能不是。在这里我不确定)。

Now, I am trying testing it with swagger after signing in to Google Account and calling back, it is showing me the error oauth state was missing or invalid:

现在,我尝试使用Swagger进行测试,登录到Google账户并回调后,它显示了错误“oauth状态丢失或无效”:

I am not sure what I did wrong here. Also, the same problem is happening with Postman.

我不确定我在这里做错了什么。同时,使用Postman也出现了相同的问题。

I tested my client Id and client secret with an ASP.NET Core Web App using individual accounts authentication, and it is working fine. So, what am I doing wrong here, and how to implement Google OAuth in an ASP.NET Core Web API project with Identity Server?

我测试了我的客户端ID和客户端密钥,使用单独的账户身份验证的ASP.NET Core Web应用程序,它运行正常。所以,在这里我做错了什么,以及如何在ASP.NET Core Web API项目中使用Identity Server实现Google OAuth?

英文:

I am trying to use IdentityServer on my asp.net core web api project with Google OAuth. So, my service configuration is:

 public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration)
    {
        if (configuration.GetValue&lt;bool&gt;(&quot;UseInMemoryDatabase&quot;))
        {
            services.AddDbContext&lt;ApplicationDbContext&gt;(options =&gt;
                options.UseInMemoryDatabase(&quot;DreamBookDb&quot;));
        }
        else
        {
            services.AddDbContext&lt;ApplicationDbContext&gt;(options =&gt;
                options.UseSqlServer(configuration.GetConnectionString(&quot;DefaultConnection&quot;),
                    builder =&gt; builder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
        }

        services.AddScoped&lt;IApplicationDbContext&gt;(provider =&gt; provider.GetRequiredService&lt;ApplicationDbContext&gt;());
        services.AddScoped&lt;ApplicationDbContextInitialiser&gt;();

        services
            .AddDefaultIdentity&lt;ApplicationUser&gt;(options =&gt; options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores&lt;ApplicationDbContext&gt;();

        services.AddIdentityServer()
            .AddApiAuthorization&lt;ApplicationUser, ApplicationDbContext&gt;();

        services.AddAuthentication(x =&gt;
        {
            x.DefaultAuthenticateScheme = IdentityServerJwtConstants.IdentityServerJwtBearerScheme;
            x.DefaultChallengeScheme = IdentityServerJwtConstants.IdentityServerJwtBearerScheme;
        })
            .AddIdentityServerJwt()
            .AddGoogle(googleOptions =&gt;
        {
            googleOptions.ClientId = configuration[&quot;Authentication:Google:ClientId&quot;];
            googleOptions.ClientSecret = configuration[&quot;Authentication:Google:ClientSecret&quot;];
            googleOptions.SignInScheme = IdentityServerJwtConstants.IdentityServerJwtBearerScheme;
        });

        return services;
    }

I am using swagger to test it:

static void AddSwaggerServices(IServiceCollection services, IConfiguration configuration)
{
    services.AddSwaggerGen(setup =&gt;
    {
        setup.SwaggerDoc(&quot;v1&quot;, new OpenApiInfo { Title = &quot;DreamBook&quot;, Version = &quot;v1&quot; });
        setup.AddSecurityDefinition(&quot;oauth2&quot;, new OpenApiSecurityScheme
        {
            Type = SecuritySchemeType.OAuth2,
            Flows = new OpenApiOAuthFlows()
            {
                AuthorizationCode = new OpenApiOAuthFlow()
                {
                    AuthorizationUrl = new Uri(&quot;https://accounts.google.com/o/oauth2/v2/auth&quot;),
                    TokenUrl = new Uri(&quot;https://oauth2.googleapis.com/token&quot;)
                }
            }
        });
        setup.AddSecurityRequirement(
               new OpenApiSecurityRequirement
               {
                {
                    new OpenApiSecurityScheme{
                        Reference = new OpenApiReference{
                            Id = &quot;oauth2&quot;, //The name of the previously defined security scheme.
                            Type = ReferenceType.SecurityScheme
                        },
                        Type=SecuritySchemeType.OAuth2
                    },
                    new List&lt;string&gt;()
                }
               });
    });
}

So, building configuration like this:

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c =&gt;
    {
        c.OAuthClientId(builder.Configuration[&quot;Authentication:Google:ClientId&quot;]);
        c.OAuthClientSecret(builder.Configuration[&quot;Authentication:Google:ClientSecret&quot;]);
        c.OAuthScopes(&quot;https://www.googleapis.com/auth/userinfo.profile&quot;);
        c.OAuth2RedirectUrl(&quot;https://localhost:44385/signin-google&quot;);
        c.OAuthUsePkce();
    });
    // Initialize and seed database
    using (var scope = app.Services.CreateScope())
    {
        var initialiser = scope.ServiceProvider.GetRequiredService&lt;ApplicationDbContextInitialiser&gt;();
        await initialiser.InitialiseAsync();
        await initialiser.SeedAsync();
    }
}
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

My project type is Web Api based on Clean Architecture (Jayson Taylor). It doesn't have controller for managing account since account (creating, deleting, sign in, sign up...) will be managed by the identity server (or maybe not. I am not sure here):

Google OAuth 在我的 ASP.NET Core 7 WEB Api 项目中显示 OAuth 状态丢失或无效。

Now, I am trying testing it with swagger after sign in to Google Account and calling back it is showing me error oauth state was missing or invalid:
Google OAuth 在我的 ASP.NET Core 7 WEB Api 项目中显示 OAuth 状态丢失或无效。

I am not sure, what I did wrong here. Also, the same problem is happening with PostMan

I tested my client Id and client secret with Asp.Net Core Web App using induvidual accounts authentication and it is working fine. So, what I am doing wrong here and how to implement Google Oauth in asp.net core Web Api project with Identity server?

答案1

得分: 0

下面是代码部分的中文翻译:

所以,在我的情况下,请求应该从我的API发送。因此,我创建了身份验证控制器并添加了Google登录操作:

[HttpGet("google")]
public IActionResult Login()
{
    var redirectUrl = Url.Action(nameof(GoogleCallBack), "Auth");
    var properties = _signInManager.ConfigureExternalAuthenticationProperties(GoogleDefaults.AuthenticationScheme, redirectUrl);
    return Challenge(properties, GoogleDefaults.AuthenticationScheme);
}

这将重定向到与Google进行身份验证,完成后将返回到我的回调操作:

[AllowAnonymous]
[HttpGet("google-callBack")]
public async Task<IActionResult> GoogleCallBack()
{
    return Ok(await _authService.SignInWithGoogleAsync());
}

这个操作将创建一个用于Bearer身份验证的JWT令牌,我将使用它来进行身份验证。我还为我的Swagger添加了另一个身份验证。我的Swagger配置如下:

static void AddSwaggerServices(IServiceCollection services, IConfiguration configuration)
{
    services.AddSwaggerGen(setup =>
    {
        setup.SwaggerDoc("v1", new OpenApiInfo { Title = "DreamBook", Version = "v1" });
        setup.AddSecurityDefinition("OAuth", new OpenApiSecurityScheme
        {
            Type = SecuritySchemeType.OAuth2,
            Flows = new OpenApiOAuthFlows()
            {
                Implicit = new OpenApiOAuthFlow()
                {
                    AuthorizationUrl = new Uri("https://localhost:44385/api/Auth/google"),
                }
            }
        });
        setup.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
        {
            Description = "JWT授权标头,使用Bearer方案。在下面的文本输入中输入 'Bearer' [空格],然后输入您的令牌。示例:'Bearer 12345abcdef'",
            Name = "Authorization",
            In = ParameterLocation.Header,
            Type = SecuritySchemeType.ApiKey,
            Scheme = "Bearer"
        });
        var securityRequirement = new OpenApiSecurityRequirement();
        var securityScheme = new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference
            {
                Type = ReferenceType.SecurityScheme,
                Id = "Bearer"
            },
            Scheme = "Bearer",
            Name = "Bearer",
            In = ParameterLocation.Header,
        };
        securityRequirement.Add(securityScheme, new List<string>());
        setup.AddSecurityRequirement(securityRequirement);
    });
}
英文:

So, it looks like in my case request should be sent from my api. So I created auth controller and put google login action:

[HttpGet(&quot;google&quot;)]
public IActionResult Login()
{
    var redirectUrl = Url.Action(nameof(GoogleCallBack), &quot;Auth&quot;);
    var properties = _signInManager.ConfigureExternalAuthenticationProperties(GoogleDefaults.AuthenticationScheme, redirectUrl);
    return Challenge(properties, GoogleDefaults.AuthenticationScheme);
}

This will redirect to authenticate with google, after finishing it will be back on my call back action:

[AllowAnonymous]
[HttpGet(&quot;google-callBack&quot;)]
public async Task&lt;IActionResult&gt; GoogleCallBack()
{
    return Ok(await _authService.SignInWithGoogleAsync());
}

This action will create a JWT token for Bearer Auth which I will use it to auth. I added another auth for my swagger as well. My swagger configuration looks like this:

 static void AddSwaggerServices(IServiceCollection services, IConfiguration configuration)
    {
        services.AddSwaggerGen(setup =&gt;
        {
            setup.SwaggerDoc(&quot;v1&quot;, new OpenApiInfo { Title = &quot;DreamBook&quot;, Version = &quot;v1&quot; });
            setup.AddSecurityDefinition(&quot;OAuth&quot;, new OpenApiSecurityScheme
            {
                Type = SecuritySchemeType.OAuth2,
                Flows = new OpenApiOAuthFlows()
                {
                    Implicit = new OpenApiOAuthFlow()
                    {
                        AuthorizationUrl = new Uri($&quot;https://localhost:44385/api/Auth/google&quot;),
                    }
                }
            });
            setup.AddSecurityDefinition(&quot;Bearer&quot;, new OpenApiSecurityScheme
            {
                Description = &quot;JWT Authorization header using the Bearer scheme. Enter &#39;Bearer&#39; [space] and then your token in the text input below. Example: &#39;Bearer 12345abcdef&#39;&quot;,
                Name = &quot;Authorization&quot;,
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey,
                Scheme = &quot;Bearer&quot;
            });
            var securityRequirement = new OpenApiSecurityRequirement();
            var securityScheme = new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = &quot;Bearer&quot;
                },
                Scheme = &quot;Bearer&quot;,
                Name = &quot;Bearer&quot;,
                In = ParameterLocation.Header,

            };
            securityRequirement.Add(securityScheme, new List&lt;string&gt;());
            setup.AddSecurityRequirement(securityRequirement);
        });
    }

huangapple
  • 本文由 发表于 2023年2月6日 19:44:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75360886.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定