IdentityServer 4 WsFederation - 如何获取调用的访问令牌 API

IdentityServer 4 WsFederation - How to get access token for calling API

我正在使用带有 Ws-Federation 插件的 Identity Server 4。 Identity Server 配置为连接到 Azure AD 进行身份验证。以下是 Identity Server 项目的相关代码:

public void ConfigureServices(IServiceCollection services)
        {
            var rsaCertificate = new X509Certificate2("rsaCert.pfx", "1234");

            services.AddRazorPages();
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity<User, IdentityRole>(options =>
            {
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(2);
                options.Lockout.MaxFailedAccessAttempts = 3;
            })
            .AddDefaultUI()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddUserStore<CustomUserStore>()
            .AddUserManager<CustomUserManager>()
            .AddDefaultTokenProviders();

            services.AddTransient<IUserStore<User>, CustomUserStore>();
            services.AddTransient<IEmailSender, EmailSender>();

            var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseSuccessEvents = true;

                // see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
                options.EmitStaticAudienceClaim = true;
            })
            .AddSigningCredential(rsaCertificate)
            .AddInMemoryIdentityResources(IdentityConfig.IdentityResources)
            .AddInMemoryApiScopes(IdentityConfig.ApiScopes)
            .AddInMemoryClients(IdentityConfig.Clients)
            .AddAspNetIdentity<User>()
            .AddWsFederationPlugin(options =>
            {
                options.Licensee = "Licensee";
                options.LicenseKey = "LicenseKey";
            })
            .AddInMemoryRelyingParties(new List<RelyingParty>());

            services.AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
            })
            .AddWsFederation(options =>
            {
                options.Wtrealm = "Azure AD App Id";
                options.MetadataAddress = "WSFed metadata URL from Azure AD App";
                options.Events.OnSecurityTokenValidated = SecurityTokenValidated;
            })
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromMinutes(IdentityConfig.SessionTimeoutInMinutes);
                options.SlidingExpiration = true;
                options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
            });
        }

我有一个 API 受 JWT 承载身份验证保护,它连接到同一身份服务器。 API中的相关代码(注意https://localhost:5001是Identity Server所在的地址运行):

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

            services.AddAuthentication("Bearer")
            .AddJwtBearer("Bearer", options =>
            {
                options.Authority = "https://localhost:5001";

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = false
                };
            });
        }

我也有一个连接到同一个身份服务器的 MVC 客户端。我能够从 MVC 客户端成功验证用户。现在,我想做的是从 MVC 客户端中调用 API 项目中受保护的 API 端点。我还没有找到任何方法来获取调用受保护 API 所需的 access token。来自MVC客户端的相关代码:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            services.AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
            })
            .AddCookie(options =>
            {
                options.Cookie.Name = "aspnetcorewsfed";
                options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
                options.SlidingExpiration = true;
                options.ExpireTimeSpan = TimeSpan.FromMinutes(Configuration.GetValue<int?>("SessionTimeoutInMinutes") ?? 15);
            })
            .AddWsFederation(options =>
            {
                options.MetadataAddress = "https://localhost:5001/wsfed"; // Address of the Identity Server
                options.RequireHttpsMetadata = false;

                options.Wtrealm = "mvc"; // ClientId registered in Identity Server

                options.CallbackPath = "/";
                options.SkipUnrecognizedRequests = true;
            });
        }

Identity Server 网站上的文档描述了如何访问受保护的 API,如 here 所示。但这是使用 OpenIdConnect。由于我使用的是 WsFederation,所以我不知道如何获取访问令牌或刷新令牌。 WsFed 无法刷新令牌吗?

任何人都可以指出正确的方向来解决这个问题吗?

在 MVC 客户端中使用 OpenIdConnect 而不是 WsFed。将 MVC 客户端 Startup.cs 中的代码更改为以下内容:

services.AddAuthentication(options =>{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
}).AddCookie("Cookies").AddOpenIdConnect("oidc", options =>{
    options.Authority = "https://localhost:5001";
    options.ClientId = "mvc-openid";
    options.ClientSecret = "secret";
    options.ResponseType = "code";
    options.SaveTokens = true;
});

Identity Server中对应的客户端注册应该是:

new Client {
    ClientId = "mvc-openid",
    ClientSecrets = {
      new Secret("secret".Sha256())
    },
    AllowedGrantTypes = GrantTypes.Code,
    RedirectUris = {
      "https://localhost:6001/signin-oidc"
    },
    AllowedScopes = new List < string > {
      IdentityServerConstants.StandardScopes.OpenId,
      IdentityServerConstants.StandardScopes.Profile,
      "api"
    }
}

https://localhost:5001是Identity Server地址,https://localhost:6001是MVC客户端地址。

访问API的访问令牌可以这样获取:

var accessToken = await HttpContext.GetTokenAsync("access_token");