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.
I am using Asp.net Identity in API with entity framework core.
My project are distributed in different projects.
- Project.Auth (using Identity Server 4)
- Project.Admin
- Project.Data (where my Context and Migration Lies)
- Project.Domain(Enities)
- Project.Service(Repository and ViewModel)
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, "[email protected]"),
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"
]
}
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.
The Claims and User used to have the value before i added the DI for Context and Services on the Startup Class.
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.
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" was not authenticated. Failure message: "Unprotect ticket failed"
See Question&Answers more detail:
os