Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default settings for AddApiAuthorization (Scaffolded Angular + IdentityServer4)

I'm using this scaffolded example for Angular + IdentityServer4.

dotnet new angular -o <output_directory_name> -au Individual

What are the default credentials, grant types, client id, client secret for AddApiAuthorization, so I could test it with Postman? Because all I can find is that we can add additional API resources, Clients, etc. I'm aware of the default profiles.

Link to their implementation: https://github.com/dotnet/aspnetcore/blob/9a1810c1dbe432fc7bc7e8bc68fa22ab787c0452/src/Identity/ApiAuthorization.IdentityServer/src/IdentityServerBuilderConfigurationExtensions.cs

Example of adding more clients and API resources:

AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
    options.Clients.AddSPA(
        "My SPA", spa =>
        spa.WithRedirectUri("http://www.example.com/authentication/login-callback")
           .WithLogoutRedirectUri(
               "http://www.example.com/authentication/logout-callback"));

    options.ApiResources.AddApiResource("MyExternalApi", resource =>
        resource.WithScopes("a", "b", "c"));
});

Microsoft's scaffolded way:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            configuration.GetConnectionString("DefaultConnection"),
            b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));

    services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = false)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddIdentityServer()
        .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

    services.AddAuthentication()
        .AddIdentityServerJwt();
    services.AddControllersWithViews();
    services.AddRazorPages();
    // In production, the Angular files will be served from this directory
    services.AddSpaStaticFiles(configuration =>
    {
        configuration.RootPath = "ClientApp/dist";
    });
}

My previous configuration with the original IdentityServer4 package. It uses code with PKCE:

public class Startup
{
    public IWebHostEnvironment Environment { get; }
    public IConfiguration Configuration { get; }

    public Startup(IWebHostEnvironment environment, IConfiguration configuration)
    {
        Environment = environment;
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration["ConnectionStrings:DayumConnection"],
                optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));

        services.AddIdentity<ApplicationUser, IdentityRole>(options =>
        {
            options.Password.RequireDigit = false;
            options.Password.RequireLowercase = false;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = false;
            options.Password.RequiredLength = 6;
        })
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddIdentityServer(options =>
        {
            options.Events.RaiseErrorEvents = true;
            options.Events.RaiseInformationEvents = true;
            options.Events.RaiseFailureEvents = true;
            options.Events.RaiseSuccessEvents = true;
        })
            .AddSigningCredential(new X509Certificate2(Configuration["Certificates:Default:Path"], Configuration["Certificates:Default:Password"]))
            .AddConfigurationStore(options =>
            {
                options.ConfigureDbContext = builder => builder.UseSqlServer(Configuration["ConnectionStrings:DayumConnection"],
                    optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName));
            })
            .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = builder => builder.UseSqlServer(Configuration["ConnectionStrings:DayumConnection"],
                    optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName));

                options.EnableTokenCleanup = true;
            })
            .AddProfileService<ProfileService>()
            .AddAspNetIdentity<ApplicationUser>();
    }

    public void Configure(IApplicationBuilder app)
    {
        using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
        {
            serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();

            var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
            context.Database.Migrate();
            if (!context.Clients.Any())
            {
                foreach (var client in Config.GetClients())
                {
                    context.Clients.Add(client.ToEntity());
                }
                context.SaveChanges();
            }

            if (!context.IdentityResources.Any())
            {
                foreach (var resource in Config.GetResources())
                {
                    context.IdentityResources.Add(resource.ToEntity());
                }
                context.SaveChanges();
            }

            if (!context.ApiResources.Any())
            {
                foreach (var resource in Config.GetApis())
                {
                    context.ApiResources.Add(resource.ToEntity());
                }
                context.SaveChanges();
            }
        }

        if (Environment.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseIdentityServer();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "MyArea",
                pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

public static class Config
{
    public static IEnumerable<IdentityResource> GetResources() =>
        new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile()
        };

    public static IEnumerable<ApiResource> GetApis() =>
        new List<ApiResource>
        {
            new ApiResource("api1", "My API")
        };

    public static IEnumerable<Client> GetClients() =>
        new List<Client>
        {
            new Client
            {
                ClientId = "trusted",
                ClientName = "Dayum Client",
                //ClientSecrets = { new Secret("123456".Sha256()) },

                RequireConsent = false,
                RequireClientSecret = false,
                AllowedGrantTypes = GrantTypes.Code,
                RequirePkce = true,

                AllowAccessTokensViaBrowser = true,
                RedirectUris = { "http://localhost:58508" },
                PostLogoutRedirectUris = { "http://localhost:58508" },

                AllowedScopes =
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    IdentityServerConstants.StandardScopes.OfflineAccess,
                    "api1"
                },

                AccessTokenType = AccessTokenType.Jwt,  
                AccessTokenLifetime = 900,

                AllowOfflineAccess = true,
                RefreshTokenExpiration = TokenExpiration.Absolute,
                RefreshTokenUsage = TokenUsage.OneTimeOnly,
                AbsoluteRefreshTokenLifetime = 1800
            }
        };
}

Edit:

@Lasanga Guruge explained it very well on how to see the default values.

