0

我在一台服务器上有一个带有 RESTful API 的 .Net core 3.2 站点,在另一台服务器上有一个客户端网站。用户仅通过 Facebook、Google 或 Microsoft 等外部提供商向客户端应用程序进行身份验证。我们还有一个将要使用的 Identity Server 4.0,但它的行为就像另一个外部提供者一样。

问题是,一旦用户在客户端通过身份验证,并且他们授予的角色/声明已经确定,我们如何从 API 请求特定资源?客户端 Web 应用程序了解用户并知道用户就是他们所说的那个人,客户端应用程序知道他们可以做什么。我们如何将这些信息安全地传递给 API?

我正在考虑 API 和网站之间的 client_credentials,但它似乎适用于没有用户的情况,如服务或守护进程。

我不希望 API 知道或关心用户,只希望他们经过身份验证以及他们的声明是什么。

4

2 回答 2

0

要在单页应用程序中实现身份验证,您需要将授权码与 PKCE OAuth2 流一起使用。它使您不会在您的 SPA 中存储任何秘密。

请不要使用Implicitflow,因为出于安全原因,它已被弃用。

当您将令牌从客户端发送到正确配置的 .NET Core API 时,您应该能够读取User控制器的属性以获取身份信息。

如果您正确配置 API,则只有在访问令牌有效的情况下,请求才会到达控制器。

于 2020-11-23T17:18:20.870 回答
0

我一直在寻找的答案是 JWT Tokens: 在客户端上,在它发送不记名令牌之前:

 protected override async Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            var accessToken = await GetAccessTokenAsync();

            if (!string.IsNullOrWhiteSpace(accessToken))
            {
                request.SetBearerToken(accessToken);
            }

            return await base.SendAsync(request, cancellationToken);
        }

  public async Task<string> GetAccessTokenAsync()
        {

            var longKey = "FA485BA5-76C3-4FF5-8A33-E3693CA97002";

            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(longKey));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            var claims = new List<Claim> {
                new Claim("sub",  _httpContextAccessor.HttpContext.User.GetUserId())
            };

            claims.AddRange(_httpContextAccessor.HttpContext.User.Claims);
            
            var token =new JwtSecurityToken(
                issuer: "https://localhost:44389",
                audience: "https://localhost:44366",
                claims: claims.ToArray(),
                expires: DateTime.Now.AddMinutes(30),
                signingCredentials: credentials
            );

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

在 API 服务器上

 var longKey = "FA485BA5-76C3-4FF5-8A33-E3693CA97002";

            services.AddAuthentication(x=> {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
                .AddJwtBearer(options =>
                {
                    options.SaveToken = true;
                    options.RequireHttpsMetadata = false;
                    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidateIssuer = false,
                        ValidateAudience = false,
                        //ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        //ValidIssuer = "https://localhost:44366",
                        //ValidAudience = "https://localhost:44366",
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(longKey)),
                        //ClockSkew = TimeSpan.Zero
                    };

                    
                });
于 2020-11-23T18:51:06.237 回答