iOS 在 Flutter 中使用 IdentityServer4 调用 AppAuth 注销/结束会话端点

Calling AppAuth sign out / endsession endpoint using IdentityServer4 in Flutter on iOS

我在 Flutter 中使用 flutter_appauth 包来处理针对 IdentityServer4 的授权代码流,但一直无法找到调用 iOS 中的 /endsession 端点的方法。

为了了解我正在尝试做什么,这是我使用 url_launcher 包的工作 Android 实现:

    var signOutUrl = '${_endSessionUrl}?id_token_hint=${_idToken}&post_logout_redirect_uri=${AppConfig.oidcCallbackUri}';
    await launch(signOutUrl);

使用相同的代码,iOS 只是报告一般性的 PlatformException,没有关于原因的额外细节,尽管这个异常肯定与通过尝试启动 url.

this GitHub comment 中的解决方案似乎可以使用 OKTA,但是当使用 IdentityServer4 时,我收到以下异常,它会立即终止 Flutter 应用程序:

[DEVICE LOG] 2020-04-16 08:55:01.039163-0400  localhost Runner[18007]: (CoreFoundation) *** Terminating app due to uncaught exception 'Attempted to create a token exchange request from an authorization
response with no authorization code.', reason: 'Attempted to create a token exchange request from an authorization response with no authorization code.'

考虑到我的 /endsession 端点没有返回授权响应,这似乎是有道理的。

无论如何,调用带有结束会话的授权端点的解决方案 URL 充其量只是一种 hack,但这似乎是 "accepted" 的实现方式。

我能找到的所有关于使用 AppAuth 的文档都说注销可以通过应用程序内的 "forgetting" 令牌来实现,但是由于浏览器保留了身份验证 cookie,因此会自动重新登录。用户没有机会选择不同的帐户。

另外值得注意的是,这并非特定于 Flutter、flutter_appauth 包或 IdentityServer4。 This comment 在本机 AppAuth-iOS 包上列出了与上述相同解决方案的相同问题。

绝对可以在 iOS 上注销(并因此删除浏览器 cookie),但我完全不知道如何实现它。

当您调用授权和交换代码的方法时,需要添加一个名为“promptValues”的附加参数,其值为'login'。这样,每次登录时,缓存中没有任何值,它总是要求重新登录。

我从这个 post openid/AppAuth-Android#215 找到这个解决方案,其中评论了注销和删除浏览器历史记录以及 OpenId 文档

final AuthorizationTokenResponse result =
await appAuth.authorizeAndExchangeCode(
  AuthorizationTokenRequest(
    your_client_id,
    your_localhost,
    promptValues: ['login'],
    discoveryUrl:
    your_discovery_url,
    scopes: [your_scopes],
  ),
);