无法在 ASP.NET Core 2 应用程序上注销 identityserver4 的 OpenIdConnect 身份验证
Cannot sign out the OpenIdConnect authentication of identityserver4 on ASP.NET Core 2 application
我的身份服务器正在使用 identityserver4 框架 (http://localhost:9000)。然后我在 Identity Server 上注册客户端,如下所示。
clients.Add(
new Client
{
ClientId = "customer.api",
ClientName = "Customer services",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = false,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "http://localhost:60001/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:60001/signout-callback-oidc" },
ClientSecrets = new List<Secret>
{
new Secret("testsecret".Sha256())
},
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.OfflineAccess,
"customerprivatelinesvn.api",
},
AllowOfflineAccess = true,
AlwaysIncludeUserClaimsInIdToken = true,
AllowedCorsOrigins = { "http://localhost:60001" }
});
这是我的客户端应用程序 (http://localhost:60001) 上的身份验证。
private void AddAuthentication(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie()
.AddOpenIdConnect("oidc", options =>
{
Configuration.GetSection("OpenIdConnect").Bind(options);
});
}
"OpenIdConnect": {
"SignInScheme": "Cookies",
"Authority": "http://localhost:9000/",
"RequireHttpsMetadata": false,
"ClientId": "customer.api",
"ClientSecret": "testsecret",
"Scope": [ "customerprivatelinesvn.api", "offline_access" ],
"CallbackPath": "/signin-oidc",
"ResponseType": "code id_token token",
"GetClaimsFromUserInfoEndpoint": true,
"SaveTokens": true
}
客户端应用的HomeController
[Authorize]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
这是用户登录后客户端应用程序的Cookies。
我尝试执行如下注销操作
public class AccountController : Controller
{
public async Task<IActionResult> Signout()
{
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
return RedirectToAction("Index", "Home");
}
}
但是当用户注销时,它不会调用身份服务器的结束会话端点。我看fiddler的流量,没有请求identity server
我的期望是当用户注销时,它将调用身份服务器的结束会话端点并重定向到身份服务器的注销 link,如下所示。
我们可以通过调用 OwinContext signout 在 MVC 应用程序上轻松完成此操作
private void LogoutOwin(IOwinContext context)
{
context.Authentication.SignOut();
}
但是注销方法在 ASP.NET Core 2 上不再有效。
注意:我正在从 AJAX post 调用注销操作,因为我的客户端应用程序是 angular 5 应用程序。
有谁知道如何在 ASP.NET Core 2 上正确实现注销?
非常感谢。
此致,
凯文
我现在可以解决我的问题了。
1) Return SignOutResult 将调用结束会话端点。
2) 更改 AJAX post 以提交表单。
public class AccountController : Controller
{
public IActionResult Signout()
{
return new SignOutResult(new[] { "oidc", "Cookies" });
}
}
<form action="/Account/Signout" id="signoutForm" method="post" novalidate="novalidate">
<ul class="nav navbar-nav navbar-right">
<li><a href="javascript:document.getElementById('signoutForm').submit()">Sign out</a></li>
</ul>
</form>
在 Net Core 2.0 上更改您的代码以使用枚举 CookieAuthenticationDefaults 和 OpenIdConnectDefaults
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(SetOpenIdConnectOptions);
private static void SetOpenIdConnectOptions(OpenIdConnectOptions options)
{
options.ClientId = "auAuthApp_implicit";
options.Authority = "http://localhost:55379/";
options.SignInScheme = "Cookies";
options.RequireHttpsMetadata = false;
options.SaveTokens = true;
options.ResponseType = "id_token token";
options.GetClaimsFromUserInfoEndpoint = true;
}
和...
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
return RedirectToAction("Index", "Home");
}
要允许注销,请使用以下注销操作:
public async Task Logout()
{
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
}
这正是快速入门所说的使用方法 (http://docs.identityserver.io/en/release/quickstarts/3_interactive_login.html)。
你(和我)太聪明了。我查看了教程中的操作并认为“这还不完整,它没有 return 操作结果,让我们重定向回我的页面”。
实际上,HttpContext.SignOutAsync("oidc");
设置了一个默认的 ActionResult(重定向到 OpenIdConnect 提供商以完成注销)。通过使用 return RedirectToAction("Index", "Home");
指定您自己的内容,您可以覆盖它,因此永远不会发生注销操作。
注销后重定向
从 this answer 开始,您在注销完成后指定重定向 URL 的方法是使用 AuthenticationProperties
public async Task Logout()
{
await context.SignOutAsync("Cookies");
var prop = new AuthenticationProperties
{
RedirectUri = "/logout-complete"
};
// after signout this will redirect to your provided target
await context.SignOutAsync("oidc", prop);
}
.Net Core 3.1,使用AuthenticationProperties设置重定向url.
public async Task Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties { RedirectUri = "/Home/Logout-Complete" });
}
我的身份服务器正在使用 identityserver4 框架 (http://localhost:9000)。然后我在 Identity Server 上注册客户端,如下所示。
clients.Add(
new Client
{
ClientId = "customer.api",
ClientName = "Customer services",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = false,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "http://localhost:60001/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:60001/signout-callback-oidc" },
ClientSecrets = new List<Secret>
{
new Secret("testsecret".Sha256())
},
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.OfflineAccess,
"customerprivatelinesvn.api",
},
AllowOfflineAccess = true,
AlwaysIncludeUserClaimsInIdToken = true,
AllowedCorsOrigins = { "http://localhost:60001" }
});
这是我的客户端应用程序 (http://localhost:60001) 上的身份验证。
private void AddAuthentication(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie()
.AddOpenIdConnect("oidc", options =>
{
Configuration.GetSection("OpenIdConnect").Bind(options);
});
}
"OpenIdConnect": {
"SignInScheme": "Cookies",
"Authority": "http://localhost:9000/",
"RequireHttpsMetadata": false,
"ClientId": "customer.api",
"ClientSecret": "testsecret",
"Scope": [ "customerprivatelinesvn.api", "offline_access" ],
"CallbackPath": "/signin-oidc",
"ResponseType": "code id_token token",
"GetClaimsFromUserInfoEndpoint": true,
"SaveTokens": true
}
客户端应用的HomeController
[Authorize]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
这是用户登录后客户端应用程序的Cookies。
我尝试执行如下注销操作
public class AccountController : Controller
{
public async Task<IActionResult> Signout()
{
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
return RedirectToAction("Index", "Home");
}
}
但是当用户注销时,它不会调用身份服务器的结束会话端点。我看fiddler的流量,没有请求identity server
我的期望是当用户注销时,它将调用身份服务器的结束会话端点并重定向到身份服务器的注销 link,如下所示。
我们可以通过调用 OwinContext signout 在 MVC 应用程序上轻松完成此操作
private void LogoutOwin(IOwinContext context)
{
context.Authentication.SignOut();
}
但是注销方法在 ASP.NET Core 2 上不再有效。
注意:我正在从 AJAX post 调用注销操作,因为我的客户端应用程序是 angular 5 应用程序。
有谁知道如何在 ASP.NET Core 2 上正确实现注销?
非常感谢。
此致,
凯文
我现在可以解决我的问题了。
1) Return SignOutResult 将调用结束会话端点。
2) 更改 AJAX post 以提交表单。
public class AccountController : Controller
{
public IActionResult Signout()
{
return new SignOutResult(new[] { "oidc", "Cookies" });
}
}
<form action="/Account/Signout" id="signoutForm" method="post" novalidate="novalidate">
<ul class="nav navbar-nav navbar-right">
<li><a href="javascript:document.getElementById('signoutForm').submit()">Sign out</a></li>
</ul>
</form>
在 Net Core 2.0 上更改您的代码以使用枚举 CookieAuthenticationDefaults 和 OpenIdConnectDefaults
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(SetOpenIdConnectOptions);
private static void SetOpenIdConnectOptions(OpenIdConnectOptions options)
{
options.ClientId = "auAuthApp_implicit";
options.Authority = "http://localhost:55379/";
options.SignInScheme = "Cookies";
options.RequireHttpsMetadata = false;
options.SaveTokens = true;
options.ResponseType = "id_token token";
options.GetClaimsFromUserInfoEndpoint = true;
}
和...
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
return RedirectToAction("Index", "Home");
}
要允许注销,请使用以下注销操作:
public async Task Logout()
{
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
}
这正是快速入门所说的使用方法 (http://docs.identityserver.io/en/release/quickstarts/3_interactive_login.html)。 你(和我)太聪明了。我查看了教程中的操作并认为“这还不完整,它没有 return 操作结果,让我们重定向回我的页面”。
实际上,HttpContext.SignOutAsync("oidc");
设置了一个默认的 ActionResult(重定向到 OpenIdConnect 提供商以完成注销)。通过使用 return RedirectToAction("Index", "Home");
指定您自己的内容,您可以覆盖它,因此永远不会发生注销操作。
注销后重定向
从 this answer 开始,您在注销完成后指定重定向 URL 的方法是使用 AuthenticationProperties
public async Task Logout()
{
await context.SignOutAsync("Cookies");
var prop = new AuthenticationProperties
{
RedirectUri = "/logout-complete"
};
// after signout this will redirect to your provided target
await context.SignOutAsync("oidc", prop);
}
.Net Core 3.1,使用AuthenticationProperties设置重定向url.
public async Task Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties { RedirectUri = "/Home/Logout-Complete" });
}