异常:oauth 状态丢失或无效。 (ASP.NET 核心外部标识符 OAuth)
Exception: The oauth state was missing or invalid. (ASP.NET Core external identifier OAuth)
我正在尝试在 Asp.Net Core 中实现外部 OAuth(https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers). My application (GitLab) has Callback URL https://myhost.com/signin-gitlab(中间件默认使用)。
如果我 运行 下面的代码,我得到“异常:oauth 状态丢失或无效。”但是,如果我从 Startup.cs 中删除“options.UserInformationEndpoint”,那么我将使用代码和状态参数重定向到 myhost.com/signin-gitlab,中间件应将其交换为访问令牌。我的问题是,为什么我的状态参数会损坏(使用 UserInformationEndpoint)?为什么我没有获得访问令牌?我在这里错过了什么?
我的创业公司class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using AspNet.Security.OAuth.GitLab;
using System.Net.Http;
using System.Net.Http.Headers;
namespace MyApp
{
public class Startup
{
private readonly IConfiguration _cfg;
public Startup(IConfiguration configuration) => _cfg = configuration;
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie()
.AddGitLab("Gitlab", options => {
options.ClientId = "...";
options.ClientSecret = "...";
options.AuthorizationEndpoint = "https://mygitlabserver.com/oauth/authorize";
options.TokenEndpoint = "https://mygitlabserver.com/oauth/token";
options.Scope.Clear();
options.Scope.Add("api");
options.SaveTokens = true;
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.UserInformationEndpoint = "https://mygitlabserver.com/api/v4/user";
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
}
我的控制器:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
namespace MyApp.Controllers
{
public class HomeController : Controller
{
[HttpGet("/")]
public IActionResult Index()
{
return View();
}
[HttpGet("/login")]
public IActionResult LogIn()
{
// Instruct the middleware corresponding to the requested external identity
// provider to redirect the user agent to its own authorization endpoint.
// Note: the authenticationScheme parameter must match the value configured in Startup.cs
return Challenge(new AuthenticationProperties { RedirectUri = "https://myhost.com/signin-gitlab" }, "Gitlab");
}
}
}
首先,ASP.NET 外部身份 provider/social 登录要么使用身份框架,要么不使用身份框架。如果没有 Identity,应该这样设置 (https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/social-without-identity?view=aspnetcore-5.0):
public void ConfigureServices(IServiceCollection services)
{
// requires
// using Microsoft.AspNetCore.Authentication.Cookies;
// using Microsoft.AspNetCore.Authentication.Google;
// NuGet package Microsoft.AspNetCore.Authentication.Google
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie()
.AddGoogle(options =>
{
options.ClientId = Configuration["Authentication:Google:ClientId"];
options.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
});
services.AddRazorPages();
}
第二个问题在控制器内部:
return Challenge(new AuthenticationProperties { RedirectUri = "https://myhost.com/signin-gitlab" }, "Gitlab");
就像 aspnet-contrib 团队 (https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/blob/dev/samples/Mvc.Client/Controllers/AuthenticationController.cs) 的 MVC 示例应用程序一样,它实际上应该是:
return Challenge(new AuthenticationProperties { RedirectUri = "/" }, "Gitlab");
用户实际上已经过身份验证,问题是他们随后被重定向到没有状态或代码参数的 OAuth 中间件的内部路由 /signin-gitlab 而不是 home route/index 操作,因此出现错误。
也就是说,我搞混了:
- RedirectUri(用户在身份验证后重定向)
- 回调URL(OAuth 应用程序将带有状态和代码的用户重定向到 OAuth 中间件内部路由,默认情况下为 /signin-gitlab、/signin-google、/signin -facebook 但也可以用 options.CallbackPath).
覆盖
也许我的困惑是由于回调 url 在 GitLab 文档 (https://docs.gitlab.com/ee/api/oauth2.html) 中被称为 REDIRECT_URI。
感谢南宇() and Tratcher (https://github.com/dotnet/aspnetcore/issues/22125, https://github.com/aspnet/Security/issues/1756) 的精彩帖子。
我正在尝试在 Asp.Net Core 中实现外部 OAuth(https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers). My application (GitLab) has Callback URL https://myhost.com/signin-gitlab(中间件默认使用)。
如果我 运行 下面的代码,我得到“异常:oauth 状态丢失或无效。”但是,如果我从 Startup.cs 中删除“options.UserInformationEndpoint”,那么我将使用代码和状态参数重定向到 myhost.com/signin-gitlab,中间件应将其交换为访问令牌。我的问题是,为什么我的状态参数会损坏(使用 UserInformationEndpoint)?为什么我没有获得访问令牌?我在这里错过了什么?
我的创业公司class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using AspNet.Security.OAuth.GitLab;
using System.Net.Http;
using System.Net.Http.Headers;
namespace MyApp
{
public class Startup
{
private readonly IConfiguration _cfg;
public Startup(IConfiguration configuration) => _cfg = configuration;
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie()
.AddGitLab("Gitlab", options => {
options.ClientId = "...";
options.ClientSecret = "...";
options.AuthorizationEndpoint = "https://mygitlabserver.com/oauth/authorize";
options.TokenEndpoint = "https://mygitlabserver.com/oauth/token";
options.Scope.Clear();
options.Scope.Add("api");
options.SaveTokens = true;
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.UserInformationEndpoint = "https://mygitlabserver.com/api/v4/user";
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
}
我的控制器:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
namespace MyApp.Controllers
{
public class HomeController : Controller
{
[HttpGet("/")]
public IActionResult Index()
{
return View();
}
[HttpGet("/login")]
public IActionResult LogIn()
{
// Instruct the middleware corresponding to the requested external identity
// provider to redirect the user agent to its own authorization endpoint.
// Note: the authenticationScheme parameter must match the value configured in Startup.cs
return Challenge(new AuthenticationProperties { RedirectUri = "https://myhost.com/signin-gitlab" }, "Gitlab");
}
}
}
首先,ASP.NET 外部身份 provider/social 登录要么使用身份框架,要么不使用身份框架。如果没有 Identity,应该这样设置 (https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/social-without-identity?view=aspnetcore-5.0):
public void ConfigureServices(IServiceCollection services)
{
// requires
// using Microsoft.AspNetCore.Authentication.Cookies;
// using Microsoft.AspNetCore.Authentication.Google;
// NuGet package Microsoft.AspNetCore.Authentication.Google
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie()
.AddGoogle(options =>
{
options.ClientId = Configuration["Authentication:Google:ClientId"];
options.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
});
services.AddRazorPages();
}
第二个问题在控制器内部:
return Challenge(new AuthenticationProperties { RedirectUri = "https://myhost.com/signin-gitlab" }, "Gitlab");
就像 aspnet-contrib 团队 (https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/blob/dev/samples/Mvc.Client/Controllers/AuthenticationController.cs) 的 MVC 示例应用程序一样,它实际上应该是:
return Challenge(new AuthenticationProperties { RedirectUri = "/" }, "Gitlab");
用户实际上已经过身份验证,问题是他们随后被重定向到没有状态或代码参数的 OAuth 中间件的内部路由 /signin-gitlab 而不是 home route/index 操作,因此出现错误。
也就是说,我搞混了:
- RedirectUri(用户在身份验证后重定向)
- 回调URL(OAuth 应用程序将带有状态和代码的用户重定向到 OAuth 中间件内部路由,默认情况下为 /signin-gitlab、/signin-google、/signin -facebook 但也可以用 options.CallbackPath). 覆盖
也许我的困惑是由于回调 url 在 GitLab 文档 (https://docs.gitlab.com/ee/api/oauth2.html) 中被称为 REDIRECT_URI。
感谢南宇(