具有EF Identity DB的Identity Server 4问题 [英] Identity Server 4 with EF Identity DB Issue
问题描述
我正在尝试使用EF Identity DB设置Identity Server 4解决方案.我可能遇到的问题是身份数据库中存储的信息.不知道我是否有正确的客户端,API,Provision,Scopes ...设置.这是我第一次使用EF Identity DB.如果可以帮助解决问题,我可以发布数据库信息.
I'm trying to setup an Identity Server 4 solution with EF Identity DB. The issue I'm having maybe with info stored in the Identity DB. Not sure if I have the client, API, Provision, Scopes... setup correct. This is my first attempt working with EF Identity DB. I can post DB info if it helps resolve the issue.
我能够登录并检索安全用户声明"信息,
I'm able to login and retrieve the Secure User Claim information,
Identity Server(来自API的请求)令牌请求验证和令牌验证成功.下面的日志信息:
The Identity Server (Request from API) Token request validation and Token validation are successful. Log info below:
令牌请求验证成功
{
"ClientId": "mvc",
"ClientName": "mvc.client",
"GrantType": "authorization_code",
"AuthorizationCode": "416bf70a2fdfc9b507207e2d2ebaea04b1d26b0dbeab246c3a08c14d4eed0d88",
"Raw": {
"client_id": "mvc",
"client_secret": "***REDACTED***",
"code": "416bf70a2fdfc9b507207e2d2ebaea04b1d26b0dbeab246c3a08c14d4eed0d88",
"grant_type": "authorization_code",
"redirect_uri": "http://localhost:5002/signin-oidc"
}
}
令牌验证成功
{
"ValidateLifetime": true,
"AccessTokenType": "Jwt",
"ExpectedScope": "openid",
"Claims": {
"nbf": 1517178337,
"exp": 1517181937,
"iss": "http://localhost:5000",
"aud": "http://localhost:5000/resources",
"client_id": "mvc",
"sub": "8ae24a28-59f5-48a6-92c6-c6cac551341b",
"auth_time": 1517178333,
"idp": "local",
"scope": [
"openid",
"profile",
"api1"
],
"amr": "pwd"
}
}
,但API令牌授权失败. API失败,并显示错误消息:
but API Token authorization is failing. The API fails with error message:
2018-01-28 17:28:38.011 -05:00 [INF] Failed to validate the token eyJhbGciOiJSUzI1NiIsImtpZCI6IjY3NTYzMGI1NWQ3NWE3OTI4MmNmZWI2OGNiN2I2MDZmIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MTcxNzgzMzcsImV4cCI6MTUxNzE4MTkzNywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwL3Jlc291cmNlcyIsImNsaWVudF9pZCI6Im12YyIsInN1YiI6IjhhZTI0YTI4LTU5ZjUtNDhhNi05MmM2LWM2Y2FjNTUxMzQxYiIsImF1dGhfdGltZSI6MTUxNzE3ODMzMywiaWRwIjoibG9jYWwiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwiYXBpMSJdLCJhbXIiOlsicHdkIl19.meLK1puLfEapFz-sL5IC9NlByfecDDtasPa_Vzba62FZXRJZijlQHysVNRbDKBI5TMqJf3GEs30D4U4T_IoCPz75lkLqCC4XtKROpsIwktm6lpHs-2GEXAZRmhLYDvmlUqwBNmv94XeuiYX8JWm9M-EHIL96Pn4eSlo-ItStgpHCK4sGfSUlTK_CZAfjfgeNXrhR0Sh9ZlXhZyZ5ucyQf8goLSJFk8SkFz3gsNA_gn_L_Q8r7cQk_Sq7Dyqq2YAvTocnwgp8o3UXOEf7h_rGnslLJqLbsnj9Cz8dZPuhknFgP2XZQn1m7ctAuVkz4s4mSJ75g--wYPQ1mJZUHV3l2Q.
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidAudienceException: IDX10214: Audience validation failed. Audiences: 'http://localhost:5000/resources'. Did not match: validationParameters.ValidAudience: 'api1' or validationParameters.ValidAudiences: 'null'.
at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
这是上面的令牌信息:
Here is the token info above:
这是API启动类:
#region "ConfigureServices"
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
}
#endregion
#region "Configure"
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseAuthentication();
app.UseMvc();
}
#endregion
这是MVC客户端启动类:
Here is the MVC Client Startup class:
#region "ConfigureServices"
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("api1");
options.Scope.Add("openid");
//options.Scope.Add("offline_access");
});
}
#endregion
#region "Configure"
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseAuthentication();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
#endregion
这是Identity Server启动:
Here is the Identity Server Startup:
#region "ConfigureServices"
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
services.AddMvc();
string connectionString = Configuration.GetConnectionString("DefaultConnection");
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddAspNetIdentity<ApplicationUser>()
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 120; // interval in seconds. 15 seconds useful for debugging
});
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.ClientId = "434483408261-55tc8n0cs4ff1fe21ea8df2o443v2iuc.apps.googleusercontent.com";
options.ClientSecret = "3gcoTrEDPPJ0ukn_aYYT6PWo";
})
.AddOpenIdConnect("oidc", "OpenID Connect", options =>
{
//options.Authority = "https://demo.identityserver.io/";
//options.ClientId = "implicit";
//options.SaveTokens = true;
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.SaveTokens = true;
options.ClientId = "mvc";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
}
#endregion
#region "Configure"
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
// app.UseAuthentication(); // not needed, since UseIdentityServer adds the authentication middleware
app.UseIdentityServer();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
#endregion
MVC客户端控制器:
MVC Client Controller:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
using System.Net.Http;
using Newtonsoft.Json.Linq;
using IdentityModel.Client;
namespace MvcClient.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[Authorize]
public IActionResult Secure()
{
ViewData["Message"] = "Secure page.";
return View();
}
public async Task Logout()
{
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
}
public IActionResult Error()
{
return View();
}
public async Task<IActionResult> CallApiUsingClientCredentials()
{
var tokenClient = new TokenClient("http://localhost:5000/connect/token", "mvc", "secret");
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");
var client = new HttpClient();
client.SetBearerToken(tokenResponse.AccessToken);
var content = await client.GetStringAsync("http://localhost:5001/identity");
ViewBag.Json = JArray.Parse(content).ToString();
return View("json");
}
public async Task<IActionResult> CallApiUsingUserAccessToken()
{
var accessToken = await HttpContext.GetTokenAsync("access_token");
var client = new HttpClient();
client.SetBearerToken(accessToken);
var content = await client.GetStringAsync("http://localhost:5001/identity");
ViewBag.Json = JArray.Parse(content).ToString();
return View("json");
}
}
}
API控制器:
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using IdentityServer4.AccessTokenValidation;
namespace Api.Controllers
{
[Route("[controller]")]
[Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme)]
public class IdentityController : ControllerBase
{
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
}
}
感谢您的协助,以解决此问题并增进我的知识.保罗
Appreciate your assistance resolving this issue and furthering my knowledge. Paul
推荐答案
提供的代码不会增加价值.我想看看您是如何配置api1的.似乎您的配置缺少某些内容.下表应包含api1的记录:
The provided code doesn't add value. What I would like to see is how you configured api1. It seems that your configuration is missing something. The following tables should contain a record for api1:
- ApiResources:Name = api1和Enabled = true
- ApiScopes:Name = api1和ApiResourceId应该链接到ApiResource
- ClientScopes:Scope = api1和ClientId链接到您的客户端
这篇关于具有EF Identity DB的Identity Server 4问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!