Oauth 2.0 .NET Core 3.1 IdentityServer 4:使用资源所有者密码凭据授予时获取无效访问令牌
我正在尝试使用资源所有者密码凭据授权类型从身份提供程序获取访问令牌。相同的配置适用于.NET Core 2.2,但不再适用于.NET Core 3.1。以下是标识提供程序的配置:Oauth 2.0 .NET Core 3.1 IdentityServer 4:使用资源所有者密码凭据授予时获取无效访问令牌,oauth-2.0,jwt,identityserver4,openid-connect,asp.net-core-3.1,Oauth 2.0,Jwt,Identityserver4,Openid Connect,Asp.net Core 3.1,我正在尝试使用资源所有者密码凭据授权类型从身份提供程序获取访问令牌。相同的配置适用于.NET Core 2.2,但不再适用于.NET Core 3.1。以下是标识提供程序的配置: public class Startup { public IConfiguration Configuration { get; } private readonly string _MyAllowSpecificOrigins = "fooorigin"; private readonly
public class Startup
{
public IConfiguration Configuration { get; }
private readonly string _MyAllowSpecificOrigins = "fooorigin";
private readonly IWebHostEnvironment _env;
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
IdentityModelEventSource.ShowPII = true;
_env = env;
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddPersistence(Configuration); //Custom extension
services.AddAutoMapper(Assembly.GetAssembly(typeof(BaseMappingProfile)));
#region Options
services.Configure<IdentityServerOptions>(Configuration.GetSection("IdentityServerOptions"));
services.Configure<Settings>(Configuration.GetSection("Settings"));
#endregion
#region Configurations
services.AddTransient<IdentityServerOptions>();
#endregion
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<ITokenManagerHelper, TokenManagerHelper>();
services.AddScoped<IUserService, UserService>();
services.AddCors(options =>
{
options.AddPolicy(_MyAllowSpecificOrigins,
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddMvc().AddFluentValidation(fv =>
{
fv.RegisterValidatorsFromAssemblyContaining<CommonValidator>();
fv.ImplicitlyValidateChildProperties = true;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
var identityServerDataDBConnectionString = Configuration.GetConnectionString("IdentityServerConfigDatabase");
var migrationsAssembly = typeof(UsersDbContext).GetTypeInfo().Assembly.GetName().Name;
var identityAuthority = Configuration.GetValue<string>("IdentityServerOptions:Authority");
// Add Authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = Configuration.GetValue<string>("IdentityServerOptions:Authority");
options.ClientId = Configuration.GetValue<string>("IdentityServerOptions:ClientName");
options.ClientSecret = Configuration.GetValue<string>("IdentityServerOptions:ClientSecret");
options.ResponseType = Configuration.GetValue<string>("IdentityServerOptions:ResponseType");
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("roles");
options.Scope.Add("fooapi");
options.Scope.Add("fooidentityapi");
options.Scope.Add("offline_access");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.Remove("amr");
options.ClaimActions.DeleteClaim("sid");
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.GivenName,
RoleClaimType = JwtClaimTypes.Role,
};
});
services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
// Add Identity Server
// Add Signing Certificate
// Add Users Store
// Add Configurations Store
// Add Operational Stores
if (_env.IsDevelopment() || _env.IsStaging())
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddUserStore()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
{
builder.UseSqlServer(identityServerDataDBConnectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
};
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
{
builder.UseSqlServer(identityServerDataDBConnectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
};
})
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();
}
else
{
//Todo: add certificate
}
}
public void Configure(
IApplicationBuilder app,
IWebHostEnvironment env,
IOptions<Settings> settingOptions)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(_MyAllowSpecificOrigins);
app.UseCookiePolicy();
var forwardOptions = new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
RequireHeaderSymmetry = false
};
forwardOptions.KnownNetworks.Clear();
forwardOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardOptions);
app.UseAuthentication();
app.UseRouting();
app.UseIdentityServer();
}
}
公共类启动
{
公共IConfiguration配置{get;}
私有只读字符串\u MyAllowSpecificOrigins=“foooorigin”;
私人只读IWebHostEnvironment;
公共启动(IConfiguration配置,IWebHostEnvironment环境)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
IdentityModelEventSource.ShowPII=true;
_env=env;
配置=配置;
}
public void配置服务(IServiceCollection服务)
{
配置(选项=>
{
options.checkApprovered=context=>true;
options.MinimumSameSitePolicy=SameSiteMode.None;
});
services.AddPersistence(配置);//自定义扩展
AddAutoMapper(Assembly.GetAssembly(typeof(BaseMappingProfile));
#区域选项
Configure(Configuration.GetSection(“IdentityServerOptions”);
services.Configure(Configuration.GetSection(“设置”));
#端区
#区域配置
services.AddTransient();
#端区
services.AddSingleton();
services.addScope();
services.addScope();
services.AddCors(选项=>
{
options.AddPolicy(_MyAllowSpecificOrigins,
生成器=>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddMvc().AddFluentValidation(fv=>
{
fv.RegisterValidatorsFromAssemblyContaining();
fv.ImplicitlyValidateChildProperties=true;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
var identityServerDataDBConnectionString=Configuration.GetConnectionString(“IdentityServerConfigDatabase”);
var migrationassembly=typeof(UsersDbContext.GetTypeInfo().Assembly.GetName().Name;
var identityAuthority=Configuration.GetValue(“IdentityServerOptions:Authority”);
//添加身份验证
services.AddAuthentication(选项=>
{
options.DefaultAuthenticateScheme=CookieAuthenticationDefaults.AuthenticationScheme;
options.defaultsignnscheme=CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultScheme=CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme=“oidc”;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(“oidc”,选项=>
{
options.signnscheme=CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority=Configuration.GetValue(“IdentityServerOptions:Authority”);
options.ClientId=Configuration.GetValue(“IdentityServerOptions:ClientName”);
options.ClientSecret=Configuration.GetValue(“IdentityServerOptions:ClientSecret”);
options.ResponseType=Configuration.GetValue(“IdentityServerOptions:ResponseType”);
options.Scope.Add(“openid”);
选项。范围。添加(“配置文件”);
选项。范围。添加(“角色”);
选项。范围。添加(“fooapi”);
options.Scope.Add(“foodIdentityAPI”);
options.Scope.Add(“脱机访问”);
options.SaveTokens=true;
options.GetClaimsFromUserInfoEndpoint=true;
选项。索赔。删除(“amr”);
选项。索赔。删除索赔(“sid”);
options.TokenValidationParameters=新的TokenValidationParameters
{
NameClaimType=JwtClaimTypes.GivenName,
RoleClaimType=JwtClaimTypes.Role,
};
});
services.AddTransient();
services.AddTransient();
//添加身份服务器
//添加签名证书
//添加用户存储
//添加配置存储
//添加运营商店
如果(_env.IsDevelopment()| | | u env.istaging())
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddUserStore()
.AddConfigurationStore(选项=>
{
options.ConfigureDbContext=builder=>
{
builder.UseSqlServer(identityServerDataDBConnectionString,
sql=>sql.migrationassembly(migrationassembly));
};
})
.addStore(选项=>
{
options.ConfigureDbContext=builder=>
{
builder.UseSqlServer(identityServerDataDBConnectionString,
sql=>sql.migrationassembly(migrationassembly));
};
})
.AddResourceOwnerValidator();
}
其他的
{
//Todo:添加证书
}
}
公共无效配置(
IApplicationBuilder应用程序,
IWebHostenvironmentEnv,
IOptions设置选项)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
其他的
{
app.UseHsts();
}
应用程序UseCors(_MyAllowSpecificCorigins);
app.UseCookiePolicy();
var forwardOptions=新ForwardedHeadersOptions
{
ForwardedHeaders=ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
RequireHeaderSymmetry=假
};
转发选项
public class Startup
{
#region Private Fields
private readonly string _allowedOrigins = "fooorigin";
#endregion
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthorization();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = Configuration.GetValue<string>("IdentityServerOptions:Authority");
options.RequireHttpsMetadata = false;
options.ApiName = Configuration.GetValue<string>("IdentityServerOptions:ApiName");
options.SupportedTokens = IdentityServer4.AccessTokenValidation.SupportedTokens.Jwt;
});
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
#region Options
services.AddOptions();
#endregion
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddCors(options =>
{
options.AddPolicy(_allowedOrigins, builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
});
services.AddMvc(o =>
{
o.EnableEndpointRouting = false;
o.Conventions.Add(new ApiExplorerGroupPerVersionConvention());
o.Filters.Add(new ModelStateFilter());
}).AddFluentValidation(fv =>
{
fv.RegisterValidatorsFromAssemblyContaining<CommonValidator>();
fv.ImplicitlyValidateChildProperties = true;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
#region Customise default API behavour
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
#endregion
#region Versioning
services.AddApiVersioning(o =>
{
o.ApiVersionReader = new HeaderApiVersionReader("api-version");
o.DefaultApiVersion = new ApiVersion(1, 0);
o.AssumeDefaultVersionWhenUnspecified = true;
o.ReportApiVersions = true;
});
#endregion
#region Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1.0", new OpenApiInfo
{
Title = Configuration.GetValue<string>("SwaggerDocOptions:Title"),
Version = Configuration.GetValue<string>("SwaggerDocOptions:Version"),
Description = Configuration.GetValue<string>("SwaggerDocOptions:Description")
});
c.OperationFilter<RemoveApiVersionFromParamsOperationFilter>();
var basePath = PlatformServices.Default.Application.ApplicationBasePath;
var xmlPath = Path.Combine(basePath, "foo.xml");
c.IncludeXmlComments(xmlPath);
var scopes = Configuration.GetValue<string>("IdentityServerOptions:RequiredScopes").Split(',').ToList();
var scopesDictionary = new Dictionary<string, string>();
foreach (var scope in scopes)
{
scopesDictionary.Add(scope, scope);
}
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
Type = SecuritySchemeType.OAuth2,
Scheme = "Bearer",
Flows = new OpenApiOAuthFlows
{
Password = new OpenApiOAuthFlow
{
TokenUrl = new Uri(Configuration.GetValue<string>("IdentityServerOptions:TokenEndpoint")),
Scopes = scopesDictionary
}
},
In = ParameterLocation.Header
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Type = SecuritySchemeType.Http,
Scheme = "Bearer",
Name = "Bearer",
In = ParameterLocation.Header
},
new List<string>()
}
});
});
#endregion
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app">Application builder</param>
/// <param name="env">Web host environment</param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(_allowedOrigins);
app.UseAuthentication();
app.UseSerilogRequestLogging();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseSwagger(
o =>
{
o.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
{
var paths = new OpenApiPaths();
foreach (var x in swaggerDoc.Paths)
{
var key = x.Key.Contains("{version}") ? x.Key.Replace("{version}", swaggerDoc.Info.Version) : x.Key;
paths.Add(key, x.Value);
}
swaggerDoc.Paths = paths;
swaggerDoc.Extensions.Add(
new KeyValuePair<string,
IOpenApiExtension>("x-identity-authority",
new OpenApiString(Configuration.GetValue<string>("IdentityServerOptions:Authority"))));
});
o.RouteTemplate = "docs/{documentName}/swagger.json";
});
app.UseSwaggerUI(
c =>
{
c.SwaggerEndpoint("/docs/v1.0/swagger.json", "Foo API");
c.OAuthClientId(Configuration.GetValue<string>("IdentityServerOptions:ClientName"));
c.OAuthClientSecret(Configuration.GetValue<string>("IdentityServerOptions:ClientSecret"));
}
);
}
}