Asp.net core Nopokta集成

Asp.net core Nopokta集成,asp.net-core,asp.net-core-mvc,openid,nopcommerce,okta,Asp.net Core,Asp.net Core Mvc,Openid,Nopcommerce,Okta,我有以下资料: Okta身份管理,带自定义身份验证服务器 .net核心web应用程序 .net核心web api应用程序 Nopcommerce 4.2 web应用程序 所有都在Azure应用程序服务中运行。我构建的web应用程序和api应用程序配合得非常好。web应用程序将身份验证承载令牌传递给API,API使用Aspnetcore.Okta中间件对其进行验证 然而,我现在需要把我的Nopcommerce应用程序带到这个领域。我花了3天的时间尝试构建一个插件——即使是一个基本上什么都不做的

我有以下资料:

  • Okta身份管理,带自定义身份验证服务器
  • .net核心web应用程序
  • .net核心web api应用程序
  • Nopcommerce 4.2 web应用程序
所有都在Azure应用程序服务中运行。我构建的web应用程序和api应用程序配合得非常好。web应用程序将身份验证承载令牌传递给API,API使用Aspnetcore.Okta中间件对其进行验证

然而,我现在需要把我的Nopcommerce应用程序带到这个领域。我花了3天的时间尝试构建一个插件——即使是一个基本上什么都不做的插件,也只遇到了麻烦。我使用了他们的“官方”模板,它有自己的问题。所以我决定只使用Facebook外部认证插件并开始编辑它。至少现在我有了一些我可以用的东西

