C# IdentityServer4不带UI的Windows身份验证

C# IdentityServer4不带UI的Windows身份验证,c#,asp.net-mvc,asp.net-core,asp.net-web-api,identityserver4,C#,Asp.net Mvc,Asp.net Core,Asp.net Web Api,Identityserver4,我希望能够使用IdentityServer4作为使用Windows身份验证的应用程序的STS。我的大多数应用程序没有UI组件(它们只是ASP.NET核心API)。通过遵循指南并使用“is4inmem”身份服务器模板,我已经能够使用MVC(UI)客户端获得我的IdentityServer4 Windows身份验证。我使用的MVC客户端是示例客户端。我现在正在尝试设置我的api客户端。我的所有应用程序都使用kestrel托管,下面是IIS,以便启用Windows身份验证。下面是我的api客户端的St

我希望能够使用IdentityServer4作为使用Windows身份验证的应用程序的STS。我的大多数应用程序没有UI组件(它们只是ASP.NET核心API)。通过遵循指南并使用“is4inmem”身份服务器模板,我已经能够使用MVC(UI)客户端获得我的IdentityServer4 Windows身份验证。我使用的MVC客户端是示例客户端。我现在正在尝试设置我的api客户端。我的所有应用程序都使用kestrel托管,下面是IIS,以便启用Windows身份验证。下面是我的api客户端的Startup.cs的样子,我相信这就是问题所在

    public class Startup
    {
        public IWebHostEnvironment HostingEnvironment { get; private set; }
        public IConfiguration Configuration { get; }

        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            HostingEnvironment = env;
            Configuration = configuration;
        }   

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddAuthentication("token")
                .AddJwtBearer("token", options => {
                    options.Authority = "https://localhost:44353";
                    options.TokenValidationParameters.ValidateAudience = false;
                    options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
                });

            services.AddAuthorization(options => {
                options.AddPolicy("scope", policy => {
                    policy.AddAuthenticationSchemes("token")
                        .RequireAuthenticatedUser()
                        .RequireClaim("scope", "api1");
                });
            });

            AppServSettings.WebHostEnvironment = HostingEnvironment;

            var appSettingsSection = Configuration.GetSection("appSettings");
            var connectionStringsSection = Configuration.GetSection("appSettings");

            services.Configure<AppSettings>(appSettingsSection)
                    .Configure<ConnectionStrings>(connectionStringsSection);

            services.AddControllersWithViews(options => {
                options.InputFormatters.Add(new ProtobufInputFormatter());
                options.OutputFormatters.Add(new ProtobufOutputFormatter());
            });

            var appSettingsOptions = new AppSettings();
            appSettingsSection.Bind(appSettingsOptions);

            var connectionStringsOptions = new ConnectionStrings();
            connectionStringsSection.Bind(connectionStringsOptions);

            AppServSettings.AppSettings = new AppEnvSettings(Options.Create<AppSettings>(appSettingsOptions), Options.Create<ConnectionStrings>(connectionStringsOptions));

            AppServ.Preload();
        }

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

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(
                endpoints => endpoints.MapControllers()
            );
        }
    }
我试图使用的客户端是使用NTLM授权方案的Postman。此外,我还设置了cookies“.AspNetCore.Antiforgery.WxKm21GkYM0”和“idsrv.external”。我目前也在使用NuGet的IdentityServer4版本3.1.3

下面是我和邮递员一起发送的请求,打开了body标签。如您所见,我设置了授权类型、范围、客户机id和客户机机密


