[英]How to check access_denied on client when using IdentityServer4?
I have a login page, and I need when the user clicks Cancel button to redirect him to access denied page on a client application.我有一个登录页面,当用户单击“取消”按钮时我需要将他重定向到客户端应用程序上的拒绝页面。
Inside login action:内部登录操作:
if (button != "login")
{
// the user clicked the "cancel" button
var context = await interaction.GetAuthorizationContextAsync(model.ReturnUrl);
if (context != null)
{
// if the user cancels, send a result back into IdentityServer as if they
// denied the consent (even if this client does not require consent).
// this will send back an access denied OIDC error response to the client.
await interaction.GrantConsentAsync(context, ConsentResponse.Denied);
// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
return Redirect(model.ReturnUrl);
}
}
and on the client-side(MVC) I have configured the following event:在客户端(MVC)我配置了以下事件:
options.Events = new OpenIdConnectEvents
{
OnRemoteFailure = context =>
{
// here it's returned as 200 ok in case I denied
// consent should'nt be 401 access denined??
var statusCode=context.Response.StatusCode;
context.Response.Redirect("/");
context.HandleResponse();
return Task.FromResult(0);
}
};
But my question is: how do I know that the IdentityServer4 has failed because the user clicked the Cancel button(access_denied) or if there is another issue caused that failure?但我的问题是:我怎么知道 IdentityServer4 失败是因为用户单击了“取消”按钮(access_denied),或者是否有其他问题导致了该失败?
The basic form has 2 buttons: login
and cancel
.基本表单有 2 个按钮:
login
和cancel
。 If login
is not pressed;如果没有按下
login
; it's a cancel
.这是一个
cancel
。
Otherwise its a validation error and you can show it.否则它是一个验证错误,您可以显示它。 On
cancel
you should redirect back to a page that makes sense.在
cancel
您应该重定向回有意义的页面。
You can redirect with extra parameters.您可以使用额外的参数重定向。 These can be fetched and used to display the error.
这些可以被获取并用于显示错误。 Keep in mind that a lot of error handling, like invalid username/passord stays at the IdentityServer side.
请记住,很多错误处理,例如无效的用户名/密码,都停留在 IdentityServer 端。
How to check access_denied on client when using IdentityServer4?
使用 IdentityServer4 时如何在客户端检查 access_denied?
After some inspection, the Event's context.Failure.Data
is a type of ListDictionaryInternal
, which contains the entries you're probably looking for:经过一些检查,事件的
context.Failure.Data
是一种ListDictionaryInternal
,其中包含您可能正在寻找的条目:
error
error_description
error_uri
. error_uri
。 So by using context.Failure.Data["error"]
you can get the "access_denied" value you're looking for.因此,通过使用
context.Failure.Data["error"]
您可以获得您正在寻找的“access_denied”值。
Using Identity Server 4's demo code as an example, if we go to the Login Post Account Controller action, the section that would interest you is the one that handles the cancel button press:以 Identity Server 4 的演示代码为例,如果我们转到 Login Post Account Controller 操作,您会感兴趣的部分是处理取消按钮按下的部分:
// check if we are in the context of an authorization request
var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);
// the user clicked the "cancel" button
if (button != "login")
{
if (context != null)
{
// RATHER THAN USING THE ORIGINAL STRATEGY:
//await _interaction.GrantConsentAsync(context, ConsentResponse.Denied);
// ...MANUALLY BUILD THE RETURN URL YOURSELF
// THEN REDIRECT TO THAT:
model.ReturnUrl = BuildCancelReturnUrl(context);
if (await _clientStore.IsPkceClientAsync(context.ClientId))
{
return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
}
return Redirect(model.ReturnUrl);
}
else
{
// since we don't have a valid context, then we just go back to the home page
return Redirect("~/");
}
}
As you can see, instead of using the call to GrantConsentAsync
to respond with the access_denied
code (which doesn't include any error_description
or error_uri
values), you could simply replace the return url with the redirect_uri, adding the error parameter yourself.如您所见,您无需使用对
GrantConsentAsync
的调用来响应access_denied
代码(不包含任何error_description
或error_uri
值),而是可以简单地将返回 url 替换为 redirect_uri,自己添加错误参数。 The trick here is that since the error_description and error_uri parameters are completely optional, you could capitalize on that and pass along something meaningful so that each client knows that this access was denied because the user canceled the form .这里的技巧是,由于 error_description 和 error_uri 参数是完全可选的,您可以利用它并传递一些有意义的东西,以便每个客户端知道此访问被拒绝,因为用户取消了表单。 Then, use that return url in the redirect.
然后,在重定向中使用该返回 url。
Here's an example on how to "re-build" the return url.这是一个关于如何“重新构建”返回 url 的示例。 You could have a function like:
你可以有这样的功能:
private string BuildCancelReturnUrl(AuthorizationRequest context)
{
var RedirectUri = new UriBuilder(context.RedirectUri);
var Query = HttpUtility.ParseQueryString(string.Empty);
Query.Add("error", "access_denied");
Query.Add("error_description", "some_meaningful_code_here");
// The state IS MEGA IMPORTANT:
Query.Add("state", context.Parameters["state"]);
RedirectUri.Query = Query.ToString();
return RedirectUri.ToString();
}
// Use like: model.ReturnUrl = BuildCancelReturnUrl(context);
// See above extract from Identity Server's demo code
So then, on the client's side, you could create some extension like this:那么,在客户端,你可以像这样创建一些扩展:
public static class OpenIdConnectOptionsExtensions {
public static OpenIdConnectOptions UseRedirectionOnLoginCancel(
this OpenIdConnectOptions options
, string RedirectTo = "/")
{
options.Events.OnAccessDenied = context =>
{
NameValueCollection RequestQuery = HttpUtility.ParseQueryString(context.Request.QueryString.Value);
string descriptionField = "error_description";
string cancelledCode = "your_meaningful_description_code_here";
bool descriptionIncluded = RequestQuery.AllKeys.Contains(descriptionField);
if (descriptionIncluded && RequestQuery[errorDescriptionField].Equals(cancelledCode))
{
context.Response.Redirect(RedirectTo);
context.HandleResponse();
}
return Task.CompletedTask;
};
return options;
}
}
Finally, each client could be configured to redirect to where you specify in Startup.cs
:最后,每个客户端都可以配置为重定向到您在
Startup.cs
指定的位置:
services.AddOpenIdConnect(<challenge_name>, config =>
{
// ...
config.UseRedirectionOnLoginCancel(<final path to redirect to>);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.