【发布时间】:2020-07-06 12:06:18
【问题描述】:
我们有一个使用 ASP.NET Membership 进行用户身份验证的 .net MVC Web 应用程序。我们还为我们的移动应用程序发行不记名令牌。我正在尝试以 okta 为例来添加对 SSO 的支持。我在 Okta 中创建了一个应用程序,并正在尝试登录我们的应用程序。我目前的流程如下:
- 打开登录页面
- 点击“使用 okta 登录”
- 我们的服务器收到请求。用户未通过身份验证,因此发出了质询
- 用户被重定向到 Okta 的登录页面
- 成功登录后,会向登录重定向 url 发出请求(我想它是由 OpenIdConnect 中间件捕获的?)
- AuthorizationCodeReceived 事件被触发。
- 重定向完成,但未发出 cookie
- 用户被重定向到登录页面,但由于他们没有经过身份验证,它会重定向到 Okta 进行登录。循环回到第 4 步并重复。
似乎在登录重定向并且我设置了正确的声明之后,结果应该是应该发出一个 cookie 并在响应中返回以表示用户已登录。我不确定我在做什么在这里失踪,但如果有人能指出我正确的方向,或解释正在发生的事情,我将非常感激!
下面是我们 Startup.cs 中的一个 sn-p:
public void ConfigureAuth(IAppBuilder app, bool allowInsecureHttp = false)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(OwinIdentityDbContext.Create);
app.CreatePerOwinContext<IdentityUserManager>(IdentityUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = GlobalConstants.Settings.OktaClientId,
ClientSecret = GlobalConstants.Settings.OktaClientSecret,
Authority = GlobalConstants.Settings.OktaDomain,
AuthenticationType = "okta", // This is basically a "name" for this open id configuration
RedirectUri = GlobalConstants.Settings.OktaRedirectUri,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
Scope = $"{OpenIdConnectScope.OpenIdProfile} {OpenIdConnectScope.Email}", // Get the profile and email
PostLogoutRedirectUri = GlobalConstants.Settings.OktaPostLogoutRedirectUri,
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name"
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
// Exchange code for access and ID tokens
var tokenClient = new TokenClient(GlobalConstants.Settings.OktaDomain + "/v1/token", GlobalConstants.Settings.OktaClientId, GlobalConstants.Settings.OktaClientSecret);
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, GlobalConstants.Settings.OktaRedirectUri);
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
var userInfoClient = new UserInfoClient(GlobalConstants.Settings.OktaDomain + "/v1/userinfo");
var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
var claims = new List<Claim>();
claims.AddRange(userInfoResponse.Claims);
claims.Add(new Claim("id_token", tokenResponse.IdentityToken));
claims.Add(new Claim("access_token", tokenResponse.AccessToken));
if (!string.IsNullOrEmpty(tokenResponse.RefreshToken))
{
claims.Add(new Claim("refresh_token", tokenResponse.RefreshToken));
}
// Add custom user claims here
#region Add custom claims
var email = claims.Find(_ => _.Type == "email")?.Value;
claims.Add(new Claim(ClaimTypes.Name, email));
claims.Add(new Claim(ClaimTypes.NameIdentifier, email));
// Hardcoded for now. Discover these for real later
claims.Add(new Claim(CustomClaimTypes.OurUserId, "{userId}"));
claims.Add(new Claim(CustomClaimTypes.OurOrganizationId, "{orgId}"));
#endregion
// https://stackoverflow.com/questions/55797063/asp-net-owin-openid-connect-not-creating-user-authentication
var identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.Name, ClaimTypes.Role);
n.AuthenticationTicket = new AuthenticationTicket(identity, n.AuthenticationTicket.Properties);
n.AuthenticationTicket.Identity.AddClaims(claims);
return;
},
RedirectToIdentityProvider = n =>
{
// If signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var idTokenClaim = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenClaim != null)
{
n.ProtocolMessage.IdTokenHint = idTokenClaim.Value;
}
}
return Task.CompletedTask;
}
},
});
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
CookieManager = new SystemWebCookieManager(),
LoginPath = new PathString("/"),
SlidingExpiration = true,
CookieSecure = GlobalConstants.Settings.IsEnvironmentDev ? CookieSecureOption.SameAsRequest : CookieSecureOption.Always,
Provider = new CookieAuthenticationProvider
{
OnApplyRedirect = context =>
{
if (IsClientPortalRequest(context.Request))
{
context.Response.Redirect("/public/ClientPortalLogin");
}
else if (!IsAjaxRequest(context.Request) && !IsPublicApiRequest(context.Request) && !IsWopiRequest(context.Request))
{
context.Response.Redirect(context.RedirectUri);
}
}
}
});
// For Two Factor Log In
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(10));
OAuthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = allowInsecureHttp, // NOTE: Only for unit tests
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new CustomBearerTokenProvider()
};
// Configure Bearer Token Generation
app.UseOAuthAuthorizationServer(OAuthOptions);
// Needed to Authenticate Bearer Tokens
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
// Set Cookies are the default type
app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ApplicationCookie);
}
【问题讨论】:
-
服务器是否正在创建身份验证cookie并保存在浏览器中?可以在浏览器中使用开发者工具查看吗?
-
当我检查响应的 cookie 时,有一个名为 "OpenIdConnect.nonce.lmY6ycbG52f%2BQeGNuvsb32vwVZnKZSPVof0xJ7VE%2FgY%3D" 的厨师,这是请求的 cookie 的名称,值为空白
-
@chronolinq 你解决过这个问题吗?我正在更新旧版 ASPNET MVC 5 应用程序以使用 OpenIdConnect 并具有完全相同的症状 - 身份验证有效,但它重定向到没有设置 ApplicationCookie 的 Home 控制器,因此重定向回 Idp 登录页面,该页面立即进行身份验证,重定向回 Home等等等等 - 我不知道为什么没有设置 ApplicationCookie,OpenIdConnect.nonce 和 OpenIdConnect.nv cookie 在身份验证过程中设置并在来自 /signin-oidc 的 Home 重定向中清除(OpenIdConnect 中间件必须处理) - 热衷于收到你的来信:)
标签: .net asp.net-mvc owin openid-connect okta