在没有 ASP.NET Core Identity 的 ASP.NET Core2.2 MVC Web 应用程序中实现外部社交登录时。成功登录 Google、Facebook、Twitter、LinkedIn 和 Microsoft 后,我在重定向回应用程序时收到以下错误。
处理请求时发生未处理的异常。 异常:无效的状态 cookie。未知地点
异常:处理远程登录时遇到错误。 Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()
以下是Startup.cs文件中的设置
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.IsEssential = true;
})
.AddGoogle(options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.ClientId = Configuration["Authentication:Google:ClientId"];
options.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
options.CallbackPath = "/externallogincallback";
})
.AddFacebook(facebookOptions =>
{
facebookOptions.AppId = Configuration["Authentication:Facebook:AppId"];
facebookOptions.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
facebookOptions.CallbackPath = "/externallogincallback";
})
.AddLinkedIn(linkedinOptions =>
{
linkedinOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
linkedinOptions.ClientId = Configuration["Authentication:LinkedIn:ClientId"];
linkedinOptions.ClientSecret = Configuration["Authentication:LinkedIn:ClientSecret"];
linkedinOptions.CallbackPath = "/externallogincallback";
})
.AddTwitter(twitterOptions =>
{
twitterOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
twitterOptions.ConsumerKey = Configuration["Authentication:Twitter:ConsumerKey"];
twitterOptions.ConsumerSecret = Configuration["Authentication:Twitter:ConsumerSecret"];
twitterOptions.CallbackPath = "/Home/externallogincallback";
}).AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
microsoftOptions.ClientId = Configuration["Authentication:Microsoft:ClientId"];
microsoftOptions.ClientSecret = Configuration["Authentication:Microsoft:ClientSecret"];
microsoftOptions.CallbackPath = "/externallogincallback";
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
以下是HomeController.cs的详细信息(由于我没有使用Identity,所以我需要专门定义重定向url。)
//Action to issue a challange to google login
public IActionResult LogInMicrosoft(string provider)
{
//provider = Microsot or Google or LinkedIn or Twitter or Facebook
provider = "Microsoft";
//Issue a challenge to external login middleware to trigger sign in process
//return new ChallengeResult(provider);
var authenticationProperties = new AuthenticationProperties
{
RedirectUri = Url.Action("externallogincallback")
};
return Challenge(authenticationProperties, provider);
//return new ChallengeResult(provider);
}
//Callback action to retrive signin user details
//public IActionResult externallogincallback(string returnUrl = null, string remoteError = null)\
public IActionResult externallogincallback()
{
//Here we can retrieve the claims
// read external identity from the temporary cookie
//var authenticateResult = HttpContext.GetOwinContext().Authentication.AuthenticateAsync("ExternalCookie");
var result = HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (result.Result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
// retrieve claims of the external user
var externalUser = result.Result.Principal;
if (externalUser == null)
{
throw new Exception("External authentication error");
}
// retrieve claims of the external user
var claims = externalUser.Claims.ToList();
// try to determine the unique id of the external user - the most common claim type for that are the sub claim and the NameIdentifier
// depending on the external provider, some other claim type might be used
//var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
var userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
if (userIdClaim == null)
{
throw new Exception("Unknown userid");
}
var externalUserId = userIdClaim.Value;
var externalProvider = userIdClaim.Issuer;
// use externalProvider and externalUserId to find your user, or provision a new user
return RedirectToAction("Privacy", "Home");
}
您似乎想在登录微软帐户后将请求重定向到
externallogincallback
。如果是这样,则不应将 microsoftOptions.CallbackPath
与 externallogincallback
设置。通过此设置,来自 Microsoft 的所有请求都将由 OAuth 中间件处理,而不是您自己的端点externallogincallback
。
对于登录后重定向页面,您需要通过设置
return Challenge(authenticationProperties, provider);
来传递
authenticationProperties.authenticationProperties
请按照以下步骤操作:
REDIRECT URI
更改 Azure 门户中的
https://localhost:xxx/signin-microsoft
将
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)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
//options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.IsEssential = true;
//options.Cookie.SameSite = SameSiteMode.None;
})
.AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
microsoftOptions.ClientId = Configuration["Authentication:Microsoft:ClientId"];
microsoftOptions.ClientSecret = Configuration["Authentication:Microsoft:ClientSecret"];
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
家庭控制器
public class HomeController : Controller
{
//Action to issue a challange to google login
public IActionResult LogInMicrosoft(string provider)
{
//provider = Microsot or Google or LinkedIn or Twitter or Facebook
provider = "Microsoft";
var authenticationProperties = new AuthenticationProperties
{
RedirectUri = Url.Action("externallogincallback")
};
return Challenge(authenticationProperties, provider);
}
[Route("/[action]")]
public async Task<IActionResult> externallogincallback()
{
var request = HttpContext.Request;
//Here we can retrieve the claims
// read external identity from the temporary cookie
//var authenticateResult = HttpContext.GetOwinContext().Authentication.AuthenticateAsync("ExternalCookie");
var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (result.Succeeded != true)
{
throw new Exception("External authentication error");
}
// retrieve claims of the external user
var externalUser = result.Principal;
if (externalUser == null)
{
throw new Exception("External authentication error");
}
// retrieve claims of the external user
var claims = externalUser.Claims.ToList();
// try to determine the unique id of the external user - the most common claim type for that are the sub claim and the NameIdentifier
// depending on the external provider, some other claim type might be used
//var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
var userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
if (userIdClaim == null)
{
throw new Exception("Unknown userid");
}
var externalUserId = userIdClaim.Value;
var externalProvider = userIdClaim.Issuer;
// use externalProvider and externalUserId to find your user, or provision a new user
return RedirectToAction("Privacy", "Home");
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
我通过确保在 Twitter 开发人员上创建的应用程序上配置的重定向路径恰好是“base_url/signin-twitter”来解决此问题。任何其他值都不起作用。
当用户单击登录/注册按钮时,您可以使用质询方法配置重定向路径:
Challenge(new AuthenticationProperties {RedirectUri = "/redirect/path" }, "Twitter");