调用RequestClientCredentialsTokenAsync

时间:2019-01-28 17:19:53

标签: asp.net-core asp.net-core-mvc identityserver4 asp.net-core-webapi

我已经建立了以下三个资产的解决方案:

  • ASP.NET MVC核心应用程序
  • ASP.NET Core Web API
  • IdentityServer4主机

当前,身份验证有效:如果我尝试访问MVC应用程序中的受保护资源,它将重定向到IdentityServer4,那么我可以使用我的Facebook帐户登录,配置用户并生成主题ID,然后我m重定向回MVC应用。这可以正常工作。

我还可以从MVC站点内调用受保护的Web API函数。但是,在我从Web API中收到的声明中,我没有收到主题ID。

如果我进一步调查,那么我可以在MVC应用程序中看到,我从RequestClientCredentialsTokenAsync调用中获取了访问令牌,但它仅包含:

{
  "nbf": 1548693531,
  "exp": 1548697131,
  "iss": "http://localhost:5000",
  "aud": [
    "http://localhost:5000/resources",
    "mgpApi"
  ],
  "client_id": "mgpPortal",
  "scope": [
    "mgpApi"
  ]
}

我想要的是,我也收到此访问令牌中的主题ID ,这样我也可以在调用的Web API函数中使用它。

我的IdentityServer4主机配置有:

public void ConfigureServices(IServiceCollection services)
{
    var builder = services.AddIdentityServer()
            .AddInMemoryIdentityResources(Resources.GetIdentityResources())
            .AddInMemoryApiResources(Resources.GetApiResources())                
            .AddProfileService<ProfileService>()
            .AddInMemoryClients(Clients.Get());
}

...并且我正在使用以下方式注册客户端:

new Client
{
    EnableLocalLogin = false,

    ClientId = "mgpPortal",
    ClientName = "MGP Portal Site",
    AllowedGrantTypes = GrantTypes.ImplicitAndClientCredentials,

    // where to redirect to after login
    RedirectUris = { "http://localhost:5002/signin-oidc" },

    // where to redirect to after logout
    PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

    // secret for authentication
    ClientSecrets =
    {
        new Secret("secret".Sha256())
    },

    AllowedScopes = new List<string>
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        "mgpApi"
    },

    AllowOfflineAccess = true,
    AlwaysIncludeUserClaimsInIdToken = true,
    AlwaysSendClientClaims = true,
}

...而且我也尝试通过ProfileService这样的声明来添加声明,例如:

public class ProfileService : IProfileService
{
    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        context.IssuedClaims.AddRange(context.Subject.Claims);
        context.IssuedClaims.Add(new Claim("sub", "test"));

        return Task.FromResult(0);
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        return Task.FromResult(0);
    }
}

但这没什么区别。

我的MVC客户端配置有:

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

    services.AddAuthentication(options =>
    {
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";                 
    })
    .AddCookie("Cookies")
    .AddOpenIdConnect("oidc", options =>
    {                
        options.Authority = "http://localhost:5000";
        options.RequireHttpsMetadata = false;                
        options.ClientId = "mgpPortal";
        options.SaveTokens = true;                
    });           
}

那么我应该添加些什么以便在访问令牌中接收主题ID?

如果需要更多信息,请告诉我。任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:2)

您使用了错误的流程,请使用hybrid流程。在client credentials中,没有用户主题的概念,因此您遇到的问题。

答案 1 :(得分:0)

我处于类似情况。经过大量的证明,我发现使用MVC应用程序用户的相同令牌访问另一个Web Api应用程序非常容易。说明here

public async Task<IActionResult> CallApi()
{
    var accessToken = await HttpContext.GetTokenAsync("access_token");

    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    ...
}

使用IdentityModel的另一个版本:

public async Task<IActionResult> CallApi()
{
  var accessToken = await HttpContext.GetTokenAsync("access_token");
  var apiClient = new HttpClient();
  client.SetBearerToken(accessToken); 
  ....
  await client.PutAsync(url, json);   

希望它可以帮助...

相关问题