简体   繁体   English

使用 IdentityServer4 时如何在客户端检查 access_denied?

[英]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),或者是否有其他问题导致了该失败?

On the IdentityServer side:在 IdentityServer 端:

The basic form has 2 buttons: login and cancel .基本表单有 2 个按钮: logincancel 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您应该重定向回有意义的页面。

On the MVC side:在MVC方面:

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”值。


Another Option另外一个选项

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_descriptionerror_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.

相关问题 使用Yahoo OAuth时出现“ access_denied” - “access_denied” when using Yahoo OAuth ACCESS_DENIED 在 UWP 应用中使用 ShellExecute - ACCESS_DENIED in UWP app using ShellExecute 如何使用FrontChannelLogout从外部IdentityServer4从IdentityServer4-客户端注销 - How to logout from IdentityServer4-client from External IdentityServer4 using FrontChannelLogout IdentityServer4 - ApiResource和Client,它们是如何捆绑在一起的 - IdentityServer4 - ApiResource and Client, how are they tied together IdentityServer4:如何检查访问令牌是否具有给定访问令牌的权限? - IdentityServer4: How do you check if access token has permission for a given access token? IdentityServer4错误,此客户端不允许offline_access - IdentityServer4 Error, offline_access is not allowed for this client 密码流的 IdentityServer4 客户端不包括访问令牌中的 TestUser 声明 - IdentityServer4 client for Password Flow not including TestUser claims in access token 使用IdentityServer,在运行CreateUser时,.json文件的访问被拒绝 - Using IdentityServer, when running CreateUser access is denied for .json file 通过oidc-client登录IdentityServer4时出现InvalidOperationException - InvalidOperationException when signing in to IdentityServer4 via oidc-client GetDiscoveryDocumentAsync 失败,IdentityServer4 客户端 - GetDiscoveryDocumentAsync failed, IdentityServer4 client
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM