身份服务器4声明在API

时间:2018-05-06 08:14:37

标签: asp.net-identity entity-framework-core asp.net-core-2.0 identityserver4

我一直在尝试将Identity Server 4与SPA应用程序集成。我能够在API中授权应用程序,但在授权后,User.Claims始终为empty,尽管我已在范围中添加了声明。

我在API中使用Asp.net Identity与实体框架核心。

我的项目分布在不同的项目中。

  1. Project.Auth(使用Identity Server 4)
  2. Project.Admin
  3. Project.Data(我的上下文和迁移所在的位置)
  4. Project.Domain(Enities)
  5. Project.Service(Repository和ViewModel)
  6. Startup.cs对于Project.Admin

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<MyContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    
            services.AddAuthorization();
    
            services.AddIdentity<User, IdentityRole<Guid>>()
                .AddEntityFrameworkStores<MyContext>()
                .AddDefaultTokenProviders();
    
            services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "https://localhost:44305";
                    options.RequireHttpsMetadata = false;
                    options.ApiName = "api1";
                });
    
            services.AddCors(options =>
            {
                options.AddPolicy("default", policy =>
                {
                    policy.WithOrigins("http://localhost:8080")
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                });
            });
    
            services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
            services.AddScoped<IContractService, ContractService>();
            services.AddScoped<IClientService, ClientService>();
    
            services.AddAutoMapper(mapperConfig => mapperConfig.AddProfiles(GetType().Assembly));
    
    
            services.AddMvcCore()
                .AddJsonFormatters();
        }
    

    Identity Server Setup

    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = builder =>
                builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                    sql => sql.MigrationsAssembly(typeof(MyContext).GetTypeInfo().Assembly.GetName().Name));
        })
        .AddOperationalStore(options =>
        {
            options.ConfigureDbContext = builder =>
                builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                    sql => sql.MigrationsAssembly(typeof(MyContext).GetTypeInfo().Assembly.GetName().Name));
        }).AddAspNetIdentity<User>();
    

    TestUser.cs

    public class TestUsers
    {
        public static List<TestUser> Users = new List<TestUser>
        {
            new TestUser{SubjectId = Guid.NewGuid().ToString(), Username = "alice", Password = "alice",
                Claims =
                {
                    new Claim(JwtClaimTypes.Name, "Alice Smith"),
                    new Claim(JwtClaimTypes.Role,"Admin"),
                    new Claim(JwtClaimTypes.GivenName, "Alice"),
                    new Claim(JwtClaimTypes.FamilyName, "Smith"),
                    new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),
                    new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                    new Claim(JwtClaimTypes.WebSite, "http://alice.com"),
                    new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json)
                }
            }
        };
    }
    

    Client

    new Client
    {
        ClientId = "js",
        ClientName = "JavaScript Client",
        AllowedGrantTypes = GrantTypes.Implicit,
        AllowAccessTokensViaBrowser = true,
        AlwaysIncludeUserClaimsInIdToken = true,
        RedirectUris =            new List<string> {"http://localhost:8080/silent","http://localhost:8080/authredirect"},
        PostLogoutRedirectUris =   { "http://localhost:8080" },
        AllowedCorsOrigins =     { "http://localhost:8080" },
    
        AllowedScopes =
        {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile,
            "api1",
            "role"
        }
    }
    

    ApiResource

    new ApiResource("api1", "My API")
    

    IdentityResources

    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
        return new List<IdentityResource> {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
            new IdentityResources.Email(),
            new IdentityResource {
                Name = "role",
                UserClaims = new List<string> {"role"}
            }
        };
    }
    

    Decode Token

    {
      "nbf": 1525602392,
      "exp": 1525605992,
      "iss": "https://localhost:44305",
      "aud": [
        "https://localhost:44305/resources",
        "api1"
      ],
      "client_id": "js",
      "sub": "c81ce899-77d9-4c34-ab31-b456129ee762",
      "auth_time": 1525601959,
      "idp": "local",
      "scope": [
        "openid",
        "profile",
        "role",
        "api1"
      ],
      "amr": [
        "pwd"
      ]
    }
    

    为什么API能够授权和验证请求,但没有关于用户和声明的详细信息?我错过了API启动课上的任何内容吗?或者在启动类的优先级上存在一些错误配置。

    在我为启动类添加了上下文和服务的DI之前,声明和用户曾经拥有该值。

    我再次尝试删除对Project.Service的引用,并从Project.Admin中的Statrup类中删除所有内容。我能够获得索赔信息。如下图所示。

    Claim Information when Removed Dependency from Start Up

    然而,当我将DI添加到Context和其他服务时。我的索赔信息丢失了。但是,我仍然通过身份验证,并通过了我的授权过滤器。

    Break Point on <code>User.Claims</code>

    编辑:当我检查我的应用程序上的日志时发现错误

    &#34; Identity.Application&#34;未经过身份验证。失败消息:&#34;取消保护票证失败&#34;

2 个答案:

答案 0 :(得分:0)

试试这个

$getID3 = new getID3;
$OldThisFileInfo = $getID3->analyze($Path);
if(isset($OldThisFileInfo['comments']['picture'][0]))
{
    header('Content-Type: ' . $OldThisFileInfo['comments']['picture'][0]['image_mime']);
    echo $OldThisFileInfo['comments']['picture'][0]['data'];
    die;
}

我不是专家,但我认为这是你应该如何处理声明,而不是旧版本的Asp.Net,其中放置用户足够

答案 1 :(得分:0)

我找到了解决这个问题的方法。我在代码上遗漏了几件事:

  1. 存在对IdentityServer4.AccessTokenValidation的重复引用。
  2. 我错过了我的API DefaultChallengeScheme

    上的ConfigureServices
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = "oidc";
    })
    .AddIdentityServerAuthentication(options =>
    {
      options.Authority = "https://localhost:44305";
      options.RequireHttpsMetadata = false;
      options.ApiName = "api1";
    });
    
  3. 所以我的配置服务变得如下:

     public void ConfigureServices(IServiceCollection services)
    {
    
        services.AddMvcCore().AddAuthorization().AddJsonFormatters();
    
        var connectionString = Configuration.GetConnectionString("DefaultConnection");
        services.AddDbContext<MyContext>(o => o.UseSqlServer(connectionString));
        services.AddIdentity<User, IdentityRole<Guid>>().AddEntityFrameworkStores<MyContext>().AddDefaultTokenProviders();
    
    
        services.AddAuthentication(
            options =>
            {
                options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = "oidc";
            })
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = "https://localhost:44305";
            options.RequireHttpsMetadata = false;
            options.ApiName = "api1";
    
        });
    
        services.AddCors(options =>
        {
            // this defines a CORS policy called "default"
            options.AddPolicy("default", policy =>
            {
                policy.WithOrigins("http://localhost:8080")
                    .AllowAnyHeader()
                    .AllowAnyMethod();
            });
        });
        services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
        services.AddScoped<IContractService, ContractService>();
        services.AddScoped<IClientService, ClientService>();
    
        services.AddAutoMapper(mapperConfig => mapperConfig.AddProfiles(GetType().Assembly));
    
    }
    

    更改以上两项内容解决了我的遗漏索赔问题以及没有承载令牌的Authorized