첫 번째 문제는 이것이 큰 게시물이지만 몇 주 동안이 문제를 추적하고 있으며 문제의 원인이 될 수있는 많은 정보를 수집합니다.Asp.NET Core OpenIddict invalid_grant
OpenIddict 인증과 함께 Angular2 응용 프로그램을 사용하고 있습니다. 클라이언트 응용 프로그램에서 access_token, refresh_token을 얻습니다. refresh_token을 사용하여 새로운 access_token을 얻을 수 있습니다. 모든 것이 작동합니다. 거의.
POST https://mydomain:2000/api/authorization/token 400 (잘못된 요청)
및 응답 :
error:"invalid_grant"
error_description:"Invalid ticket"
내가 트리플 확인 모든과 refresh_token도 어떤 점에서
나는 서버에서 오류 응답을 얻을 나는 옳다. 디자인에 대해:
내가 만료 access_token이 있다면 확인 서버에 요청을하기 전에. 만료되면 refresh_token으로 새로운 access_token을 요청합니다.
그리고 임의의 시간에 작동하지만 임의의 시간 (반복) refresh_token이 유효하지 않게됩니다.
AddEphemeralSigningKey
과 관련이 있지만 AddSigningCertificate
으로 변경합니다. (세부 사항은 this 스레드입니다.)
제가 생각하기에, IIS는 일정한 활동 시간 후에 Kestrel을 죽입니다. 내 응용 프로그램 풀 설정은 다음과 같습니다
StartMode: OnDemand
Idle Time-out (minutes): 20
Idle Time-out (action): Terminate
나는 새로운 요청이 후, OpenIddict 잘못 것을 해제 토굴 refresh_token도 의심, 황조롱이가 다시 시작했기 때문에? 또는 나는 틀린가?
또한 OpenIddict 테이블과 OpenIddictApplications, OpenIddictAuthorizations 및 OpenIddictScopes가 모두 비어 있는지 확인합니다. 만 OpenIddictTokens 일부 데이터를 포함 (및 모든 유형 refresh_token도이다) :
이내가 기대, refresh_tokens 어딘가에 저장됩니다. 어디서? 어쩌면 이것이 소스 문제 일 수 있습니다. 왜 내가 임의의 시간 (아마도 Kestrel이 재시작 될 때) 이후에 내 refresh_tokens가 유효하지 않은 것입니까?
IIS 로그 : 여기
Hosting environment: Production
Content root path: D:\Podatki\OpPISWeb\WWWProduction
Now listening on: http://localhost:1408
Application started. Press Ctrl+C to shut down.
fail: AspNet.Security.OpenIdConnect.Server.OpenIdConnectServerMiddleware[0]
The token request was rejected because the authorization code or the refresh token was invalid.
fail: AspNet.Security.OpenIdConnect.Server.OpenIdConnectServerMiddleware[0]
The token request was rejected because the authorization code or the refresh token was invalid.
내 시작입니다.CS :
public void ConfigureServices(IServiceCollection services)
{
try
{
services.Configure<IISOptions>(options =>
{
});
services.AddMvc();
services.AddMvcCore().AddDataAnnotations();
services.AddEntityFrameworkSqlServer();
services.AddScoped<UserStore<AppUser, AppRole, AppDbContext, int, AppUserClaim, AppUserRole, AppUserLogin, AppUserToken, AppRoleClaim>, AppUserStore>();
services.AddScoped<UserManager<AppUser>, AppUserManager>();
services.AddScoped<RoleManager<AppRole>, AppRoleManager>();
services.AddScoped<SignInManager<AppUser>, AppSignInManager>();
services.AddScoped<RoleStore<AppRole, AppDbContext, int, AppUserRole, AppRoleClaim>, AppRoleStore>();
var connection = Configuration["ConnectionStrings:Web"];
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(connection);
options.UseOpenIddict<int>();
if (this.env.IsDevelopment())
options.EnableSensitiveDataLogging();
});
services
.AddIdentity<AppUser, AppRole>()
.AddUserStore<AppUserStore>()
.AddUserManager<AppUserManager>()
.AddRoleStore<AppRoleStore>()
.AddRoleManager<AppRoleManager>()
.AddSignInManager<AppSignInManager>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
});
services.AddOpenIddict<int>(options =>
{
options.AddEntityFrameworkCoreStores<AppDbContext>();
options.AddMvcBinders();
options.EnableTokenEndpoint("/API/authorization/token");
options.AllowPasswordFlow();
options.AllowRefreshTokenFlow();
options.AllowCustomFlow("urn:ietf:params:oauth:grant-type:google_identity_token");
options.AllowCustomFlow("urn:ietf:params:oauth:grant-type:logedin");
options.UseJsonWebTokens();
if (this.env.IsDevelopment())
options.AddEphemeralSigningKey();
else
options.AddSigningCertificate(new FileStream(
Directory.GetCurrentDirectory() + "/Resources/cert.pfx", FileMode.Open), "password");
options.SetAccessTokenLifetime(TimeSpan.FromMinutes(30));
options.SetRefreshTokenLifetime(TimeSpan.FromDays(14));
if (this.env.IsDevelopment())
options.DisableHttpsRequirement();
});
services.AddSingleton<DbSeeder>();
services.AddSingleton<IConfiguration>(c => { return Configuration; });
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
throw;
}
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, DbSeeder dbSeeder)
{
loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
}
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(this.Configuration["Directories:Upload"]),
RequestPath = new PathString("/Files")
});
app.UseOpenIddict();
var JwtOptions = new JwtBearerOptions()
{
Authority = this.Configuration["Authentication:OpenIddict:Authority"],
Audience = "OpPISWeb",
AutomaticAuthenticate = true,
AutomaticChallenge = true,
RequireHttpsMetadata = false
};
JwtOptions.RequireHttpsMetadata = !env.IsDevelopment();
app.UseJwtBearerAuthentication(JwtOptions);
app.UseMvc();
using (var context = new AppDbContext(this.Configuration))
{
context.Database.Migrate();
}
try
{
dbSeeder.SeedAsync();
}
catch (AggregateException e)
{
throw new Exception(e.ToString());
}
}
업데이트 : 결국 내가해야 할 일을했을 모두에서
은 다음과 같습니다
services.AddDataProtection()
.SetApplicationName(this.Configuration["Authentication:ApplicationId"])
.PersistKeysToFileSystem(new DirectoryInfo(this.Configuration["Directories:Keys"]));
권한을 추가하는 것을 잊지 마십시오
디렉터리 용 IIS : Keys 폴더
@Pinpint : 이것이 사실이라고 생각합니다. 다른 사용자가 로그인하면 문제가 발생합니다. 권장 방법이 있습니까? 나는 당신의 예를 점검하고, 관련 주제를 읽는다. 어쩌면 몇 줄의 코드를 사용해야합니까? 감사합니다. – Makla