[英]How to check access_denied on client when using IdentityServer4?
我有一個登錄頁面,當用戶單擊“取消”按鈕時我需要將他重定向到客戶端應用程序上的拒絕頁面。
內部登錄操作:
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);
}
}
在客戶端(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);
}
};
但我的問題是:我怎么知道 IdentityServer4 失敗是因為用戶單擊了“取消”按鈕(access_denied),或者是否有其他問題導致了該失敗?
基本表單有 2 個按鈕: login
和cancel
。 如果沒有按下login
; 這是一個cancel
。
否則它是一個驗證錯誤,您可以顯示它。 在cancel
您應該重定向回有意義的頁面。
您可以使用額外的參數重定向。 這些可以被獲取並用於顯示錯誤。 請記住,很多錯誤處理,例如無效的用戶名/密碼,都停留在 IdentityServer 端。
使用 IdentityServer4 時如何在客戶端檢查 access_denied?
經過一些檢查,事件的context.Failure.Data
是一種ListDictionaryInternal
,其中包含您可能正在尋找的條目:
error
error_description
error_uri
。 因此,通過使用context.Failure.Data["error"]
您可以獲得您正在尋找的“access_denied”值。
以 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("~/");
}
}
如您所見,您無需使用對GrantConsentAsync
的調用來響應access_denied
代碼(不包含任何error_description
或error_uri
值),而是可以簡單地將返回 url 替換為 redirect_uri,自己添加錯誤參數。 這里的技巧是,由於 error_description 和 error_uri 參數是完全可選的,您可以利用它並傳遞一些有意義的東西,以便每個客戶端知道此訪問被拒絕,因為用戶取消了表單。 然后,在重定向中使用該返回 url。
這是一個關於如何“重新構建”返回 url 的示例。 你可以有這樣的功能:
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
那么,在客戶端,你可以像這樣創建一些擴展:
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;
}
}
最后,每個客戶端都可以配置為重定向到您在Startup.cs
指定的位置:
services.AddOpenIdConnect(<challenge_name>, config =>
{
// ...
config.UseRedirectionOnLoginCancel(<final path to redirect to>);
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.