Search code examples
asp.net-coreasp.net-identityidentityserver4

ASP.NET Core returns InternalServerError while using Identity server


I trying to add identity server for my web API as its identity server4 documentation. when I was trying to call API from my console application it's every time returns InternalServerError.

Here is My Identity server Config.cs

public static class Config
{
    // register api
    public static IEnumerable<ApiScope> ApiScopes => new List<ApiScope>
   {
        // in here add your api name 
      new ApiScope("api1", "My API")
   };

    // register client which is going to access api. eg: front-end application, mobile apps etc. can add multiple client.
    public static IEnumerable<Client> Clients => new List<Client>
    {
      new Client
      {
          // which is going to access
          ClientId = "client",
          // no interactive user, use the clientid/secret for authentication
         AllowedGrantTypes = GrantTypes.ClientCredentials,
         // secret for authentication
        ClientSecrets =
        {
            new Secret("secret".Sha256())
        },

        // scopes that client has access to
        AllowedScopes = { "api1" }

      }
    };

}

and here the identity server startup file configuration service and configure functions

  public void ConfigureServices(IServiceCollection services)
        {
            // uncomment, if you want to add an MVC-based UI
            services.AddControllersWithViews();

            var builder = services.AddIdentityServer()
                .AddInMemoryApiScopes(Config.ApiScopes)
                .AddInMemoryClients(Config.Clients);

            builder.AddDeveloperSigningCredential();

          
            builder.AddDeveloperSigningCredential();
        }

        public void Configure(IApplicationBuilder app)
        {
            if (Environment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            // uncomment if you want to add MVC
            app.UseStaticFiles();
            app.UseRouting();

            app.UseIdentityServer();

            // uncomment, if you want to add MVC
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
            });
        }

and here is my API startup file's congurationService and configure functions

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddAuthentication("Bearer")
                .AddJwtBearer("Bearer", options =>
                {
                    options.Authority = "https://localhost:14030/";
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateAudience = false
                    };
                }
                );
           
        }

        
   

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

here is my API controller

[Route("identity")]
  
    public class IdentityController : ControllerBase
    {
        [HttpGet]
        [Authorize]
        public IActionResult Get() => Ok(new JsonResult(from c in User.Claims select new { c.Type, c.Value }));
    }

and here is my console application client request a api

 static async System.Threading.Tasks.Task Main(string[] args)
        {

            // discover endpoints from metadata
            var client = new HttpClient();

            var disco = await client.GetDiscoveryDocumentAsync("http://localhost:14030");
            if (disco.IsError)
            {
                Console.WriteLine(disco.Error);
                return;
            }

            // request token
            var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = "client",
                ClientSecret = "secret",
                Scope = "api1"
            });

            if (tokenResponse.IsError)
            {
                Console.WriteLine(tokenResponse.Error);
                return;
            }

            Console.WriteLine(tokenResponse.Json);
            Console.WriteLine("\n\n");

            // call api
            var apiClient = new HttpClient();
            apiClient.SetBearerToken(tokenResponse.AccessToken);

            var response = await apiClient.GetAsync("https://localhost:5001/identity");
            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine(response.StatusCode);
            }
            else
            {
                var content = await response.Content.ReadAsStringAsync();
                Console.WriteLine(content);
            }
        }

what are the mistakes should I have to fix. Im really appreciates your valuable answers and efforts.

Thank


Solution

  • I got the code working, I would do the following:

    use HTTPS here, not HTTP:

    var disco = await
       client.GetDiscoveryDocumentAsync("http://localhost:14030");
    

    Remove the duplicate lines of in IdentityServer startup class:

    builder.AddDeveloperSigningCredential();
    

    I would add in your API startup.cs

    services.AddAuthorization();
    

    Remove the trailing / at the end of the URL here:

    options.Authority = "https://localhost:14030/";
    

    To get more debugging output from your API, you can add the following two trace lines to your appsettings.Development.json file:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information",
          "Microsoft.AspNetCore.Authentication": "Trace",
          "Microsoft.AspNetCore.Authorization": "Trace"
        }
      }
    }
    

    If you want to validate the Audience (and using IdentityServer4 v4.00) you can add:

    services.AddControllers();

    services.AddAuthentication("Bearer")
        .AddJwtBearer("Bearer", options =>
            {
                options.Authority = "https://localhost:14030";
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidAudiences = new[] {"https://localhost:14030/resources"},
                    ValidateAudience = true
                };
            }
        );