New to the whole Identity concept but I've had a couple of Google searches and haven't found a reply I felt fitting.
I'm using .NET Core 1.0.0 with EF Core and IdentityServer 4 (ID4). The ID4 is on a separate server and the only information I get in the client is the claims. I'd like to have access to the full (extended) user profile, preferrably from User.Identity.
So how to I set up so that the User.Identity is populated with all the properties on the ApplicationUser model without sending a DB request every time? I'd like the information to be stored in cache on authentication until the session ends.
What I don't want to do is that in each controller set up a query to get the additional information. All controllers on the client will be inheriting from a base controller, meaning I could DI some service if that's necessary.
Thanks in advance.
Client
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = Configuration.GetSection("IdentityServer").GetValue<string>("Authority"),
RequireHttpsMetadata = false,
ClientId = "RateAdminApp"
});
ID4
app.UseIdentity();
app.UseIdentityServer();
services.AddDeveloperIdentityServer()
.AddOperationalStore(builder => builder.UseSqlServer("Server=localhost;Database=Identities;MultipleActiveResultSets=true;Integrated Security=true", options => options.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name)))
.AddConfigurationStore(builder => builder.UseSqlServer("Server=localhost;Database=Identities;MultipleActiveResultSets=true;Integrated Security=true", options => options.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name)))
.AddAspNetIdentity<ApplicationUser>();
ApplicationUser Model
public class ApplicationUser : IdentityUser
{
[Column(TypeName = "varchar(100)")]
public string FirstName { get; set; }
[Column(TypeName = "varchar(100)")]
public string LastName { get; set; }
[Column(TypeName = "nvarchar(max)")]
public string ProfilePictureBase64 { get; set; }
}
If you want to transform claims on the identity server, for your case(you use aspnet identity) overriding UserClaimsPrincipalFactory
is a solution(see Store data in cookie with asp.net core identity).
public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
{
public AppClaimsPrincipalFactory(
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager,
IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)
{
}
public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
{
var principal = await base.CreateAsync(user);
((ClaimsIdentity)principal.Identity).AddClaims(new[] {
new Claim("FirstName", user.FirstName)
});
return principal;
}
}
// register it
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, AppClaimsPrincipalFactory>();
Also you can use events(on the client application) to add extra claims into cookie, it provides claims until the user log out.
There are two(maybe more than) options:
First using OnTicketReceived
of openidconnect authentication:
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = Configuration.GetSection("IdentityServer").GetValue<string>("Authority"),
RequireHttpsMetadata = false,
ClientId = "RateAdminApp",
Events = new OpenIdConnectEvents
{
OnTicketReceived = e =>
{
// get claims from user profile
// add claims into e.Ticket.Principal
e.Ticket = new AuthenticationTicket(e.Ticket.Principal, e.Ticket.Properties, e.Ticket.AuthenticationScheme);
return Task.CompletedTask;
}
}
});
Or using OnSigningIn
event of cookie authentication
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookies",
Events = new CookieAuthenticationEvents()
{
OnSigningIn = async (context) =>
{
ClaimsIdentity identity = (ClaimsIdentity)context.Principal.Identity;
// get claims from user profile
// add these claims into identity
}
}
});
See similar question for solution on the client application: Transforming Open Id Connect claims in ASP.Net Core