【问题标题】:Auto redirect to external authority when user is not authorized using ASP.NET Core 2.2 and OIDC当用户未使用 ASP.NET Core 2.2 和 OIDC 授权时自动重定向到外部权限
【发布时间】:2019-07-19 01:37:00
【问题描述】:

我正在尝试通过 OpenID 连接协议(特别是 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;
    });  

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

此按钮有效 - 它重定向到授权服务器,并在成功登录后打开 /Identity/Account/ExternalLogin 并建议填写缺失的本地注册用户声明(特别是 - 电子邮件)。
事实上,/signin-oidc地址当然是先打开的,我相信哪个handler会根据收到的授权码完成认证过程。

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

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

【问题讨论】:

    标签: c# asp.net-core openid-connect


    【解决方案1】:

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

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

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

    但通常我们仍然需要另一个SignInScheme。如果你查看源代码,你会发现当远程身份验证处理程序成功验证某个用户时,它会sign the user in:

       // ...
       await Context.SignInAsync(SignInScheme, ticketContext.Principal, ticketContext.Properties);
       // ...
    

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


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

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

    现在您可以随意使用[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 =>
        {
             // ....
        }
    
    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);
            }
        }
    

    【讨论】:

    • 在此之后我重定向到/Account/Login?ReturnUrl=%2F,但没有重定向到授权服务。我该如何改变这种行为?
    • @Emanuel 抱歉,我忘了说我们必须自定义挑战过程。请参阅我的更新答案。
    • 谢谢,它有效!也许你也可以解释一下,为什么SignInManager.IsSignedIn(User)变成_LoginPartial.cshtml现在返回false,不管那个用户实际上是授权的并且我可以阅读他的声明?
    • @Emanuel SignInManager 在 ASP.NET Core Identity 中定义。由于我们在这里从未使用过 ASP.NET Core Identity,它肯定不会起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-13
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    相关资源
    最近更新 更多