13

我正在尝试让隐式流程为 IdentityServer4 工作。登录和注销工作正常,但是 PostLogoutRedirectUri 返回 null,尽管设置了需要设置的值。我想要的是注销过程在注销完成后重定向回我的应用程序。

我正确获取了 logoutId,并且 Logout 调用了 BuildLoggedOutViewModelAsync:

[HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Logout(LogoutInputModel model)
    {
        var vm = await _account.BuildLoggedOutViewModelAsync(model.LogoutId);
...

这个方法位于我的AccountService.cs类中,然后调用DefaultIdentityServiceInteractionService的GetLogoutContextAsync:

public async Task<LoggedOutViewModel> BuildLoggedOutViewModelAsync(string logoutId)
    {
        // get context information (client name, post logout redirect URI and iframe for federated signout)
        var logout = await _interaction.GetLogoutContextAsync(logoutId);
...

这会创建一个 IdentityServer4.Models.LogoutRequest。

SignOutIFrameUrl字符串属性设置为,但"http://localhost:5000/connect/endsession/callback?sid=bf112f7785bc860fcc4351893012622e&logoutId=d6649e7f818d9709b2c0bc659696abdf"LogoutRequest 中似乎没有填充任何其他内容。

不幸的是,这意味着PostLogoutRedirectUri是空的,而AutomaticRedirectAfterSignOut也是空的,当LoggedOut.cshtml页面加载时,signout-callback.js文件永远不会加载:

@section scripts
{
    @if (Model.AutomaticRedirectAfterSignOut)
    {
        <script src="~/js/signout-redirect.js"></script>
    }
}

这是我的配置设置。

配置文件:

public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "implicit.client",
                AllowedGrantTypes = GrantTypes.Implicit,
                AllowAccessTokensViaBrowser = true,
                AllowedScopes = 
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "ContractManagerAPI"
                },
                RedirectUris = { "http://localhost:9000/" },
                PostLogoutRedirectUris = { "http://localhost:9000/" },
                AllowedCorsOrigins = { "http://localhost:9000" },
                RequireConsent = false,

            }                
        };
    }

app.ts(js客户端):

import {UserManager} from 'oidc-client';
import { inject, Factory } from 'aurelia-framework';

@inject(Factory.of(UserManager))
export class App {
  userManager: UserManager;

  constructor(userManagerFactory){
    let config = {
      authority: 'http://localhost:5000',
      client_id: 'implicit.client',
      response_type: 'id_token token',
      scope: 'openid profile ContractManagerAPI',
      redirect_uri: 'http://localhost:9000/',
      post_logout_redirect_uri: 'http://localhost:9000/'
    };

    this.userManager = userManagerFactory(config);
  }

  login(){
    this.userManager.signinRedirect();
  }

  logout(){
    this.userManager.signoutRedirect();
  }
}

Startup.cs 的相关部分:

services.AddIdentityServer()
                .AddTemporarySigningCredential()
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddContractManagerUserStore()
                .AddProfileService<ContractManagerProfileService>();

在找出我哪里出错的任何帮助将不胜感激。

谢谢!

4

6 回答 6

11

将 id_token_hint 参数传递给 signoutRedirect()

您可以从 signinRedirect() 返回的 User 对象中获取 id_token_hint;

因此,假设您在 ts 文件中有一个名为“user”的变量,该变量是由于用户通过 signinRedirect() 登录而设置的。

那么你会做...

logout(){
    this.userManager.signoutRedirect({ 'id_token_hint': this.user.id_token });
}
于 2017-06-23T16:39:19.540 回答
3

我遇到了(可能)与 OP 相同的问题。

在检查了来自 IdentityServer 的日志后,我注意到在包含我的客户端信息的请求信息被发送到 IdentityServer 服务器之后就抛出了一个异常。

这导致我直接解决了这个错误的 github 帖子。解决方案是更新到 IdentityServer4 v4.1.2。然后我重新运行了我的代码,瞧!var context = await _interaction.GetLogoutContextAsync(logoutId);现在从调用中正确填充了 PostLogoutRedirectUri(和其他参数) 。

于 2021-03-30T14:25:56.833 回答
2

确保正确配置了这些设置:

public class AccountOptions
        {
            public static bool AllowLocalLogin = true;
            public static bool AllowRememberLogin = true;
            public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30);

            public static bool ShowLogoutPrompt = false;
            public static bool AutomaticRedirectAfterSignOut = true;

            public static bool WindowsAuthenticationEnabled = false;
            // specify the Windows authentication schemes you want to use for authentication
            public static readonly string[] WindowsAuthenticationSchemes = new string[] { "Negotiate", "NTLM" };
            public static readonly string WindowsAuthenticationDisplayName = "Windows";

            public static string InvalidCredentialsErrorMessage = "Invalid username or password";
        }
于 2017-06-22T12:45:13.360 回答
1

我想分享我用空 PostLogoutRedirectUri 值解决问题的经验。

要启动注销过程,您必须首先SignOut("Cookies", "oidc")在 mvc 客户端调用。否则,您将在 Identity Server 端获得 null logoutId 值。我的 HomeController 中的示例端点:

public IActionResult Logout()
{
    return SignOut("Cookies", "oidc");
}

SignInScheme在我在 mvc 客户端添加值之前,我在注销上下文中总是有 null PostLogoutRedirectUri 值。MVC 客户端的这些身份验证设置对我有用:

var authenticationBuilder = services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
});

authenticationBuilder.AddCookie(options =>
{
    options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
    options.Cookie.Name = "identity_server_mvc";
});

authenticationBuilder.AddOpenIdConnect("oidc", options =>
{
    options.Authority = "{IDENTITY_SERVER_URL}";
    options.ClientId = "mvc";
    options.SaveTokens = true;
    options.SignInScheme = "Cookies";
});

您还需要确保已将 PostLogoutRedirectUri 值添加到 Identity Server 端的客户端配置中:

new Client
{
    ClientId = "mvc",
    AllowedGrantTypes = GrantTypes.Implicit,

    RedirectUris           = { "{CLIENT_URL}/signin-oidc" },
    PostLogoutRedirectUris = { "{CLIENT_URL}/signout-callback-oidc" },

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile
    }
}

希望能帮助到你!

于 2019-10-28T23:56:35.640 回答
0

尝试为 MVC 客户端配置 LogoutUrl!

于 2017-06-21T20:27:36.540 回答
0

对我来说,解决 null 的是 mvc 客户端上设置的波纹管选项

o.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
于 2021-02-24T17:49:48.383 回答