I am using duende template for creating customized identity server, and there I need some Apis and I have implemented those in the same project
My Apis should be authenticated via same identity sever with a bearer token.
it was working as expected when I use two projects but when I use same project and same program.cs it's giving below error "**The supplied principal does not contain a claim of type http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier**"
I'll attach my program.cs here
using Azure.Identity;
using Duende.IdentityServer.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
using Newtonsoft.Json;
using Microsoft.OpenApi.Models;
using Duende.IdentityServer;
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
var identity = config.GetValue<string>("ManagedIdentity");
var env = builder.Configuration.GetValue<string>("Env");
var connectionString = config.GetConnectionString("DefaultConnection");
config.AddAzureAppConfiguration(options =>
{
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = identity });
options.Connect(connectionString)
.Select("Common:*", LabelFilter.Null)
.Select("Common:*", env)
.Select("Identity:*", LabelFilter.Null)
.Select("Identity:*", env)
.ConfigureKeyVault(options =>
{
options.SetCredential(credential);
})
.ConfigureRefresh(refreshoptions => refreshoptions.Register("version", refreshAll: true));
});
builder.Services.AddCors(options =>
{
options.AddPolicy(
name: "AllowedOriginsPolicy",
policy =>
{
policy.WithOrigins("*").AllowAnyHeader().AllowAnyMethod();
}
);
});
builder.Services
.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Include;
});
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = builder.Configuration.GetValue<string>("Identity:AuthorityUrl");
options.Audience = builder.Configuration.GetValue<string>("Identity:ApiClientId");
options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddApplicationServices();
builder.Services.AddInfrastructure();
builder.Services.AddWebApiServices();
builder.Services.AddSwaggerGen(options =>
{
options.AddSecurityDefinition(
"oauth2",
new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
AuthorizationCode = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri(
$"{builder.Configuration.GetValue<string>("Identity:AuthorityUrl")}/connect/authorize"
),
TokenUrl = new Uri(
$"{builder.Configuration.GetValue<string>("Identity:AuthorityUrl")}/connect/token"
),
Scopes = new Dictionary<string, string>
{
{ "inzinqidentity.api", "Identity API" },
{"openid","openid" },
{"profile","profile" }
}
}
},
BearerFormat = "JWT",
In = ParameterLocation.Query,
Scheme = "bearer",
OpenIdConnectUrl = new Uri(
$"{builder.Configuration.GetValue<string>("Identity:AuthorityUrl")}/.well-known/openid-configuration"),
}
);
options.AddSecurityRequirement(new OpenApiSecurityRequirement() {
{
new OpenApiSecurityScheme {
Reference = new OpenApiReference {
Type = ReferenceType.SecurityScheme,
Id = "oauth2"
},
Scheme = "oauth2",
Name = "oauth2",
In = ParameterLocation.Header,
},
new List <string> ()
}
});
options.OperationFilter<SwaggerOperationFilter>();
options.SchemaFilter<SwaggerSchemaFilter>();
});
builder.Services.AddRazorPages();
var dbConnection = config.GetValue<string>("Identity:IdentityServerConnectionString");
builder.Services.AddIdentityServer(dbConnection);
builder.Services.AddScoped<IProfileService, ProfileService>();
var salt = config.GetValue<string>("Identity:Salt");
PasswordHashValidator.AssignSalt(salt);
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1");
options.OAuthClientId(builder.Configuration.GetValue<string>("Identity:ApiClientId"));
options.OAuthClientSecret(
builder.Configuration.GetValue<string>("Identity:ApiClientSecret")
);
options.OAuthUsePkce();
options.OAuthUseBasicAuthenticationWithAccessCodeGrant();
});
app.UseIdentityServer();
app.UseCors("AllowedOriginsPolicy");
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages().RequireAuthorization();
app.Run();
And here I grab the claims
public class CurrentUserService : ICurrentUserService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CurrentUserService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string? UserId => _httpContextAccessor.HttpContext?.User?.GetNameIdentifier();
public string? Email => _httpContextAccessor.HttpContext?.User.GetEmailValue();
}
here httpContextAccessor.User.claims are always empty.