1

We are currently working on a identityserver4 implementation which will also have a few api calls.

Those api calls should only be available if a user is authorized(with the bearer token).

In the Startup.cs we have the services.AddIdentityServer() since this is the identityServer, and also added the AddAuthentication() call to make sure the authorized endpoints are only available for authorized connections.

Startup.cs => ConfigureServices():

services.AddIdentityServer();                
services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "http://localhost:9000";
                    options.RequireHttpsMetadata = false;

                    options.ApiName = "identityserver4";
                });

Startup.cs => Configure():

        app.UseAuthentication();

        app.UseIdentityServer();

        //app.UseAuthentication();

using the UseAuthentication() before or after UseIdentityServer() does not change anything.

My api call within the identityserver is still avaialble to all. Currently using postman to test the calls.

Do i need to add something? Is there something i missed?

Kind regards,

Walter

edit 1: added controller and full startup.cs UserController.cs:

namespace Identity.Controllers
{
    [Authorize]
    [Route("[controller]")]

    public class UserController : ControllerBase
    {
        private readonly ILogger _logger;
        private readonly IUserBusinessLogic _userBusinessLogic;

        public UserController(ILogger<UserController> logger, IUserBusinessLogic userBusinessLogic)
            : base()
        {
            _logger = logger;
            _userBusinessLogic = userBusinessLogic;
        }

        [Route("")]
        [HttpGet]        
        public async Task<ActionResult<IList<UserDto>>> GetAllUsers()
        {
            var users = await _userBusinessLogic.GetAll();
            return users.ToList();
        }
    }
}

Startup.cs:

namespace Identity
{
    public class Startup
    {
        private readonly IConfiguration _configuration;
        private readonly ILogger _logger;

        public Startup(IConfiguration configuration, ILogger<Startup> logger)
            : base()
        {
            _configuration = configuration;
            _logger = logger;
        }

        // 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)
        {
            services.AddMvcCore()
                .AddJsonFormatters()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddRazorViewEngine(); 

            services.Configure<ApiBehaviorOptions>(options =>
            {
                options.InvalidModelStateResponseFactory = context => new ValidationProblemDetailsResult();
            });

            services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "http://localhost:9000";
                    options.RequireHttpsMetadata = false;

                    options.ApiName = "identityserver4";
                });

            services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddPersistedGrantStore<PersistedGrantStoreBusinessLogic>()
            .AddResourceStore<ResourceBusinessLogic>()
            .AddClientStore<ClientBusinessLogic>()
            .AddProfileService<ProfileBusinessLogic>()
            .AddCorsPolicyService<CorsPolicyBusinessLogic>();

            services.AddCors(options =>
            {
                options.AddPolicy("default",
                    builder => builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader().Build());
            });

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseAuthentication();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseCors("default");
            app.UseIdentityServer();
            app.UseStaticFiles();
            app.ConfigureExceptionHandler(_logger);
            app.UseMvcWithDefaultRoute();
        }
    }
}
WeB
  • 21
  • 6

3 Answers3

1

Found my problem! in my startup i used services.AddMvcCore() when i should have used services.AddMvc() OR just add the services.AddAuthorization which is not added using services.AddMvcCore().

I came upon this solution after doing some research for something else. In my research i came upon this page: https://offering.solutions/blog/articles/2017/02/07/difference-between-addmvc-addmvcore/

It explains the differences between AddMvc() and AddMvcCore(). So after adding services.AddAuthorization() my problem was solved and the api within my identityserver where protected.

Thank you to all who tried to help me!

WeB
  • 21
  • 6
0

I just wrote some code for the exact same purpose, and I struggled with the same issues as you do.

According to the Identity Server Doc, do not forget to specify the authentication scheme in [Authorize] attribute.

Startup.cs:

services.AddAuthentication()
        .AddIdentityServerAuthentication("Bearer", options =>
                {
                    options.Authority = "http://localhost:9000";
                    options.RequireHttpsMetadata = false;
                    options.ApiName = "identityserver4";
                });

Note that "Bearer" is given to AddIdentityServerAuthentication and not to AddAuthentication.

Controller.cs:

[Authorize(AuthenticationSchemes = "Bearer")]
public IActionResult YourControllerAction()
{
}

Hope it will works for you!

Nicolas G.
  • 1
  • 1
  • 2
  • i added the bearer scheme to [Authorize] that i already had and put the bearer scheme within AddIdentityServerAuthentication(). When i get back to work tomorrow i want to see if the following api project helps: its a IdentityserverHost combined with Api https://github.com/brockallen/IdentityServerAndApi – WeB Jan 29 '19 at 19:02
0

this answer may comes late but comes late better than never , using IdentityServer to secure other APIs and do not secure the main token or access provider may seems silly somehow ,so in this case if you want to secure the Api That implement IdentityServer it self you can add the predefined IdentityServer scope IdentityServerApi in the allowed scopes and also for the client scopes , and then you have to configure the services to use the local authentication (provided by identityserver) by adding services.AddLocalApiAuthentication(); and the final part is to add the authorize attribute to the controller or the action method as you wish as follow [Authorize(Policy = LocalApi.PolicyName)] and in the end you can add claims policy authorization side by side with the local authentication

Dark Storm
  • 187
  • 4
  • 10