在 SSO 的旧 .Net Web Forms (aspx) 站点中使用 ASP.Net Core 2.2 Auth Cookie

Using ASP.Net Core 2.2 Auth Cookies in old .Net Web Forms (aspx) site for SSO

TLDR:如何获得旧版 Web 窗体应用程序理解的 Asp.Net Core 2.2 加密身份验证 cookie?

DR:

我发现自己处于这样一种情况,我试图让旧版 Web 表单 (aspx) 站点使用由新的闪亮的 .NET Core 2.2 MVC 站点在浏览器中设置的 auth cookie。有问题的 Web 窗体应用程序是用 Visual Basic 编写的,.Net Core 应用程序是用 C# 编写的。一切都由 IIS/IIS Express 托管(来自 Visual Studio)。

cookie 似乎设置得很好,为了让事情变得简单(目前),所有东西都托管在同一台机器上(我的 Windows 10 专业版 Dell XPS)。用于 cookie 加密的 encryption/machine 密钥位于磁盘上明确定义的位置。 .Net Core 应用程序(我们暂时称它为 "Auth Portal")基本上是 AWS Cognito 的前台。

在 Auth Portal 中,cookie 的配置方式如下 Startup.cs:

services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        var keyDir = Configuration["AuthSettings:CookieEncryptionKeyDir"];
        services.AddDataProtection()
            .PersistKeysToFileSystem(new DirectoryInfo(keyDir))
            .SetApplicationName(Configuration["ApplicationName"]);

        services.AddCognitoIdentity();
        services.AddSingleton(typeof(IAmazonCognitoIdentityProvider),
            _ => new AmazonCognitoIdentityProviderClient(RegionEndpoint.APSoutheast2)); // Oh no you know I'm using Sydney!

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie();

        services
            .ConfigureApplicationCookie(options =>
            {
                var parseSucceeded = int.TryParse(Configuration["AuthSettings:CookieExpiryHours"],
                    out var cookieExpiry);
                if (!parseSucceeded) _log.LogError("Failed to parse from configuration auth cookie expiry value");

                parseSucceeded = bool.TryParse(Configuration["AuthSettings:SSLCookieOnly"], out var secureCookieOnly);
                var securePolicy = secureCookieOnly ? CookieSecurePolicy.Always : CookieSecurePolicy.SameAsRequest;
                if (!parseSucceeded) _log.LogError("Failed to parse from configuration cookie security policy");

                options.Cookie.HttpOnly = true;
                options.ExpireTimeSpan = TimeSpan.FromHours(cookieExpiry);
                options.SlidingExpiration = true;
                options.LoginPath = Configuration["AuthSettings:LoginUrl"];
                options.LogoutPath = Configuration["AuthSettings:LogoutUrl"];
                options.Cookie.Domain = Configuration["AuthSettings:TrustedDomains"];
                options.Cookie.Name = Configuration["AuthSettings:CookieName"];
                options.Cookie.SecurePolicy = securePolicy;
            });

        services
            .Configure<SecurityStampValidatorOptions>(o =>
            {
                o.ValidationInterval = TimeSpan.FromHours(1);
            });

        services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardLimit = 2;
            options.ForwardedForHeaderName = "X-Forwarded-For-Auth-Portal";
        });

在 Web 窗体应用程序中,我正在替换现有的默认 sql 身份验证。这是在线资源似乎枯竭的地方。我可以制作一个自定义的会员提供者,我已经很容易做到了。但它不能(可以理解)开箱即用地理解现有的 cookie,即使我在表单身份验证设置中设置了 cookie 名称

<authentication mode="Forms">
  <forms timeout="60" name="my.sso.cookie" requireSSL="false" path="/"  />
</authentication>
<membership defaultProvider="CognitoMembershipProvider" userIsOnlineTimeWindow="60">
  <providers>
    <clear />
    <add name="CognitoMembershipProvider" type="TheOldWebFormsApp.Authentication.CognitoMembershipProvider" applicationName="MyWebForms" enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="true" requiresUniqueEmail="false" passwordFormat="Clear" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="3" maxInvalidPasswordAttempts="8" />
  </providers>
</membership>

正如我所发现的那样,它只会覆盖现有的 cookie,我假设这是因为它将无法理解的 cookie 视为不存在的 cookie。

我想这是一个非常冗长的方式来询问我如何才能让这个旧的 Web 表单应用程序接受和解密 Auth Portal cookie?

干杯~!

不幸的是,这是不可能的。 ASP.NET Core 使用与 ASP.NET 完全不同的方法来加密 cookie。后者基于 "machine key",但 ASP.NET 核心使用数据保护提供程序和密钥环。两者从根本上是不兼容的,所以即使你可以 "share" cookie,这样每个人都能看到它,一个人将无法解密另一个人设置的 cookie。

可以与 ASP.NET MVC 5 成功共享 cookie,但那是因为它使用了 OWIN,并且数据保护内容与 OWIN 兼容。因此,尽管 MVC 5 本身也使用机器密钥,但可以改为使用数据保护,然后它可以与 ASP.NET 核心站点共享相同的数据保护密钥存储。但是,Web Forms 不支持 OWIN,因此无法在那里实现相同的目的。简而言之,这绝对不行。

另一种选择可能是依赖集中式身份提供者,例如 Identity Server、Auth0、Azure AD 等。有了这样的解决方案,就没有必要共享 cookie,因为每个站点都与提供者独立授权,但可以使用相同的用户帐户。实际登录发生在身份提供者处,然后由该身份提供者授权的每个站点都从身份提供者那里获得身份,然后可以设置自己的 cookie 或其他任何内容。