Identity Server 4声明API空 [英] Identity Server 4 Claims empty on API

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

问题描述

我一直在尝试将Identity Server 4与SPA应用程序集成.我可以使用API​​来授权应用程序,但是在授权之后,尽管User.Claims总是empty,但是我已经在范围中添加了Claims.

I have been trying to Integrate Identity Server 4 with SPA application. I am able to Authorize the Application in API but after the authorization the User.Claims are always empty though i have added the Claims in Scopes.

我在具有实体框架核心的API中使用Asp.net Identity.

I am using Asp.net Identity in API with entity framework core.

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

My project are distributed in different projects.

  1. Project.Auth(使用Identity Server 4)
  2. Project.Admin
  3. Project.Data(我的上下文和迁移所在的位置)
  4. Project.Domain(Enities)
  5. Project.Service(存储库和ViewModel)

Startup.cs对于Project.Admin

Startup.cs For 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启动课程的任何内容?或启动类的优先级上有一些错误配置.

Why the API is able to authorize and authenticate the Request but no Details on User and Claims? Did i missed anything on the API startup class? or there is some misconfiguration on the precedence on the startup class.

在我在启动类上为上下文和服务添加DI之前,Claims和User一直具有该值.

The Claims and User used to have the value before i added the DI for Context and Services on the Startup Class.

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

I tried again by removing the references to Project.Service and removing every thing from the Statrup class in Project.Admin. I was able to get the Claim information. As shown below.

但是,当我将DI添加到Context和其他服务中时.我的理赔信息丢失了.但是,我仍然通过了身份验证,它正在通过我的授权过滤器".

However when i add the DI to Context and other services. My Claim info got lost. However i am still authenticated and it is passing my Authorize Filter.

当我检查应用程序上的日志时,发现一个错误

Edited: When i was checking the log on my application i found a error

"Identity.Application"未通过身份验证.失败消息:取消保护票证失败"

推荐答案

我已经找到解决此问题的方法.我在代码中遗漏了几件事:

I have found my Solution for this problem. I was missing couple of things on my code:

  1. 有对IdentityServer4.AccessTokenValidation的重复引用.
  2. 我在我的API ConfigureServices

  1. There was the Duplicate references to IdentityServer4.AccessTokenValidation.
  2. I was missing the DefaultChallengeScheme on my API ConfigureServices

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = "oidc";
})
.AddIdentityServerAuthentication(options =>
{
  options.Authority = "https://localhost:44305";
  options.RequireHttpsMetadata = false;
  options.ApiName = "api1";
});

所以我的配置服务如下:

So my Configure Service became like below:

 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没有持票人令牌的问题.

Changing above two things solved my problem for missing claims and Authorized without the Bearer Token.

这篇关于Identity Server 4声明API空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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