Identity Server 4 和 ASP.NET Web Forms Client - 无效的授权类型
Identity Server 4 and ASP.NET Web Forms Client - invalid grant type
我已经在本地设置了 Identity Server 4 并添加了一个 MVC Net Core 客户端,没有任何问题。
我的 .Net Framework Web Forms 应用程序无法运行。
当我尝试点击关于(安全页面).aspx 页面时,出现以下错误:
“抱歉,出现错误:unauthorized_client
客户端的授权类型无效
我已经尝试了所有不同的授权类型,但都没有成功。
我觉得我在 ID4 中的客户端设置不正确。各种博客文章说我应该使用 Code grant,但其他人说使用 id_token.
我在 ID4 服务器应用程序中按如下方式设置了客户端:
new Client
{
ClientId = "aspx",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
//My web forms aspx client
RedirectUris = { "http://localhost:5969/" },
//My web forms aspx client
PostLogoutRedirectUris = { "http://localhost:5969/" },
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
RequirePkce = false,
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
},
}
Startup.cs 在我的 Web 表单应用程序中(我正在使用来自 https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/WebFormsClient/Startup.cs 的 \WebFormsClient\ 示例)
我对 https://localhost:5001/connect/userinfo 应该是什么感到有点困惑 - 我得到了 401。
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = "Cookies",
ExpireTimeSpan = TimeSpan.FromMinutes(10),
SlidingExpiration = true
});
JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "oidc",
SignInAsAuthenticationType = "Cookies",
Authority = "https://localhost:5001/",
ClientId = "aspx",
RedirectUri = "http://localhost:5969/",
PostLogoutRedirectUri = "http://localhost:5969/",
ResponseType = "id_token token",
Scope = "openid profile email",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var claims_to_exclude = new[]
{
"aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash"
};
var claims_to_keep =
n.AuthenticationTicket.Identity.Claims
.Where(x => false == claims_to_exclude.Contains(x.Type)).ToList();
claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken));
if (n.ProtocolMessage.AccessToken != null)
{
claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));
var userInfoClient = new UserInfoClient(new Uri("https://localhost:5001/connect/userinfo"), n.ProtocolMessage.AccessToken);
var userInfoResponse = await userInfoClient.GetAsync();
var userInfoClaims = userInfoResponse.Claims
.Where(x => x.Item1 != "sub") // filter sub since we're already getting it from id_token
.Select(x => new Claim(x.Item1, x.Item2));
claims_to_keep.AddRange(userInfoClaims);
}
var ci = new ClaimsIdentity(
n.AuthenticationTicket.Identity.AuthenticationType,
"name", "role");
ci.AddClaims(claims_to_keep);
n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket(
ci, n.AuthenticationTicket.Properties
);
},
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var id_token = n.OwinContext.Authentication.User.FindFirst("id_token")?.Value;
n.ProtocolMessage.IdTokenHint = id_token;
}
return Task.FromResult(0);
}
}
});
app.UseStageMarker(PipelineStage.Authenticate);
}
}
"id_token 令牌"是 Implicit flow,因此您需要将其包含在您的 AllowedGrantTypes
中。
关于 UserInfo endpoint,它只是 returns 根据您调用它时使用的访问令牌声明用户。获得 401 响应可能意味着您没有传递有效的访问令牌。如果您需要额外的用户声明并且您只有访问令牌但没有 ID 令牌,它会很有用。
我已经在本地设置了 Identity Server 4 并添加了一个 MVC Net Core 客户端,没有任何问题。
我的 .Net Framework Web Forms 应用程序无法运行。
当我尝试点击关于(安全页面).aspx 页面时,出现以下错误:
“抱歉,出现错误:unauthorized_client
客户端的授权类型无效
我已经尝试了所有不同的授权类型,但都没有成功。
我觉得我在 ID4 中的客户端设置不正确。各种博客文章说我应该使用 Code grant,但其他人说使用 id_token.
我在 ID4 服务器应用程序中按如下方式设置了客户端:
new Client
{
ClientId = "aspx",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
//My web forms aspx client
RedirectUris = { "http://localhost:5969/" },
//My web forms aspx client
PostLogoutRedirectUris = { "http://localhost:5969/" },
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
RequirePkce = false,
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
},
}
Startup.cs 在我的 Web 表单应用程序中(我正在使用来自 https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/WebFormsClient/Startup.cs 的 \WebFormsClient\ 示例)
我对 https://localhost:5001/connect/userinfo 应该是什么感到有点困惑 - 我得到了 401。
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = "Cookies",
ExpireTimeSpan = TimeSpan.FromMinutes(10),
SlidingExpiration = true
});
JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "oidc",
SignInAsAuthenticationType = "Cookies",
Authority = "https://localhost:5001/",
ClientId = "aspx",
RedirectUri = "http://localhost:5969/",
PostLogoutRedirectUri = "http://localhost:5969/",
ResponseType = "id_token token",
Scope = "openid profile email",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var claims_to_exclude = new[]
{
"aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash"
};
var claims_to_keep =
n.AuthenticationTicket.Identity.Claims
.Where(x => false == claims_to_exclude.Contains(x.Type)).ToList();
claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken));
if (n.ProtocolMessage.AccessToken != null)
{
claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));
var userInfoClient = new UserInfoClient(new Uri("https://localhost:5001/connect/userinfo"), n.ProtocolMessage.AccessToken);
var userInfoResponse = await userInfoClient.GetAsync();
var userInfoClaims = userInfoResponse.Claims
.Where(x => x.Item1 != "sub") // filter sub since we're already getting it from id_token
.Select(x => new Claim(x.Item1, x.Item2));
claims_to_keep.AddRange(userInfoClaims);
}
var ci = new ClaimsIdentity(
n.AuthenticationTicket.Identity.AuthenticationType,
"name", "role");
ci.AddClaims(claims_to_keep);
n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket(
ci, n.AuthenticationTicket.Properties
);
},
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var id_token = n.OwinContext.Authentication.User.FindFirst("id_token")?.Value;
n.ProtocolMessage.IdTokenHint = id_token;
}
return Task.FromResult(0);
}
}
});
app.UseStageMarker(PipelineStage.Authenticate);
}
}
"id_token 令牌"是 Implicit flow,因此您需要将其包含在您的 AllowedGrantTypes
中。
关于 UserInfo endpoint,它只是 returns 根据您调用它时使用的访问令牌声明用户。获得 401 响应可能意味着您没有传递有效的访问令牌。如果您需要额外的用户声明并且您只有访问令牌但没有 ID 令牌,它会很有用。