具有EF Identity DB的Identity Server 4问题 [英] Identity Server 4 with EF Identity DB Issue

查看:102
本文介绍了具有EF Identity DB的Identity Server 4问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