如果 context.Request.Scheme 设置为 "https",API 无法连接到 Azure 上的 IdentityServer4
API can't connect to IdentityServer4 on Azure without context.Request.Scheme set to "https"
我有两个服务,API 和 IdentityService4 托管在 Azure 上,带有 Kubernetes(Azure Kubernetes 服务)。
当我 运行 通过 Visual Studio 服务时,一切正常,IS4 正确验证令牌。
但是,当我尝试调用任何需要授权的“生产”请求时,我得到以下异常:
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'.
---> System.ArgumentException: IDX20108: The address specified 'System.String' is not valid as per HTTPS scheme. Please specify an https address for security reasons. If you want to test with http address, set the RequireHttps property on IDocumentRetriever to false. (Parameter 'address')
at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.ConfigurationManager'1.GetConfigurationAsync(CancellationToken cancel)
--- End of inner exception stack trace ---
at Microsoft.IdentityModel.Protocols.ConfigurationManager'1.GetConfigurationAsync(CancellationToken cancel)
我发现了这个问题:https://github.com/IdentityServer/IdentityServer4/issues/4645 并使用了这个解决方案:
app.Use((context, next) => { context.Request.Scheme = "https"; return next(); });
但我不确定这是否是一个“安全”的解决方案,因为它看起来有点老套。
API 配置
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://mylinkttoIS4.com";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
services.AddAuthorization();
services.AddHttpContextAccessor();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use((context, next) => { context.Request.Scheme = "https"; return next(); });
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization();
});
}
IdentityServer4 配置
public void ConfigureServices(IServiceCollection services)
{
var databaseConnectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(databaseConnectionString));
services.AddIdentity<User, IdentityRole<Guid>>().AddEntityFrameworkStores<DatabaseContext>()
.AddDefaultTokenProviders();
services.AddIdentityServer()
.AddSigningCredentialBasedOnEnvironment(Configuration, Environment)
.AddInMemoryApiScopes(IdentityServerConfig.ApiScopes)
.AddInMemoryClients(IdentityServerConfig.Clients)
.AddAspNetIdentity<User>()
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder => builder.UseSqlServer(databaseConnectionString, sql => sql.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name));
options.DefaultSchema = "identity";
})
.AddResourceOwnerValidator<CustomResourceOwnerPasswordValidator>();
services.AddTransient<ISmsSender, SmsSender>();
}
public void Configure(IApplicationBuilder app)
{
app.UseHttpsRedirection();
app.UseIdentityServer();
}
你知道这条线是做什么的吗?
在生产环境中使用安全吗?
也许是 Azure 配置的问题?
这取决于您在何处终止 HTTPS,是在 Kestrel 中还是在 Azure 中...Azure 中的许多服务将在您的应用程序外部终止 HTTPS,然后将流量作为 HTTP 发送到您的服务。
{互联网} -> HTTPS -> {Azure Load Balancer/gateway...} -> HTTP -> {您的应用程序}
也可能是由于网络配置导致客户端无法访问IdentityServer。
我有两个服务,API 和 IdentityService4 托管在 Azure 上,带有 Kubernetes(Azure Kubernetes 服务)。
当我 运行 通过 Visual Studio 服务时,一切正常,IS4 正确验证令牌。 但是,当我尝试调用任何需要授权的“生产”请求时,我得到以下异常:
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'.
---> System.ArgumentException: IDX20108: The address specified 'System.String' is not valid as per HTTPS scheme. Please specify an https address for security reasons. If you want to test with http address, set the RequireHttps property on IDocumentRetriever to false. (Parameter 'address')
at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.ConfigurationManager'1.GetConfigurationAsync(CancellationToken cancel)
--- End of inner exception stack trace ---
at Microsoft.IdentityModel.Protocols.ConfigurationManager'1.GetConfigurationAsync(CancellationToken cancel)
我发现了这个问题:https://github.com/IdentityServer/IdentityServer4/issues/4645 并使用了这个解决方案:
app.Use((context, next) => { context.Request.Scheme = "https"; return next(); });
但我不确定这是否是一个“安全”的解决方案,因为它看起来有点老套。
API 配置
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://mylinkttoIS4.com";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
services.AddAuthorization();
services.AddHttpContextAccessor();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use((context, next) => { context.Request.Scheme = "https"; return next(); });
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization();
});
}
IdentityServer4 配置
public void ConfigureServices(IServiceCollection services)
{
var databaseConnectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(databaseConnectionString));
services.AddIdentity<User, IdentityRole<Guid>>().AddEntityFrameworkStores<DatabaseContext>()
.AddDefaultTokenProviders();
services.AddIdentityServer()
.AddSigningCredentialBasedOnEnvironment(Configuration, Environment)
.AddInMemoryApiScopes(IdentityServerConfig.ApiScopes)
.AddInMemoryClients(IdentityServerConfig.Clients)
.AddAspNetIdentity<User>()
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder => builder.UseSqlServer(databaseConnectionString, sql => sql.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name));
options.DefaultSchema = "identity";
})
.AddResourceOwnerValidator<CustomResourceOwnerPasswordValidator>();
services.AddTransient<ISmsSender, SmsSender>();
}
public void Configure(IApplicationBuilder app)
{
app.UseHttpsRedirection();
app.UseIdentityServer();
}
你知道这条线是做什么的吗? 在生产环境中使用安全吗? 也许是 Azure 配置的问题?
这取决于您在何处终止 HTTPS,是在 Kestrel 中还是在 Azure 中...Azure 中的许多服务将在您的应用程序外部终止 HTTPS,然后将流量作为 HTTP 发送到您的服务。
{互联网} -> HTTPS -> {Azure Load Balancer/gateway...} -> HTTP -> {您的应用程序}
也可能是由于网络配置导致客户端无法访问IdentityServer。