这就是我真正陷入困境的地方。。。我能不能继续使用Okta中间件并完成它?我指的是以下步骤:

  • 添加登录操作控制器以覆盖默认登录操作
  • 如果用户不是authentictad,则发出质询
  • 中间件应该选择并重定向到登录页面(在我现有的web应用程序中)
  • 用户在那里登录
  • 中间件设置会话cookie并将用户重定向回Nopcomm应用程序
  • 现在回到Nopcomm,中间件再次启动,看到cookie,调用/verify端点,然后为相关用户填充ClaimsPrincipal
  • 我的想法是,如果两个应用程序上的机器密钥相同,cookie应该可以正常工作


    你认为这是最好的方法吗?或者我应该按照1-4中相同的步骤,除了在4之后,将用户发送回Nopcomm站点,并在查询字符串中使用令牌,然后在Nopcomm端手动验证它?

    我想我会分享我的测试结果,因为它发现了一些我真的没有想到的事情。也许你们中的大多数人都知道这些事情,但对我来说,它们确实很棘手

    我学到的第一件重要的事情是,你必须明确你的应用程序问题的挑战类型。如果您是自托管登录页面,则需要使用:

                services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                })
    
    如果您正在使用Okta(或其他openId提供商)登录页面,则需要发出不同类型的质询:

                builder.Services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
                })
    
    我学到的是,如果您在ASP.NET核心应用程序中使用OpenID Connect,并且您自托管登录页面,那么流程有点像这样:

  • 用户试图访问受保护的资源
  • [Authorize]标记告诉Okta中间件注入自身并执行其操作。User.Identity.IsAuthenticated为false,因此它将重定向到cookie选项下设置的任何登录路径:
  • 我的登录页面只是使用Okta小部件,所以单击login将用户发送到Okta,Okta完成它的工作,然后将用户发送回应用程序的每个神秘的“授权码/回调”url。该url由Okta中间件处理

  • 中间件处理从Okta发送的令牌,调用/userinfo端点以获取声明(假定您将该属性设置为true),并填充ClaimsPrincipal

  • 这里是我错过的部分它还可以设置一个cookie。从那时起,.net framework将检查cookie,以确定用户是谁以及他们是否经过身份验证。我完全误解了这一点。我认为中间件将在后台调用/授权或类似的东西

  • 因此,我在这里学到的最大教训是:仅仅因为两个应用程序使用同一个OpenID服务器并不意味着它们可以轻松共享身份验证/会话。为了让真正的SSO无缝工作,他们还必须共享一个cookie。这就引出了我的第二个发现:跨ASP.NET核心应用程序共享cookie。简短的版本是,您必须:

    a。在两个应用中为cookie命名相同 B使用IDataProtection接口将cookie密钥存储在两个应用程序都可以访问的位置(我选择了Azure)。 C确保两个应用的cookie域相同

    因此,在一天结束时,这就是我的代码端到端的样子(在每个应用程序的启动中)。我仍在处理一些特定于Nopcommerce的奇怪问题,但希望它们能很快在这里得到解决

                var oktaMvcOptions = new OktaMvcOptions()
                {
                    OktaDomain = oktaDomain,
                    ClientId = clientId,
                    ClientSecret = clientSecret,
                    Scope = new List<string> { "openid", "profile", "email", "address", "groups" },
                    AuthorizationServerId = authServerId,
                    GetClaimsFromUserInfoEndpoint = true
                };
    
                services.Configure<CookiePolicyOptions>(options =>
                {
                    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                    options.CheckConsentNeeded = context => true;
                    options.MinimumSameSitePolicy = SameSiteMode.None;
                });
    
    
                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);
                CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
                CloudBlobContainer container = blobClient.GetContainerReference(storageContainerName);
                var blob = container.GetBlockBlobReference("somefilename.xml");
    
                services.AddDataProtection().SetApplicationName("somesharedappname").PersistKeysToAzureBlobStorage(blob);
    
                services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                })
                .AddCookie(options =>
                {
                    options.LoginPath = new PathString("/Account/SignIn");
                    options.Cookie.Name = "somesharedcookiename";
                })
                .AddOktaMvc(oktaMvcOptions);
    
    var-oktaMvcOptions=new-oktaMvcOptions()
    {
    Oktomain=Oktomain,
    ClientId=ClientId,
    ClientSecret=ClientSecret,
    范围=新列表{“openid”、“profile”、“email”、“address”、“groups”},
    AuthorizationServerId=authServerId,
    GetClaimsFromUserInfoEndpoint=true
    };
    配置(选项=>
    {
    //此lambda确定给定请求是否需要非必要cookie的用户同意。
    options.checkApprovered=context=>true;
    options.MinimumSameSitePolicy=SameSiteMode.None;
    });
    CloudStorageAccount-storageAccount=CloudStorageAccount.Parse(storageConnectionString);
    CloudBlobClient blobClient=storageAccount.CreateCloudBlobClient();
    CloudBlobContainer container=blobClient.GetContainerReference(storageContainerName);
    var blob=container.GetBlockBlobReference(“somefilename.xml”);
    services.AddDataProtection();
    services.AddAuthentication(选项=>
    {
    options.DefaultAuthenticateScheme=CookieAuthenticationDefaults.AuthenticationScheme;
    options.defaultsignnscheme=CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme=CookieAuthenticationDefaults.AuthenticationScheme;
    }
    
                var oktaMvcOptions = new OktaMvcOptions()
                {
                    OktaDomain = oktaDomain,
                    ClientId = clientId,
                    ClientSecret = clientSecret,
                    Scope = new List<string> { "openid", "profile", "email", "address", "groups" },
                    AuthorizationServerId = authServerId,
                    GetClaimsFromUserInfoEndpoint = true
                };
    
                services.Configure<CookiePolicyOptions>(options =>
                {
                    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                    options.CheckConsentNeeded = context => true;
                    options.MinimumSameSitePolicy = SameSiteMode.None;
                });
    
    
                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);
                CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
                CloudBlobContainer container = blobClient.GetContainerReference(storageContainerName);
                var blob = container.GetBlockBlobReference("somefilename.xml");
    
                services.AddDataProtection().SetApplicationName("somesharedappname").PersistKeysToAzureBlobStorage(blob);
    
                services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                })
                .AddCookie(options =>
                {
                    options.LoginPath = new PathString("/Account/SignIn");
                    options.Cookie.Name = "somesharedcookiename";
                })
                .AddOktaMvc(oktaMvcOptions);