Identity Server 4: пустые заявки на API - PullRequest
0 голосов
/ 06 мая 2018

Я пытался интегрировать Identity Server 4 с приложением SPA. Я могу авторизовать приложение в API, но после авторизации User.Claims всегда empty, хотя я добавил претензии в областях.

Я использую Asp.net Identity в API с ядром платформы сущностей.

Мой проект распределен по разным проектам.

  1. Project.Auth (с использованием Identity Server 4)
  2. Project.Admin
  3. Project.Data (где мой контекст и миграция)
  4. Project.Domain (Enities)
  5. Project.Service (Репозиторий и ViewModel)

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 и удалив все из класса Statrup в Project.Admin. Я смог получить информацию о претензии. Как показано ниже.

Claim Information when Removed Dependency from Start Up

Однако, когда я добавляю DI в Context и другие службы. Моя информация о претензии потерялась. Однако я все еще аутентифицирован, и он проходит мой Фильтр Авторизации.

imageUser.Claims">

Отредактировано: когда я проверял журнал в моем приложении, я обнаружил ошибку

«Identity.Application» не был аутентифицирован. Сообщение об ошибке: «Снять незащищенный билет»

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Я нашел свое решение для этой проблемы. Мне не хватало пары вещей в моем коде:

  1. Дубликаты ссылок на IdentityServer4.AccessTokenValidation.
  2. Мне не хватало DefaultChallengeScheme в моем 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";
    });
    

Итак, моя служба настройки стала такой, как показано ниже:

 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 без жетона на предъявителя.

0 голосов
/ 06 мая 2018

Попробуйте это

var user = User.Claims.First(claim => claim.Type=="Name").Value(); 

Я не эксперт, но я думаю, что именно так вы должны работать с утверждениями вместо более старых версий Asp.Net, где достаточно размещения пользователя

...