我尝试在我的应用程序中实现 Okta 登录。在编辑真正的应用程序之前,我正在运行一个测试应用程序来弄清楚它。我加载了 url,它按应有的方式通过 Okta 进行身份验证。然后它会在页面上显示“正在加载...”几秒钟,然后给出错误:
LocalRedirect(redirectUri) 应重定向到“/”。相反,它再次循环回到登录函数。
LoginController.cs:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
namespace TestOktaLogin.Controllers {
public class LoginController : Controller {
[HttpGet("Login")]
public IActionResult Login([FromQuery] string returnUrl) {
var redirectUri = returnUrl is null ? "/" : "/" + returnUrl;
if (User.Identity.IsAuthenticated) {
return LocalRedirect(redirectUri); //It does not return. It just reloads the function.
}
return Challenge();
}
// This is the method the Logout button should get to when clicked.
[HttpGet("Logout")]
public async Task<ActionResult> Logout([FromQuery] string returnUrl) {
var redirectUri = returnUrl is null ? Url.Content("~/") : "/" + returnUrl;
if (!User.Identity.IsAuthenticated) {
return LocalRedirect(redirectUri);
}
await HttpContext.SignOutAsync();
return LocalRedirect(redirectUri);
}
}
}
RedirectToLogin.razor.cs:
using Microsoft.AspNetCore.Components;
namespace TestOktaLogin.Components {
public partial class RedirectToLogin : ComponentBase {
[Inject] public NavigationManager Navigation { get; set; }
protected override async Task OnInitializedAsync() {
var returnUrl = Navigation.ToBaseRelativePath(Navigation.Uri);
Navigation.NavigateTo($"Login?returnUrl={returnUrl}", true);
}
}
}```
Home.razor, which is the default to "/":
@页面“/”
@属性[授权]
首页
欢迎使用您的新应用程序。```
程序.cs:
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using TestOktaLogin.Components;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddMvc();
builder.Services.AddAuthentication(authOptions => {
authOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
authOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
authOptions.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
authOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}).AddOpenIdConnect(oidcOptions => {
oidcOptions.ClientId = builder.Configuration["Okta:ClientId"];
oidcOptions.ClientSecret = builder.Configuration["Okta:ClientSecret"];
oidcOptions.CallbackPath = "/authorization-code/callback";
oidcOptions.Authority = builder.Configuration["Okta:Issuer"];
oidcOptions.ResponseType = "code";
oidcOptions.SaveTokens = true;
oidcOptions.Scope.Add("openid");
oidcOptions.Scope.Add("profile");
oidcOptions.TokenValidationParameters.ValidateIssuer = false;
oidcOptions.TokenValidationParameters.NameClaimType = "name";
}).AddCookie();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment()) {
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// 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.UseAntiforgery();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
如果我需要上传任何其他代码,请告诉我。谢谢您的帮助!
您有以下循环:
User -> Login -> Okta -> LoginController -> LocalRedirect -> Home (Authorized)
^ |
|__________________________________________________________________|
发生该循环是因为在
LocalRedirect
之后,用户被重定向回登录过程而不是主页。
在
Login
操作中,您将检查用户是否已通过身份验证,然后执行 LocalRedirect
。Challenge
方法已正确放置以启动身份验证过程。
循环并非源自
Challenge
本身,但如果在用户经过身份验证后可能会发生:它们被重定向回需要身份验证的路由,并且 Authorize
属性 将它们重定向回登录页面,因为它无法识别用户已通过身份验证。
另请参阅“ASP.NET Core 身份验证概述”
您的
LoginController
中发出 Challenge
的具体部分:
if (User.Identity.IsAuthenticated) {
return LocalRedirect(redirectUri); // If authenticated, redirect to the return URL or home
} else {
return Challenge(); // If not authenticated, initiate the authentication process
}
潜在的问题可能与
LocalRedirect(redirectUri)
行有关:如果 redirectUri
在某种程度上配置错误并重定向回最终再次重定向到 /Login
的页面(就像 RedirectToLogin
组件可能会做的那样),这会创建一个循环。该循环将继续下去,直到浏览器由于重定向过多而停止它,从而导致您看到的“Too Many Requests
”错误。
此外,
Program.cs
中的中间件可能配置错误,未正确维护身份验证状态或在Authorize
中使用不正确的Home.razor
属性用法。
要调试此问题:
redirectUri
在身份验证后是有效且可访问的路由。Home
页面识别身份验证状态并且不会重定向回Login
页面。Program.cs
中的身份验证中间件是否正确配置为处理登录后的身份验证状态。如果这些检查全部正确,则应该打破循环,并且用户应该在身份验证后正确重定向到主页。
确保您的
Login
操作在身份验证成功后不会再次被调用。redirectUri
逻辑并确保 Challenge
仅在必要时出现来完成。
您的
LoginController
将是:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
namespace TestOktaLogin.Controllers {
public class LoginController : Controller {
[HttpGet("Login")]
public IActionResult Login([FromQuery] string returnUrl) {
// Make sure returnUrl is not causing a loop back to this action
var redirectUri = Url.IsLocalUrl(returnUrl) && !string.IsNullOrEmpty(returnUrl)
? returnUrl
: "/";
if (User.Identity.IsAuthenticated) {
// Redirect to the original requested resource or home if authenticated
return LocalRedirect(redirectUri);
}
// Only issue a challenge if the user is not authenticated
return Challenge();
}
// Rest of your code
}
}
您现在需要检查以确保
returnUrl
是本地的,而不是 null
或空,以防止重定向到可能导致循环的未经授权的路由。
对于
RedirectToLogin
组件,请确保仅在用户未经身份验证的情况下使用它,否则,它也可能会导致循环。
您还需要确保您的 OpenID Connect 配置和
Authorize
中的 Home.razor
属性使用设置正确,以防止未经授权的访问,这可能会导致重定向回登录过程。