Web API assumes that authentication happens in the host. For web-hosting, the host is IIS, which uses HTTP modules for authentication. You can configure your project to use any of the authentication modules built in to IIS or ASP.NET, or write your own HTTP module to perform custom authentication.
I am using IdentityServer4 with .Net Core 2.1 and Asp.Net Core Identity. I have two projects in my Solution.
I want to Protect my Web APIs, I use postman for requesting new tokens, It works and tokens are generated successfully. When I use [Authorize]
on my controllers without Roles it works perfectly but when I use [Authorize(Roles="Student")]
(even with [Authorize(Policy="Student")]
) it always return 403 forbidden
Whats wrong with my code
Web API startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddAuthorization(options => options.AddPolicy("Student", policy => policy.RequireClaim("Role", "Student")))
.AddAuthorization(options => options.AddPolicy("Teacher", policy => policy.RequireClaim("Role", "Teacher")))
.AddAuthorization(options => options.AddPolicy("Admin", policy => policy.RequireClaim("Role", "Admin")))
.AddJsonFormatters();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
}
Test API :
[Route("api/[controller]")]
[ApiController]
[Authorize(Roles="Student")]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
IdentityServer startup.cs
public class Startup
{
public IConfiguration Configuration { get; }
public IHostingEnvironment Environment { get; }
public Startup(IConfiguration configuration, IHostingEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
string connectionString = Configuration.GetConnectionString("DefaultConnection");
string migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.Configure<IISOptions>(iis =>
{
iis.AuthenticationDisplayName = "Windows";
iis.AutomaticAuthentication = false;
});
IIdentityServerBuilder builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddAspNetIdentity<ApplicationUser>()
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
// options.TokenCleanupInterval = 15; // frequency in seconds to cleanup stale grants. 15 is useful during debugging
})
.AddProfileService<ProfileService>();
if (Environment.IsDevelopment())
{
builder.AddDeveloperSigningCredential();
}
else
{
throw new Exception("need to configure key material");
}
services.AddAuthentication();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// InitializeDatabase(app);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
//app.Run(async (context) =>
//{
// await context.Response.WriteAsync("Hello World!");
//});
}
}
}
IdentityServer4 config.cs
public class Config
{
// scopes define the resources in your system
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API"),
new ApiResource("roles", "My Roles"),
new IdentityResource("roles", new[] { "role" })
};
}
// clients want to access resources (aka scopes)
public static IEnumerable<Client> GetClients()
{
// client credentials client
return new List<Client>
{
// resource owner password grant client
new Client
{
ClientId = "ro.client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1","roles" }
}
};
}
}
Token Sample
eyJhbGciOiJSUzI1NiIsImtpZCI6ImU0ZjczZDU5MjQ2YjVjMmFjOWVkNDI2ZGU4YzlhNGM2IiwidHlwIjoiSldUIn0.eyJuYmYiOjE1NDYyNTk0NTYsImV4cCI6MTU0NjI2MzA1NiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJhcGkxIl0sImNsaWVudF9pZCI6InJvLmNsaWVudCIsInN1YiI6IjIiLCJhdXRoX3RpbWUiOjE1NDYyNTk0NTYsImlkcCI6ImxvY2FsIiwic2NvcGUiOlsicm9sZXMiLCJhcGkxIl0sImFtciI6WyJwd2QiXX0.D6OvbrGx2LwrYSySne59VJ_-_kZ-WriNUbDiETiHO4pknYJzBxKr307DxvBImlvP8w35Cxj3rKxwyWDqVxyhdFhFvFFuHmxqIAv_g2r37lYj3ExcGYAn23Q1i4PuXXBWQe2AHuwFsN2cfPcG39f-N-q7pfLFhoHacXe8vSWyvKxSD0Vj3qVz15cj5VMV1R8qhodXMO-5sZfY1wNfkcJmqmXnbpPnUK_KKUY1Pi6YJkU1nYRXGRoW7YLXc7Y2SFSfa9c1ubU3DDVJV0JqVxSBpfGnvydHEpk-gBx11yQgW5nsJdu6Bi2-DVGA5AdZ_-7pz0AVI-eZPwk2lNtlivmoeA
APS.NET_USERS Table
APS.NET_USERS_Claims Table
Postman
ApiRequest
Claims While Using [Authorize]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With