enter image description here

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:61846/connect/authorize?response_type=code&state=&client_id=CleanArchitecture.WebUI&scope=openid%20profile&redirect_uri=http%3A%2F%2Flocalhost%3A61846%2Fauthentication%2Flogin-callback&code_challenge=HH2xNyUDRhvVlkvL024GD4lJKI0NQFo7QqANot3BCD4&code_challenge_method=S256  
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Request path /connect/authorize matched to endpoint type Authorize
dbug: IdentityServer4.Hosting.EndpointRouter[0]
      Endpoint enabled: Authorize, successfully created handler: IdentityServer4.Endpoints.AuthorizeEndpoint
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeEndpoint for /connect/authorize
dbug: IdentityServer4.Endpoints.AuthorizeEndpoint[0]
      Start authorize request
dbug: IdentityServer4.Endpoints.AuthorizeEndpoint[0]
      No user present in authorize request
dbug: IdentityServer4.Validation.AuthorizeRequestValidator[0]
      Start authorize request protocol validation
dbug: IdentityServer4.Stores.ValidatingClientStore[0]
      client configuration validation for client CleanArchitecture.WebUI succeeded.
dbug: IdentityServer4.Validation.AuthorizeRequestValidator[0]
      Checking for PKCE parameters
dbug: IdentityServer4.Validation.AuthorizeRequestValidator[0]
      Calling into custom validator: IdentityServer4.Validation.DefaultCustomAuthorizeRequestValidator
dbug: IdentityServer4.Endpoints.AuthorizeEndpoint[0]
      ValidatedAuthorizeRequest
      {
        "ClientId": "CleanArchitecture.WebUI",
        "ClientName": "CleanArchitecture.WebUI",
        "RedirectUri": "http://localhost:61846/authentication/login-callback",
        "AllowedRedirectUris": [
          "/authentication/login-callback"
        ],
        "SubjectId": "anonymous",
        "ResponseType": "code",
        "ResponseMode": "query",
        "GrantType": "authorization_code",
        "RequestedScopes": "openid profile",
        "Raw": {
          "response_type": "code",
          "state": "",
          "client_id": "CleanArchitecture.WebUI",
          "scope": "openid profile",
          "redirect_uri": "http://localhost:61846/authentication/login-callback",
          "code_challenge": "HH2xNyUDRhvVlkvL024GD4lJKI0NQFo7QqANot3BCD4",
          "code_challenge_method": "S256"
        }
      }
info: IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator[0]
      Showing login: User is not authenticated
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 46.115ms 302 
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:61846/Identity/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fresponse_type%3Dcode%26state%26client_id%3DCleanArchitecture.WebUI%26scope%3Dopenid%2520profile%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A61846%252Fauthentication%252Flogin-callback%26code_challenge%3DHH2xNyUDRhvVlkvL024GD4lJKI0NQFo7QqANot3BCD4%26code_challenge_method%3DS256  
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/Account/Login'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
      Route matched with {page = "/Account/Login", area = "Identity", action = "", controller = ""}. Executing page /Account/Login
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
      Executing handler method Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Internal.LoginModel.OnGetAsync - ModelState is Valid
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[11]
      AuthenticationScheme: Identity.External signed out.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
      Executed handler method OnGetAsync, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
      Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
      Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
      Executed page /Account/Login in 17.3083ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/Account/Login'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 31.3091ms 200 text/html; charset=utf-8

Does that mean that everything is normal?

like image 556
nop Avatar asked May 05 '20 12:05

nop


People also ask

What is IdentityServerSPA?

IdentityServerSPA : Represents a SPA hosted alongside IdentityServer as a single unit. The redirect_uri defaults to /authentication/login-callback . The post_logout_redirect_uri defaults to /authentication/logout-callback .

What is AddApiAuthorization?

AddApiAuthorization<TUser,TContext>(IIdentityServerBuilder) Configures defaults for Identity Server for ASP.NET Core scenarios. AddApiAuthorization<TUser,TContext>(IIdentityServerBuilder, Action<ApiAuthorizationOptions>) Configures defaults on Identity Server for ASP.NET Core scenarios.

What is the use of identityserver4?

IdentityServer is an authentication server that implements OpenID Connect (OIDC) and OAuth 2.0 standards for ASP.NET Core. It's designed to provide a common way to authenticate requests to all of your applications, whether they're web, native, mobile, or API endpoints.


1 Answers

The default values for a scaffold application would be

  1. Grantype of Authorization Code
  2. ClientId will be corresponding to the application name. That can be changed in appsettings.json (Clients) and api-authorization.constants.ts (ApplicationName)
  3. By default a client secret would not be applied to the client
  4. Also pkce is enabled.
  5. No default credentials
  6. Additional scope named {ProjectName}API will be added

You can call https://localhost:{port}/_configuration/{clientId} to get the information. To check more details about the default client you can debug the following code

 services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddApiAuthorization<ApplicationUser, ApplicationDbContext>((config) =>
                {  
                    config.Clients[0].AccessTokenLifetime = 3600   
                });

If you want to edit the default client.

UPDATE

Change clientId from appsetting.json

"IdentityServer": {
    "Clients": {
      "{ClientId}": { //To edit the clientId change here
        "Profile": "IdentityServerSPA"
      }
    }
  }

Note: As I have mentioned above if you change the ClientId make sure you chage the ApplicationName in api-authorization.constants.ts

like image 107
Lasanga Guruge Avatar answered Oct 18 '22 23:10

Lasanga Guruge