C# 不支持标识服务器响应类型:代码+;身份证
我有一个identity server 4项目作为服务器,asp.net mvc 5作为客户端。除了一个偶然的问题外,一切正常:响应类型不受支持:代码+id\U令牌 在我从生产日志进行调查的过程中,我发现授权url偶尔被编码两次,然后我无法找到根本原因并复制。我猜这是Microsoft.Owin.Security.OpenIdConnect的内部行为 当未登录的用户访问受保护的资源时,将自动生成授权的url 从我的mvc客户端,首先将“代码id_令牌”编码为“代码+id_令牌”,然后将“代码+id_令牌”编码为“代码%2Bid_令牌” 从我的身份服务器端,“代码%2Bid_令牌”被解码为“代码+id_令牌”,从而发生验证错误 以下是我的日志:C# 不支持标识服务器响应类型:代码+;身份证,c#,.net,owin,identityserver4,openid-connect,C#,.net,Owin,Identityserver4,Openid Connect,我有一个identity server 4项目作为服务器,asp.net mvc 5作为客户端。除了一个偶然的问题外,一切正常:响应类型不受支持:代码+id\U令牌 在我从生产日志进行调查的过程中,我发现授权url偶尔被编码两次,然后我无法找到根本原因并复制。我猜这是Microsoft.Owin.Security.OpenIdConnect的内部行为 当未登录的用户访问受保护的资源时,将自动生成授权的url 从我的mvc客户端,首先将“代码id_令牌”编码为“代码+id_令牌”,然后将“代码+i
INFO 11:54:35 Request starting HTTP/1.1 GET http://login.example.com/connect/authorize?client_id=gjcf_mvc&nonce=636709820590066816.ZWNlNzJmOGQtMGFhNC00NzVkLTllNzktNmE5NTIzN2EzNDE3NThhMmI2OGYtODI5Mi00OTE2LTgzN2MtNGFkZWUzODQ4Nzlk&redirect_uri=https%3A%2F%2Fwww.example.com%2Fsignin-oidc&response_mode=form_post&response_type=code%2Bid_token&scope=openid%2Bprofile%2Bapi1%2BGjcfApi%2Boffline_access&state=OpenIdConnect.AuthenticationProperties
INFO 11:54:35 Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeEndpoint for /connect/authorize
ERROR 11:54:35 Response type not supported: code+id_token
{
"ClientId": "gjcf_mvc",
"ClientName": "gjcf_mvc_name",
"RedirectUri": "https://www.example.com/signin-oidc",
"AllowedRedirectUris": [
"https://www.example.com/signin-oidc"
],
"SubjectId": "anonymous",
"RequestedScopes": "",
"State": "OpenIdConnect.AuthenticationProperties=5USuW-uf3wCad1ap9VCDDCE6bTKr1mUMZob-yI_vBUsAFqx_7oLv-0f3rTApD5_6NjVf3siQsJKg9cH4T7YA6ra2B_6_Yooq_S0rJW2L3I4a13Gg5DpcESjg8gb4MQSysOm_xLjgXa96gpGN0tTwNmnb6dB6S3c3ttIDPt_JWCI0qHclfprE_RlO4RlY3LqsI3YhGznHUXM9UW-x38KB9vUtdfulXYrWRko35cQmezI3QAIXqOCt_d7qLgL5WBeNRRk8I0QrbfrmhTwwtS1fTBi5vUPujBPi9L14mCeKPbNZIm5w4oqZOznjBhw0k5v2",
"Raw": {
"client_id": "gjcf_mvc",
"nonce": "636709820590066816.ZWNlNzJmOGQtMGFhNC00NzVkLTllNzktNmE5NTIzN2EzNDE3NThhMmI2OGYtODI5Mi00OTE2LTgzN2MtNGFkZWUzODQ4Nzlk",
"redirect_uri": "https://www.example.com/signin-oidc",
"response_mode": "form_post",
"response_type": "code+id_token",
"scope": "openid+profile+api1+GjcfApi+offline_access",
"state": "OpenIdConnect.AuthenticationProperties"
}
}
以下代码位于asp.net mvc启动中:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = context =>
{
context.Properties.AllowRefresh = true;
context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(40);
}
}
});
GjcfOpenIdConnectConfiguration conf = GjcfOpenIdConnectConfiguration.Instance;
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = conf.ClientId,
ClientSecret = conf.ClientSecret,
Authority = conf.Authority,
RedirectUri = conf.RedirectUri,
PostLogoutRedirectUri = conf.PostLogoutRedirectUri,
ResponseType = conf.ResponseType,
Scope = conf.Scope,
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
// use the code to get the access and refresh token
var tokenClient = new TokenClient(
conf.TokenAddress,
conf.ClientId,
conf.ClientSecret);
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
n.Code, n.RedirectUri);
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
// use the access token to retrieve claims from userinfo
var userInfoClient = new UserInfoClient(
new Uri(conf.UserInfoAddress),
tokenResponse.AccessToken);
var userInfoResponse = await userInfoClient.GetAsync();
// create new identity
var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);
id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
id.AddClaim(new Claim("expires_at",
DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));
id.AddClaim(new Claim(ClaimTypes.NameIdentifier,
n.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value));
id.AddClaim(new Claim(
"http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider",
n.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value));
n.AuthenticationTicket = new AuthenticationTicket(
new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType,
"name", "role"),
n.AuthenticationTicket.Properties);
},
AuthenticationFailed = (context) =>
{
if (context.Exception.Message.StartsWith("OICE_20004") || context.Exception.Message.Contains("IDX10311"))
{
context.SkipToNextMiddleware();
return Task.FromResult(0);
}
return Task.FromResult(0);
},
RedirectToIdentityProvider = n =>
{
// if signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
}
return Task.FromResult(0);
}
}
});
当用户访问标记为Authorize属性的操作时,将生成Authorize url
[Authorize]
public ActionResult IdentityServerJump(string returnUrl)
{
if (!string.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
虽然您还没有提供代码,但以下部分存在问题 从我的mvc客户端,“代码id_令牌”首先编码为“代码+id_令牌”,然后将“代码+id_令牌”编码为“代码%2Bid_令牌” 不知道为什么要进行双重编码。从IS4(identity server)端,它将执行URL解码,而不知道查询段是双重编码的 对此的更正是使用单一编码。根据OpenID连接规范,坚持使用
%20对空格进行编码,不要像现在这样进行双重编码。!!。另外,我也欢迎您阅读关于+vs%20的文章,请您提供一些相关代码。欢迎访问SO,您在提出第一个问题方面做得很好。正如@Dimitar提到的,一个代码将有助于识别您正在经历的双重编码。@Michael Zhang您找到解决方案了吗?我也有同样的问题。我认为这是基于用户使用的浏览器。但是我不知道如何修复它。谢谢,我在编码方面什么都不做,url是由oidc中间件生成和编码的,我每天只看到一两个错误log@MichaelZhang示例代码将非常有用:)