带有OpenIdAuthentication的ASP.NET:如果未经授权,则重定向到url

时间:2017-04-25 01:03:54

标签: asp.net asp.net-identity azure-active-directory openid-connect owin-middleware

我正在尝试编写一个使用混合身份验证方案的ASP.NET应用程序。 用户可以将用户名和密码哈希存储在UserStore中,也可以通过Azure Active Directory进行身份验证。

我创建了图片的登录表单。它具有标准Password[Authorize]输入,但也有“通过Active Directory登录”按钮。

enter image description here

这很有效。

现在出现问题:应用程序的主页具有public class DefaultController : Controller { [Authorize] public ViewResult Index() { // Implementation } } 属性。

Account/Login

如果用户未登录,我希望它重定向到页面IAppBuilder.UseOpenIdConnectAuthentication,允许用户选择身份验证方法。

appBuilder.SetDefaultSignInAsAuthticationType(CookieAuthenticationDefaults.AuthenticationType_; var cookieAuthenticationOptions = new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationType.ApplicationCookie, LoginPath = new Microsoft.Owin.PathString("/Account/Login"), Provider = new Security.CookieAuthenticationProvider() }; appBuilder.UseCookieAuthentication(cookieAuthenticationOptions); // Now the OpenId authentication var notificationHandlers = new OpenIdConnectAuthenticationNotificationHandlers { AuthorizationCodeReceived = async(context) => { var jwtSecurityToken = context.JwtSecurityToken; // I've written a static method to convert the claims // to a user var user = await GetOrCreateUser(context.OwinContext, jwtSecurityToken.Claims); var signInManager = context.OwinContext.Get<SignInManager>(); await signInManager.SignInAsync(user, true, false); } } var openIdOptions = new OpenIdConnectAuthenticationOptions { ClientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx", Authority = "https://login.microsoftonline.com/xxxxx.onmicrosoft.com", PostLogoutRedirectUri = "https://localhost:52538/Account/Login", Notifications = notifcationHandlers } appBuilder.UseOpenIdConnectAuthentication(openIdOptions); 添加到管道设置后,它不再重定向到该页面。相反,它直接进入Microsoft登录页面。

如何配置它以便OpenID身份验证是系统的一部分,但是允许我指定在未对用户进行身份验证时如何执行重定向?

以下是我设置管道的代码:

public ActionResult SignInWithOpenId()
{
    // Send an OpenID Connect sign-in request.
    if (!Request.IsAuthenticated)
    {
        var authenticationProperties = new AuthenticationProperties
        {
            RedirectUri = "/"
        };
        HttpContext.GetOwinContext().Authentication.Challenge
        (
            authenticationProperties,
            OpenIdConnectAuthenticationDefaults.AuthenticationType
        );
        return new EmptyResult();
    }
    else
    {
        return RedirectToAction("Index", "Default");
    }
}

当您点击“Active Directory登录”时,它会发布到“Account / SignInWithOpenId”

{{1}}

3 个答案:

答案 0 :(得分:4)

IAppBuilder.UseOpenIdConnectAuthentication(...)的调用将Owin中间件组件放入管道中。当ASP.NET MVC返回401(未授权)的HttpResponse时,Owin Middleware组件检测到此并将其更改为Http Redirect(代码302),重定向路径是Open ID提供程序。

但有一种解决方法:在中间件组件执行重定向之前,它会调用回调RedirectToIdentityProvider。从这里开始,我可以覆盖这个重定向。

这是我的代码,它覆盖了重定向,除非它来自请求路径Account/SignInWithOpenId

var notificationHandlers = new OpenIdConnectAuthenticationNotifications
{
    AuthorizationCodeReceived = async(context) => {
       // Sign in the user here
    },
    RedirectToIdentityProvider = (context) => {
        if(context.OwinContext.Request.Path.Value != "/Account/SignInWithOpenId")
        {
             context.OwinContext.Response.Redirect("/Account/Login");
             context.HandleResponse();
        }
        return Task.FromResult(0);
    }
}
var openIdOptions = new OpenIdConnectAuthenticationOptions
{
     ClientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
     Authority = "https://login.microsoftonline.com/xxxxx.onmicrosoft.com",
     PostLogoutRedirectUri = "https://localhost:52538/Account/Login",
     Notifications = notifcationHandlers
}
appBuilder.UseOpenIdConnectAuthentication(openIdOptions);

答案 1 :(得分:1)

请尝试在UseOpenIdConnectAuthentication之前移动UseCookieAuthentication,然后将用户重定向到&#34;登录&#34;页面。

// Now the OpenId authentication
var notificationHandlers = new OpenIdConnectAuthenticationNotificationHandlers 
{
  // Handler methods here
}
var openIdOptions = new OpenIdConnectAuthenticationOptions
{
     ClientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
     Authority = "https://login.microsoftonline.com/xxxxx.onmicrosoft.com",
     PostLogoutRedirectUri = "https://localhost:52538/Account/Login",
     Notifications = notifcationHandlers
}
appBuilder.UseOpenIdConnectAuthentication(openIdOptions);

appBuilder.SetDefaultSignInAsAuthticationType(CookieAuthenticationDefaults.AuthenticationType_;
var cookieAuthenticationOptions = new CookieAuthenticationOptions
{
     AuthenticationType = DefaultAuthenticationType.ApplicationCookie,
     LoginPath = new Microsoft.Owin.PathString("/Account/Login"),
     Provider = new Security.CookieAuthenticationProvider()
};
appBuilder.UseCookieAuthentication(cookieAuthenticationOptions);

请告诉我是否有帮助。

更新:

或者您可以使用自定义授权属性覆盖默认行为,例如:

    public class CustomAuthorizeAttribute: AuthorizeAttribute
    {
        public CustomAuthorizeAttribute(): base()
        {
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {

            }
            else
            {
                filterContext.HttpContext.Response.Redirect("Account/login");
            }              
        }
    }

然后只需将您的使用情况更改为:

[CustomAuthorize]
public ActionResult Index()
{
    return View();
}

答案 2 :(得分:0)

如果将OIDC的身份验证模式设置为“被动”,则它应仅响应明确的Open ID Connect请求(例如,发布到Account / SignInWithOpenId):

var openIdOptions = new OpenIdConnectAuthenticationOptions
{
     // ...
     AuthenticationMode = AuthenticationMode.Passive
}

来源:The OWIN OpenID Connect Middleware

的“明确使用挑战和登出”部分