使用ASP.NET Core 2.2和OIDC未授权用户时,自动重定向到外部授权

Ema*_*uel 5 c# openid-connect asp.net-core

我正在尝试通过OpenID Connect协议(特别是-KeyCloak,使用外部授权服务器)来保护我的ASP.NET MVC Web应用程序,这一点并不重要。
我要查找的所有示例基本上都是安装Microsoft.AspNetCore.Authentication.OpenIdConnectnuget软件包并向Startup类添加一些配置代码:

services
    .AddAuthentication()
    .AddOpenIdConnect(options =>
    {
        options.Authority = authUrl;
        options.ClientId = clientId;
        options.ClientSecret = clientSecret;
        options.ResponseType = OpenIdConnectResponseType.Code;
    });  
Run Code Online (Sandbox Code Playgroud)

然后,如果我[Authorized]向控制器操作添加属性,则当我尝试打开页面时,将重定向到/Identity/Account/Login系统页面,该部分在该部分Use another service to log in.显示OpenIdConnect用于通过远程身份验证服务器登录的按钮。

此按钮有效-重定向到授权服务器,并在成功登录后打开/Identity/Account/ExternalLogin并显示一个建议,用于填写丢失的用户本地注册声明(尤其是电子邮件)。
实际上,当然,地址/signin-oidc是最先打开的,我相信该处理程序将根据接收到的授权码完成身份验证过程。

但是,除OpenIDConnect外,我不需要任何其他授权方法。我需要未经授权的用户立即将其重定向到远程授权服务器。

如何防止其他登录方法并直接重定向到授权服务器,而不重定向到ASP.NET登录页面?

itm*_*nus 5

但是,除了 OpenIDConnect 之外,我不需要任何其他授权方法。我需要将未经授权的用户立即重定向到远程授权服务器。

如何阻止其他登录方法并直接重定向到授权服务器,而不是重定向到 ASP.NET 登录页面?

事实上,有一种方法可以直接重定向到授权服务器,而无需访问任何本地登录页面。

但通常我们仍然需要另一个SignInScheme。如果您查看源代码,您会发现当远程身份验证处理程序成功验证某个用户时,它将让用户登录

   // ...
   await Context.SignInAsync(SignInScheme, ticketContext.Principal, ticketContext.Properties);
   // ...
Run Code Online (Sandbox Code Playgroud)

例如,如果OAuth2.0身份验证成功,我们应该为当前用户设置一个 cookie 或颁发一个 JWT 令牌。


至于你的问题,最简单的方法是注册一个 cookie 方案来 Challenge / Signin :

services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect("MyOIDC", options =>
    {
        // ...
    }
Run Code Online (Sandbox Code Playgroud)

现在您可以[Authorize]随心所欲地使用。上面的代码在没有ASP.NET Core Identity 的情况下可以完美地工作

[更新]:抱歉,我忘了提到我们必须自定义挑战流程:

  1. 方法一:为Cookie配置前向挑战方案:
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie(options =>{
        options.ForwardChallenge ="MyOIDC";

    })
    .AddOpenIdConnect("MyOIDC", options =>
    {
         // ....
    }
Run Code Online (Sandbox Code Playgroud)
  1. 方法 2:手动调用挑战方案:
    public class AccountController : Controller
    {
        public async Task Login(string returnUrl = "/")
        {
            await HttpContext.ChallengeAsync("MyOIDC", new AuthenticationProperties() { RedirectUri = returnUrl });
        }
        
        // if you need sign out the MyOIDC service, you could sign out the user for two schemes as below :
        [Authorize]
        public async Task Logout()
        {
            await HttpContext.SignOutAsync("MyOIDC", new AuthenticationProperties
            {
                RedirectUri = Url.Action("Index", "Home")
            });
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        }
    }
Run Code Online (Sandbox Code Playgroud)