mvc自定义oauth服务器不会在未经授权的情况下重定向到登录页面

本文关键字:重定向 情况下 登录 授权 服务器 oauth 自定义 mvc | 更新日期: 2023-09-27 18:21:37

我设置了自己的oauth授权服务器(NO通过Facebook、Google和co登录)。不幸的是,在达到授权端点后,我的服务器不会重定向到登录页面。为什么中间件不重定向到我的登录页面?

我遵循了一些教程:

  1. OWIN OAuth 2.0授权服务器
  2. OAuth自定义提供程序c#(顺便说一句,这是我找到的唯一一个客户端登录到自定义OAuth服务器的代码示例。感谢@MatthiasRamp。我读到的所有其他内容都是关于如何使用社交媒体客户端登录的,这非常令人沮丧)
  3. MVC 5应用程序-实现OAuth授权代码流

这就是我在oauth服务器端做的短端:

  1. Startup.Auth.cs使用登录路径的活动Cookie身份验证
  2. Startup.Auth.cs使用被动Cookie身份验证
  3. Startup.Auth.cs使用AuthorizeEndpointPath的授权服务器
  4. SecurityController/Authorize调用Authentication.challenge()将状态更改为401

他在@Satish p的帖子中描述了一点:

  • 将客户端重定向到登录页面

为此,我设置属性CookieAuthenticationOptions.LoginPath,它告诉我

LoginPath属性通知中间件,它应该将传出的401未经授权的状态代码更改为302重定向到给定的登录路径上。

这是我的Startup.Auth.cs,包括LoginPath:

public void ConfigureAuth(IAppBuilder app)
    {
        // Enable the application to use a cookie to store information for the signed in user
        // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Application",
            AuthenticationMode = AuthenticationMode.Passive,
            LoginPath = new PathString("/Security/Login"),
            LogoutPath = new PathString("/Security/Logout")
        });
        // Enable the External Sign In Cookie.
        app.SetDefaultSignInAsAuthenticationType("External");
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "External",
            AuthenticationMode = AuthenticationMode.Passive,
            CookieName = CookieAuthenticationDefaults.CookiePrefix + "External",
            ExpireTimeSpan = TimeSpan.FromMinutes(5),
        });
        // The UseOAuthAuthorizationServer extension method is to setup the authorization server. The setup options are: [...]
        app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
        {
            AuthorizeEndpointPath = new PathString("/Security/Authorize"),
            TokenEndpointPath = new PathString("/Token"),
            ApplicationCanDisplayErrors = true,
#if DEBUG
            AllowInsecureHttp = true,
#endif
            // Authorization server provider which controls the lifecycle of Authorization Server
            Provider = new ApplicationOAuthProvider(PublicClientId)
        });
     }

我创建了一个派生自OAuthAuthorizationServerProvider的类。

public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        // [Check username and pw here]
        var oAuthIdentity = new ClaimsIdentity(new GenericIdentity(context.UserName, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
        var cookiesIdentity = new ClaimsIdentity(new GenericIdentity(context.UserName, CookieAuthenticationDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
        AuthenticationProperties properties = CreateProperties(context.UserName);
        AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
        context.Validated(ticket);
        context.Request.Context.Authentication.SignIn(cookiesIdentity);
    }
    public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
        foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
        {
            context.AdditionalResponseParameters.Add(property.Key, property.Value);
        }
        return Task.FromResult<object>(null);
    }
    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        var grantType = context.Parameters.SingleOrDefault(p => p.Key == "grant_type").Value;
        if (grantType != null)
        {
            if (grantType[0] == "authorization_code")
            {
                string clientId;
                string clientSecret;
                if (context.TryGetBasicCredentials(out clientId, out clientSecret) || context.TryGetFormCredentials(out clientId, out clientSecret))
                {
                    if (clientId == Clients.ClientApp.Id && clientSecret == Clients.ClientApp.Secret)
                    {
                        context.Validated();
                    }
                }
            }
        }
        return Task.FromResult<object>(null);
    }  
    public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
    {        
        if (context.ClientId == Clients.ClientApp.Id)
        {
            context.Validated(Clients.ClientApp.RedirectUrl);
        }
        return Task.FromResult<object>(null);
    }       
    public static AuthenticationProperties CreateProperties(string userName)
    {
        IDictionary<string, string> data = new Dictionary<string, string>
        {
            { "userName", userName }
        };
        return new AuthenticationProperties(data);
    }
}

这就是重定向应该发生的地方,因为质询会将响应更改为未授权(401)。它希望返回authorize视图,而不是重定向到登录页面。

public ActionResult Authorize()
    {           
        if (Response.StatusCode != 200)
        {
            return View("AuthorizeError");
        }
        var authType = DefaultAuthenticationTypes.ApplicationCookie;
        var authentication = HttpContext.GetOwinContext().Authentication;
        var ticket = authentication.AuthenticateAsync(authType).Result;
        var identity = ticket != null ? ticket.Identity : null;
        if (identity == null)
        {
            authentication.Challenge(authType);           
        }
        else
        {
            // login stuff
        }      
        return View();
    }

mvc自定义oauth服务器不会在未经授权的情况下重定向到登录页面

我知道已经太晚了,你可能不再需要这个了,但以防万一,如果其他人也面临这个问题,那么你需要返回HttpUnauthorizedResult();挑战后,它会重新提示您登录页面。例如

 if (identity == null)
 {
   authentication.Challenge(authType);
   return new HttpUnauthorizedResult();           
 }
 //login stuff