And*_*riy 3 oauth jwt openid-connect openiddict
我进行了以下设置:授权服务器(带有 MVC 的 .NET 6,端口 7000)、客户端(带有 MVC 的 .NET 6,端口 7001)、资源服务器(.NET 6 API,端口 7002)。
授权服务器设置:
builder.Services.AddAuthentication()
.AddGoogle(options =>
{
options.ClientId = builder.Configuration["ClientId"];
options.ClientSecret = builder.Configuration["ClientSecret"];
});
builder.Services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = Claims.Name;
options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
options.ClaimsIdentity.RoleClaimType = Claims.Role;
options.ClaimsIdentity.EmailClaimType = Claims.Email;
options.SignIn.RequireConfirmedAccount = false;
});
builder.Services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<AuthorizationContext>();
})
.AddServer(options =>
{
options.SetAuthorizationEndpointUris("/connect/authorize")
.SetLogoutEndpointUris("/connect/logout")
.SetTokenEndpointUris("/connect/token")
.SetUserinfoEndpointUris("/connect/userinfo")
.SetIntrospectionEndpointUris("/connect/introspect");
options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles);
options.AllowAuthorizationCodeFlow();
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
options.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough()
.EnableLogoutEndpointPassthrough()
.EnableTokenEndpointPassthrough()
.EnableUserinfoEndpointPassthrough()
.EnableStatusCodePagesIntegration();
})
.AddValidation(options =>
{
options.UseLocalServer();
options.UseAspNetCore();
});
builder.Services.AddHostedService<Worker>();
Run Code Online (Sandbox Code Playgroud)
种子客户:
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "mvc",
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
ConsentType = ConsentTypes.Explicit,
DisplayName = "MVC client application",
PostLogoutRedirectUris =
{
new Uri("https://localhost:7001/signout-callback-oidc")
},
RedirectUris =
{
new Uri("https://localhost:7001/signin-oidc")
},
Permissions =
{
Permissions.Endpoints.Authorization,
Permissions.Endpoints.Logout,
Permissions.Endpoints.Token,
Permissions.GrantTypes.AuthorizationCode,
Permissions.GrantTypes.RefreshToken,
Permissions.ResponseTypes.Code,
Permissions.Scopes.Email,
Permissions.Scopes.Profile,
Permissions.Scopes.Roles,
Permissions.Prefixes.Scope + "api1"
},
Requirements =
{
Requirements.Features.ProofKeyForCodeExchange
}
});
// resource server
if (await manager.FindByClientIdAsync("resource_server_1") == null)
{
var descriptor = new OpenIddictApplicationDescriptor
{
ClientId = "resource_server_1",
ClientSecret = "846B62D0-DEF9-4215-A99D-86E6B8DAB342",
Permissions =
{
Permissions.Endpoints.Introspection
}
};
await manager.CreateAsync(descriptor);
}
Run Code Online (Sandbox Code Playgroud)
客户端配置:
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/login";
options.ExpireTimeSpan = TimeSpan.FromMinutes(50);
options.SlidingExpiration = false;
})
.AddOpenIdConnect(options =>
{
options.ClientId = "mvc";
options.ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654";
options.RequireHttpsMetadata = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.ResponseType = OpenIdConnectResponseType.Code;
options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;
options.Authority = "https://localhost:7000/";
options.Scope.Add("email");
options.Scope.Add("roles");
options.Scope.Add("api1");
options.MapInboundClaims = false;
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "role";
});
Run Code Online (Sandbox Code Playgroud)
资源服务器配置:
builder.Services.AddOpenIddict()
.AddValidation(options =>
{
options.SetIssuer("https://localhost:7000/");
options.AddAudiences("resource_server_1");
options.UseIntrospection()
.SetClientId("resource_server_1")
.SetClientSecret("846B62D0-DEF9-4215-A99D-86E6B8DAB342");
options.UseSystemNetHttp();
options.UseAspNetCore();
});
builder.Services.AddAuthentication(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
Run Code Online (Sandbox Code Playgroud)
这是客户端向资源服务器发出请求的方式:
[Authorize, HttpPost("~/")]
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
var token = await HttpContext.GetTokenAsync(CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectParameterNames.AccessToken);
if (string.IsNullOrEmpty(token))
{
throw new InvalidOperationException("The access token cannot be found in the authentication ticket. " +
"Make sure that SaveTokens is set to true in the OIDC options.");
}
using var client = _httpClientFactory.CreateClient();
using var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:7002/api/message");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using var response = await client.SendAsync(request, cancellationToken);
var content = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
return View("Home", model: await response.Content.ReadAsStringAsync());
}
Run Code Online (Sandbox Code Playgroud)
当我设置这 3 个实例(身份验证服务器、客户端、资源服务器)并且我未在客户端中进行身份验证(没有 cookie)时,问题就出现了。我可以在客户端上进行身份验证(因此也可以在身份验证服务器上进行身份验证)。然后我从客户端向资源服务器发出请求并返回200。
但随后我停止了所有 3 个实例并尝试再次执行此操作。
那时我已经在客户端(cookie)中进行了身份验证,并且可以提取令牌(仅供参考,停止实例之前和之后的请求之间的令牌是相同的)。但该令牌无效,资源服务器的响应代码为401。
在资源服务器日志上,我可以看到以下日志:“ OpenIddict.Validation.AspNetCore was not authenticated. Failure message: An error occurred while authenticating the current request”和“ invalid_token, the specified token is invalid”
问题:这是预期的行为吗?我认为原因是数据保护更改了密钥环或类似的东西。如果是预期的 - 那么如何在不重新验证所有用户的情况下进行重新部署?
小智 5
我很确定问题出在这条线上
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
Run Code Online (Sandbox Code Playgroud)
当您重新启动应用程序时,这些证书(密钥)将会更改。您需要准备好生产加密/签名密钥。
请参阅 options.AddEncryptionKey 和 options.AddSigningKey
密钥可以这样创建
var rsa = RSA.Create(2048);
var key = new RsaSecurityKey(rsa);
Run Code Online (Sandbox Code Playgroud)
您可以获取密钥的 XML 并将其保存在私有位置
var xml = key.Rsa.ToXmlString(true);
Run Code Online (Sandbox Code Playgroud)
当您启动应用程序时,您可以使用 XML 加载密钥
var rsa = RSA.Create();
rsa.FromXmlString(xml);
Run Code Online (Sandbox Code Playgroud)
然后将密钥添加到 openiddict
options.AddEncryptionKey(rsa);
options.AddSigningKey(rsa);
Run Code Online (Sandbox Code Playgroud)
您可能还想使用以下方法
这取决于你有什么可用的。
| 归档时间: |
|
| 查看次数: |
1092 次 |
| 最近记录: |