请发布您的客户端代码(尝试使用客户端凭据工作流获取令牌的应用程序。此外,如果您使用的是IdentityServer 4的v4.0x,则还必须定义APiscope。我更新了我的帖子,指定了客户端和IdentityServer的版本。通过设计,Api将返回401 a)因为令牌无效或丢失,B)因为没有可用的UI。当您查看调用Api的示例时,您将看到到IdentityServer登录页面的重定向是由客户端初始化的。因此,当客户端从api接收401时,应该由客户端启动用户登录。
    public static class Config
    {
        public static IEnumerable<IdentityResource> Ids =>
            new IdentityResource[]
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                new IdentityResources.Email(),
                new IdentityResources.Address(),
            };


        public static IEnumerable<ApiResource> Apis =>
            new ApiResource[]
            {
                // new ApiResource("api1", "My API #1")

                new ApiResource("api1", "My API", new[] { JwtClaimTypes.Subject, JwtClaimTypes.Email, JwtClaimTypes.Address, "upn_custom"})
            };


        public static IEnumerable<Client> Clients =>
            new Client[]
            {
                // client credentials flow client
                new Client
                {
                    ClientId = "identity.server",
                    ClientName = "Identity Server Client",

                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    AlwaysIncludeUserClaimsInIdToken = true,
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    AllowedScopes = { "openid", "profile", "email", "address", "api1", "upn_custom" }
                },

                // MVC client using code flow + pkce
                new Client
                {
                    //ClientId = "mvc",
                    ClientId = "mvc.code",
                    ClientName = "MVC Client",

                    // Note
                    AlwaysIncludeUserClaimsInIdToken = true,
                    
                    AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
                    //RequirePkce = true,
                    RequirePkce = false,
                    //ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    //RedirectUris = { "https://localhost:5003/signin-oidc" },
                    RedirectUris = { "https://localhost:5003/signin-oidc" },
                    FrontChannelLogoutUri = "https://localhost:5003/signout-oidc",
                    PostLogoutRedirectUris = { "https://localhost:5003/signout-callback-oidc" },

                    AllowOfflineAccess = true,
                    AllowedScopes = { "openid", "profile", "email", "address", "api1", "upn_custom" }
                },

                // MVC client using code flow + pkce
                new Client
                {
                    //ClientId = "mvc",
                    ClientId = "ptp.appserv",
                    ClientName = "PTP AppServ",

                    // Note
                    AlwaysIncludeUserClaimsInIdToken = true,

                    AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
                    //RequirePkce = true,
                    RequirePkce = false,
                    //ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    //RedirectUris = { "https://localhost:30001/signin-oidc" },
                    RedirectUris = { "https://localhost:30001/signin-oidc" },
                    FrontChannelLogoutUri = "https://localhost:30001/signout-oidc",
                    PostLogoutRedirectUris = { "https://localhost:30001/signout-callback-oidc" },

                    AllowOfflineAccess = true,
                    AllowedScopes = { "openid", "profile", "email", "address", "api1", "upn_custom" }
                },

                // MCW Appserver
                new Client
                {
                    //ClientId = "mvc",
                    ClientId = "mcw.appserver",
                    ClientName = "MCW AppServer",

                    // Note
                    AlwaysIncludeUserClaimsInIdToken = true,

                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    RequirePkce = true,
                    //RequirePkce = false,
                    //ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },
                    ClientSecrets = { new Secret("secret".Sha256()) },

                    //RedirectUris = { "http://localhost:16835/signin-oidc" },
                    //RedirectUris = { "https://localhost:16385/signin-oidc" },
                    //FrontChannelLogoutUri = "https://localhost:16835/signout-oidc",
                    //PostLogoutRedirectUris = { "https://localhost:16835/signout-callback-oidc" },

                    AllowOfflineAccess = true,
                    AllowedScopes = { "openid", "profile", "email", "address", "api1", "upn_custom" }
                },

                // SPA client using code flow + pkce
                new Client
                {
                    ClientId = "spa",
                    ClientName = "SPA Client",
                    ClientUri = "http://identityserver.io",

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

                    RedirectUris =
                    {
                        "http://localhost:5002/index.html",
                        "http://localhost:5002/callback.html",
                        "http://localhost:5002/silent.html",
                        "http://localhost:5002/popup.html",
                    },

                    PostLogoutRedirectUris = { "http://localhost:5002/index.html" },
                    AllowedCorsOrigins = { "http://localhost:5002" },

                    AllowedScopes = { "openid", "profile", "api1" }
                }
            };
    }
    [Route("api/[controller]")]
    [Authorize]
    [ApiController]
    public class IdentityController : ControllerBase
    {
        public IActionResult Get()
        {
            return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
        }
    }