ASP.NET Core 8和DuPont Identity Server身份验证方案(OpenIdConnect、Cookie、JWT)

tgabmvqs  于 5个月前  发布在  .NET
关注(0)|答案(1)|浏览(83)

我在Visual Studio中安装了3个项目,如下所示:

  • WebServer端口5002,用于生成Web客户端页面
  • APIServer端口7288,Web服务器在此查询API端点和数据库,以将数据获取到视图中
  • AuthorisationServer端口5001,用于将用户登录到应用程序并进行身份验证/授权

WebServer使用cookie和OpenIdConnect身份验证方案。身份验证方案的配置在Program. cs中完成:

builder.Services.AddHttpClient("APIClient", client =>
{
    client.BaseAddress = new Uri(builder.Configuration["WarehouseWebAPIRoot"]);
    client.DefaultRequestHeaders.Clear();
    client.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json");
}).AddUserAccessTokenHandler();

builder.Services.AddHttpClient("IDPClient", client =>
  {
    client.BaseAddress = new Uri("https://localhost:5001/");
  });

builder.Services.AddAccessTokenManagement(options =>
  {
    options.Client.Clients.Add("identityserver", new 
  IdentityModel.Client.ClientCredentialsTokenRequest
    {
        Address = "https://localhost:5001/connect/token",
        ClientId = "web",
                    ClientSecret = "secret",
        Scope = "WebAppApi:fullaccess"
    });
   });   

builder.Services.AddAuthentication(options =>
 {
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
   })
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { 
        options.AccessDeniedPath = "/Authentication/AccessDenied";
        options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
        options.SlidingExpiration = true;
        options.Cookie.MaxAge = options.ExpireTimeSpan;
        options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
    })
    .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
    {   options.AccessDeniedPath= "/Authentication/AccessDenied";
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.Authority = "https://localhost:5001";
      
    options.ClientId = builder.Configuration["Authentication:OpenId:ClientId"];
        options.ClientSecret = builder.Configuration["Authentication:OpenId:ClientSecret"];
        options.ResponseType = "code";
        options.GetClaimsFromUserInfoEndpoint = true;
        options.SaveTokens = true;
        options.Scope.Add("roles");
          options.Scope.Add("profile");
        options.Scope.Add("WebAppApi:fullaccess");
        
        options.ClaimActions.Remove("aud");
        options.ClaimActions.DeleteClaim("sid");
        options.ClaimActions.DeleteClaim("idp");
        
        options.ClaimActions.MapJsonKey("role", "role");
        options.TokenValidationParameters = new()
        {
           
            NameClaimType = JwtClaimTypes.Name,
            RoleClaimType = JwtClaimTypes.Role,
           
        };
    });

builder.Services.AddAuthorization(options =>
    options.AddPolicy("AdminOnly", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.RequireClaim("role", "Admin");
        
    })
);

字符串
APIServer使用JWTBearer身份验证方案:

builder.Services.AddAuthentication(o =>
{
    o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
    {
        options.SaveToken = true;
        options.Authority = builder.Configuration["Authentication:OpenId:Authority"];
        options.Audience = builder.Configuration["Authentication:OpenId:Audience"];
        options.Configuration?.ClaimsSupported.Add("role");
        options.TokenValidationParameters = new()
        {

            ValidateAudience = false,
            NameClaimType = JwtClaimTypes.Name,
            RoleClaimType = JwtClaimTypes.Role,
            //ValidTypes = new[] { "at+jwt" }
        };
    });

builder.Services.AddAuthorization(options =>
    options.AddPolicy("AdminOnly", policy =>
    {
        policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
        policy.RequireAuthenticatedUser();
        policy.RequireClaim("role", "Admin");
    })
);


AuthorisationServer使用cookie和OpenIdConnect身份验证方案。配置在Program.csConfig.cs中完成。如果需要更多细节,我可以分享这些。
该用户未经过身份验证,Duodecad Identity Server的日志如下:
[23:54:57] Duplicate. IdentityServer. Endpoints. AuthorizeEndpoint ValidatedAuthorizeRequest {"ClientId ":" web "," ClientName ":null," RedirectUri ":" https://localhost:5002/signin-oidc "," AllowedRedirectUris ":[" https://localhost:5002/signin-oidc "]," SubjectId ":" anonymous "," ResponseType ":" code "," ResponseMode ":" form_post "," GrantType ":" authorization_code "," PrivateScopes ":" openid profile roles WebAppApi:fullaccess "," State ":"CfDJ8Pu7Fp24kUpGjM8vsRLlDAbPNrdC_l3Qky59ofw-LCER_PUh03HZdP-Nii7JanPnvqKm-MD7_gdrPqWdZpV6NgIUe66T6MZvJZ3XkisfAaCBsYMKDJG5kji8e1hs-I1xlYY1Oy-_9hxN_X4hlrA9rol24B-GnFKFTMXJBSzSiQuUjr5-kt0f6RjFmUBJ1z48i2R2WqNsvE6SKK n9CoAlNCjrsUa-GKVlR6Yi1t0TxL3HqY4M7IKCVvj4fPOgxqNFpa_tbqEUc6mcaXNsDzIY1 hvqHkdhtgzZPY53B57ETAdBXrGQG7uhZJWqIlXJEcxy0_0hvMh0Jgle0MoYSLrEdGEFbu11Q0-FxjUVDq6xYkjhQIKyBHbo-VwYiaBa8aL1hA "," UiLocales ":null," Nonce ":"638364596969981993.NTJjNzQzYzMtNDM2Ny00Nzc2LWI0ZDYtZWQ 2M2I4MTg0YTgwZWEwODIzMjctMTQ2ZC00MTdlLThkOTMtZWM5MGM5MjUyNDg0","AuthenticationContextReferenceClasses ":null," DisplayMode ":null," AuthenticationMode ":""," MaxAge ":null,"LoginHint":null,"SessionId":"","Raw":{"client_id ":" web "," redirect_uri ":" https://localhost:5002/signin-oidc "," response_type ":" code "," scope ":" openid profile roles WebAppApi:fullaccess "," code_challenge ":" 5m7NDLdV1So0go6tHUS7pI6EFnlxp5Py71xdXkRmObk "," code_challenge_method ":" S256 "," response_mode ":" form_post "," nonce ":"638364596969981993.NTJjNzQzYzMtNDM2Ny00Nzc2LWI0ZDYtZWQ2M2I4MTg0YTgwZWEwODIzMjctMTQ2ZC00MTdlLThkOTMtZWM5MGM5MjUyNDg0","state":"CfDJ8Pu7Fp24kUpGjM8vsRLlDAbPNrdC_l3Qky59ofw-LCER_PUh03HZdP-Nii7JanPnvqKm-MD7_gdrPqWdZpV6NgIUe66T6MZvJZ3XkisfAaCBsYMKDJG5kji8e1hs-I1xlYy1Oy-_9hxN_X4hlrA9rol24B-GnFKFTMXJBSzSiQuUjr5-kt0f6RjFmUBJ1z48i2R2WqNsvE6SKKn9CoAlNCjrsUa-GKVlR6Yi1t0TxL3HqY4M7IKCVvj4fPOgxqNFpa_tbqEUc6mcaXNsDzIY1hvqHkdhtgzZ PY53B57ETAdBXrGQG7uhZJWqIlXJEcxy0_0hvMh0Jgle0MoYSLrEdGEFbu11Q0-FxjUVDq6x YkjhQIKyBHbo-VwYiaBa8aL1hA "," x-client-server ":" ID_NET8_0 "," x-client-ver ":" www.example.com "},"$type":"AuthorizeRequestValidationLog "} 23:54:57信息] Duplicate. IdentityServer. ResponseHandling. AuthorizeInteractionResponseGenerator显示登录名:用户未经验证
[23:54:57信息】Serilog. AspNetCore. RequestLoggingMiddleware HTTP GET/connect/authorize响应302在41.8403毫秒
[23:54:57信息]> Microsoft. AspNetCore. Authentication. Cookies. CookieAuthenticationServer Cookies未经过身份验证。失败消息:取消保护票证失败
[23:54:57信息]> Microsoft. AspNetCore. Authentication. Cookies. CookieAuthenticationServer Cookies未经过身份验证。失败消息:取消保护票证失败
[23:54:57信息]> Microsoft. AspNetCore. Authentication. Cookies. CookieAuthenticationServer Cookies未经过身份验证。失败消息:取消保护票证失败
[23:54:57信息]> Microsoft. AspNetCore. Authentication. Cookies. CookieAuthenticationServer Cookies未经过身份验证。失败消息:取消保护票证失败
[23:54:57] Duplicate. IdentityServer. Validation. AuthorizeRequestValidator启动授权请求协议验证
[23:54:57]客户端Web的Duplicate. IdentityServer. Stores. ValidatingClientStore客户端配置验证成功。
[23:54:57] Duplicate. IdentityServer. Validation. AuthorizeRequestValidator检查PKCE参数
[23:54:57] Duplicate. IdentityServer. Validation. AuthorizeRequestValidator调用自定义验证器:> Duplicate. IdentityServer. Validation. DefaultCustomAuthorizeRequestValidator
[23:54:57信息] Serilog. AspNetCore. RequestLoggingMiddleware HTTP GET/Account/Login响应200在23.9251 ms
你能告诉我为什么用户没有得到认证吗?我已经尝试更改认证方案的选项,但没有成功。我正在按照文档中的说明进行操作:https://docs.duendesoftware.com/identityserver/v6/quickstarts/
你能告诉我我错过了什么吗?谢谢。

xxhby3vn

xxhby3vn1#

当你得到这个错误:

  • Microsoft.AspNetCore.Authentication.Cookies. CookieAuthenticationCookies未经过身份验证。失败消息:取消保护票证失败 *

这意味着示例无法“解密”接收到的cookie。cookie使用数据保护API进行保护。请参阅我的博客文章,了解如何保护cookie:
Exploring what is inside the ASP.NET Core cookies
另一个麻烦的原因可能是服务使用相同名称的cookie。
Cookie在同一个“域”上的所有服务之间共享,这意味着您的服务可能会收到来自另一个服务的Cookie。
因此,请确保应用程序中的所有Cookie对于每个服务都是唯一的。
答案:Are HTTP cookies port specific?
第三个问题在这里:

.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { 
    options.AccessDeniedPath = "/Authentication/AccessDenied";
    options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
    options.SlidingExpiration = true;
    options.Cookie.MaxAge = options.ExpireTimeSpan;
    options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
})

字符串
浏览器可能会拒绝严格的cookie,因为它是由另一个网站“触发”的,您可能需要更改为samesitemode.lax。
我的博客:Debugging cookie problems in ASP.NET Core

相关问题