我想获取访问令牌的声明,但是在尝试获取UserInfo的情况下,响应返回错误“ Forbidden”。 为什么会这样,我该如何解决? userinfo端点为https://localhost:44307/connect/userinfo 一旦工作,下面的代码将被重构。字段response1包含错误消息;
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(Settings.AuthorityUrl);
if (disco.IsError)
{
throw new Exception(disco.Error);
}
var tokenRequest = new ClientCredentialsTokenRequest
{
Address = Settings.AuthorityUrl + "connect/token",
ClientId = Settings.ClientId,
ClientSecret = "secret",
Scope = "SIR"
};
var response = await client.RequestClientCredentialsTokenAsync(tokenRequest);
var token = response.AccessToken;
var response1 = await client.GetUserInfoAsync(new UserInfoRequest
{
Address = disco.UserInfoEndpoint,
Token = token
});
if (response1.IsError) throw new Exception(response1.Error);
var claims = response1.Claims;
在我的IDP中,我的配置文件是
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using System.Collections.Generic;
using System.Security.Claims;
namespace QuickstartIdentityServer
{
public class Config
{
// scopes define the resources in your system
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Address()
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("SIR", "Service Inspection Report")
};
}
// clients want to access resources (aka scopes)
public static IEnumerable<Client> GetClients()
{
var baseUri = "http://localhost:53200/";
// client credentials client
return new List<Client>
{
// OpenID Connect hybrid flow and client credentials client (MVC)
new Client
{
ClientId = "SIR",
ClientName = "SIR",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { $"{baseUri}signin-oidc" },
PostLogoutRedirectUris = { $"{baseUri}signout-callback-oidc" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Address,
"SIR"
},
AllowOfflineAccess = true,
AlwaysIncludeUserClaimsInIdToken = true
}
};
}
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "1",
Username = "alice",
Password = "password",
Claims = new List<Claim>
{
new Claim("name", "Alice"),
new Claim("website", "https://alice.com"),
new Claim("address", "1a The Street")
}
},
new TestUser
{
SubjectId = "2",
Username = "bob",
Password = "password",
Claims = new List<Claim>
{
new Claim("name", "Bob"),
new Claim("website", "https://bob.com"),
new Claim("address", "2a The Street")
}
}
};
}
}
}
启动是;
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
.AddSigningCredential(new X509Certificate2(Settings.CertPath, Settings.Password))
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
// register your IdentityServer with Google at https://console.developers.google.com
// enable the Google+ API
// set the redirect URI to http://localhost:port/signin-google
options.ClientId = "copy client ID from Google here";
options.ClientSecret = "copy client secret from Google here";
})
.AddOpenIdConnect("oidc", "OpenID Connect", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://demo.identityserver.io/";
options.ClientId = "implicit";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMiddleware<StackifyMiddleware.RequestTracerMiddleware>();
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
答案 0 :(得分:1)
您使用的是OAuth 2.0定义的 client credential grant 。
在您的代码中,openid
代表使用此授权类型的令牌请求。请注意,当您通过此授权获得访问令牌时,不会涉及最终用户。它不是OpenID Connect(未经最终用户身份验证),仅可用于客户端凭据,仅使您具有访问令牌。
现在,当您将此访问令牌用于UserInfo request时,身份服务器将检测到它没有任何相关的最终用户。因此,它返回禁止的响应以告知您您无权访问端点。
查看文档中的确切信息,
UserInfo端点可用于检索有关用户的身份信息(请参阅spec)。
呼叫者需要发送一个代表用户的有效访问令牌。
如果需要用户信息,请使用授权码授予或作用域值为 let authResponse = res;
console.log('userData==> ', req.body.userData)
if (!req.params.ID) {
console.log(':: res 1')
res.status(404).json({
status: 'failed',
data: 'user id not defined'
});
return null;
}
的混合流来启用OpenID Connect请求。您可以阅读更多here以了解不同的赠款类型。