Namindu Sanchila
Namindu Sanchila

Reputation: 414

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

Upvotes: 1

Views: 537

Answers (1)

Tore Nestenius
Tore Nestenius

Reputation: 19921

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
            };
        }
    );

Upvotes: 1

Related Questions