[英]OpenIddict, after restarting auth server the tokens are invalidated
我進行了以下設置:授權服務器(帶 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>();
種子客戶:
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);
}
客戶端配置:
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";
});
資源服務器配置:
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);
這是客戶端向資源服務器發出請求的方式:
[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());
}
當我設置這 3 個實例(auth 服務器、客戶端、資源服務器)並且我未在客戶端(無 cookie)中進行身份驗證時,問題就出現了。 我可以在客戶端進行身份驗證(因此在身份驗證服務器上)。 然后我從客戶端向資源服務器發出請求,它返回200
。
但后來我停止了所有 3 個實例並嘗試再次執行。
那時我已經在客戶端(cookies)中進行了身份驗證並且可以提取令牌(僅供參考,停止實例之前和之后的請求之間的令牌是相同的)。 但此令牌無效,資源服務器的響應代碼為401
。
在資源服務器日志上,我可以看到以下日志:“ OpenIddict.Validation.AspNetCore was not authenticated. Failure message: An error occurred while authenticating the current request
”,以及“ invalid_token, the specified token is invalid
”
問題:這是預期的行為嗎? 我認為原因是數據保護更改了密鑰環或類似的東西。 如果是預期的 - 那么如何在不重新驗證所有用戶的情況下進行重新部署?
我很確定問題出在這條線
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
當您重新啟動應用程序時,這些證書(密鑰)會更改。 您需要准備好生產加密/簽名密鑰。
請參閱 options.AddEncryptionKey 和 options.AddSigningKey
密鑰可以這樣創建
var rsa = RSA.Create(2048);
var key = new RsaSecurityKey(rsa);
您可以獲得密鑰的 XML 並將其保存在某個地方 PRIVATE
var xml = key.Rsa.ToXmlString(true);
啟動應用程序時,使用 XML 加載密鑰
var rsa = RSA.Create();
rsa.FromXmlString(xml);
然后將密鑰添加到 openiddict
options.AddEncryptionKey(rsa);
options.AddSigningKey(rsa);
您可能還想改用以下方法
這取決於你有什么可用的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.