如何将 OpenID 结合 Forms Authentication 添加到 MVC
Posted
技术标签:
【中文标题】如何将 OpenID 结合 Forms Authentication 添加到 MVC【英文标题】:How to add OpenID combined with Forms Authentication to MVC 【发布时间】:2020-11-06 06:04:55 【问题描述】:我有一个使用 FormsAuthentication 进行身份验证的现有 MVC 项目。
除了已经可用的常规登录页面之外,我还需要合并使用 OpenID IDP 登录的选项。
我遇到的问题是按需挑战 IDP 并在收到声明后设置身份验证 cookie,但我找不到 cookie 没有粘贴的原因。流程似乎运行良好,我可以在 AuthorizationCodeReceived 回调中看到声明。
这是 Startup.Auth.cs 代码:
var notificationHandlers = new OpenIdConnectAuthenticationNotifications
AuthorizationCodeReceived = (context) =>
string username = context.AuthenticationTicket.Identity.FindFirst("preferred_username").Value;
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(60), true, "");
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
context.Response.Cookies.Append(FormsAuthentication.FormsCookieName, encryptedTicket);
return Task.FromResult(0);
,
RedirectToIdentityProvider = (context) =>
if (context.OwinContext.Request.Path.Value != "/Account/SignInWithOpenId")
context.OwinContext.Response.Redirect("/Account/Login");
context.HandleResponse();
return Task.FromResult(0);
;
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
AuthenticationType = "oidc",
SignInAsAuthenticationType = "Cookies",
Authority = "xxxxxxxxx",
ClientId = "MyClient",
ClientSecret = "xxxxxxxx",
RedirectUri = "http://localhost:52389/",
PostLogoutRedirectUri = "http://localhost:52389/",
ResponseType = "code id_token",
Scope = "openid profile email roles",
UseTokenLifetime = false,
TokenValidationParameters = new TokenValidationParameters()
NameClaimType = "preferred_username",
RoleClaimType = "role"
,
Notifications = notificationHandlers
);
app.SetDefaultSignInAsAuthenticationType("Cookies");
app.UseCookieAuthentication(new CookieAuthenticationOptions()
AuthenticationType = "Cookies",
AuthenticationMode = AuthenticationMode.Passive,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider()
);
app.UseStageMarker(PipelineStage.Authenticate);
这里是 AccountController SignInWithOpenId 方法:
public ActionResult SignInWithOpenId()
if (!Request.IsAuthenticated)
HttpContext.GetOwinContext().Authentication.Challenge(OpenIdConnectAuthenticationDefaults.AuthenticationType);
// If I don't have this line, reponse redirects to the forms authentication login... so maybe something is wrong here?
return new HttpUnauthorizedResult("IDP");
else
return RedirectToAction("Index", "Default");
任何指针将不胜感激。谢谢。
【问题讨论】:
【参考方案1】:这正是我目前正在尝试做的事情。如果我发现任何有用的东西,我会告诉你。
更新: 我最终在 MVC Web 应用程序中禁用了表单身份验证。我正在做一个概念验证,所以这不是一个硬性要求。我知道这不是你真正想要的。我成功使用 IdP 登录并重定向回 Web 应用程序。概念证明结束的地方是需要填充 HttpContext.User 对象。
【讨论】:
我通过更改 HttpContext.GetOwinContext().Authentication.Challenge(OpenIdConnectAuthenticationDefaults.AuthenticationType); 进一步了解了这一点到 HttpContext.GetOwinContext().Authentication.Challenge("oidc");这使得挑战工作,然后在来自 IDP 的重定向上正确设置了 cookie 嗨@Naner,我完全按照您的代码进行操作,但我使用的是 Azure AD IDP。我有我能够在 .NET 4.7 中得到这个,或者至少是等效的。我的用例是大多数订阅者正在升级以通过 Azure AD B2C 登录,但我们有公共 PC,我们希望通过隐藏的 URL 手动声明进行身份验证。
我正在使用Microsoft.Owin.Security.OpenIDConnect
和相关的包,Owin启动是标准的,虽然我会指出这一行:
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
我不得不完全禁用 Forms 身份验证;当在 IIS 中启用匿名身份验证以外的任何其他功能时,我无法使其正常工作。
解决方案的核心实际上是我在这里找到的一个示例:How to use OWIN forms authentication without aspnet identity
/* URL validated, add authenticated claim */
var claims = new List<Claim>
new Claim(ClaimTypes.Name, "PublicPC"),
new Claim(ClaimTypes.Email, "PublicPC@example.org")
;
var id = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType);
var ctx = HttpContext.Current.GetOwinContext();
var authenticationManager = ctx.Authentication;
authenticationManager.SignIn(id);
但至关重要的是,我需要指定 CookieAuthenticationDefaults.AuthenticationType
,这是我在 Owin 启动时使用的。
【讨论】:
以上是关于如何将 OpenID 结合 Forms Authentication 添加到 MVC的主要内容,如果未能解决你的问题,请参考以下文章
将 OpenID (RPX)(可能还有 OAuth)用于 RESTful Web 服务
AspNetCore With Angular SPA Authentication using the Authorization Code Flow