我们为网站提供了一个简单的 WKWebView,具有多种登录选项 - Google、Microsoft 和 DLRG(德国救生协会)。 为了进行身份验证,身份验证 URL 在
ASWebAuthenticationSession
中打开,用户可以通过所选方法登录并返回到所有登录的网站。这里有一个大问题,用户仅在弹出窗口中登录。如果我关闭 ASWebAuthenticationSession 弹出窗口,用户将返回到登录页面并可以从头开始。
更大的问题是,这不一致。有时它可以工作并且用户在
ASWebAuthenticationSession
过程完成后登录,但有时用户在弹出窗口中登录。
我有两部手机要测试,iPhone 11 和 iPhone 13 mini,在 iPhone 11 上,除了 Google 之外的所有内容每次都能正常工作,而在 iPhone 13 上,有时可以正常工作,有时我会登录到弹出窗口。这种行为是在具有相同登录数据的相同 TestFlight 版本以及两个设备最初注销时发生的。这让我发疯!
这是相关代码:
session = ASWebAuthenticationSession(url: url, callbackURLScheme: "com.my.app") { callbackURL, error in
if let error {
print("We have an error authenticating: \(error.localizedDescription)")
return
}
print("Session done and successfull")
}
session?.prefersEphemeralWebBrowserSession = true
session?.presentationContextProvider = authenticationManager
session?.start()
我们添加了带有“applinks”变量(即通用链接)的“关联域”功能,因此当用户点击包含我们标识符的链接时,应用程序将被打开。因此,
callbackURLScheme
将被完全忽略(我已经尝试了 info.plist 中方案的所有可能的变体),并且只有通过弹出窗口上的“取消”按钮关闭时才能访问打印语句。
在它确实有效的情况下,我通过此 SwiftUI 方法注册来自“外部”的重定向 url/uri:
.onOpenURL { url in
webViewModel.openURL(url)
}
然后我关闭弹出窗口(会话),加载网址并登录用户。当它不起作用时,
.onOpenURL
函数不会注册任何内容。
所以它有效,但高度不一致。我想也许是后端功能出了问题,但我和负责人谈过,他解释了背后的逻辑,我认为是iOS方面的问题。请注意,浏览器或 Android 应用程序不存在任何这些问题,因此重定向可以正常工作。但如果是在iOS端,你可以看到只需要几行代码就可以自定义
ASWebAuthenticationSession
。
如果您有任何想法或线索,请告诉我!谢谢你! :)
编辑:这个家伙here似乎也有同样的问题,它加载了ASWebAuthenticationSession中的内容,并说这是由于Google的2fa。我们使用 2fa 并遇到同样的问题,但在没有 2fa 的 Microsoft 中也会发生这种情况。所以我不确定这是否与此有关。
如果您使用 HTTPS 重定向 URL,也许可以尝试此代码。当您收到深层链接响应时,调用 startLogin 来调用窗口并调用 endLogin。
import Foundation
import AuthenticationServices
class LoginSession: NSObject, ASWebAuthenticationPresentationContextProviding {
private var authSession: ASWebAuthenticationSession?
private var error: OAuthError?
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
return ASPresentationAnchor()
}
func startLogin(authorizationRequestUrl: String) throws {
self.error = nil
authSession = ASWebAuthenticationSession(
url: URL(string: authorizationRequestUrl)!,
callbackURLScheme: "https",
completionHandler: { (callbackUrl: URL?, error: Error?) in
defer {
self.authSession?.cancel()
self.authSession = nil
}
if let errorCode = (error as? NSError)?.code {
if errorCode != ASWebAuthenticationSessionError.Code.canceledLogin.rawValue {
self.error = OAuthError(code: "login_error", message: "ASWebAuthenticationSession error code \(errorCode)")
}
}
}
)
authSession?.presentationContextProvider = self
authSession?.start()
}
func endLogin() {
self.authSession?.cancel()
self.authSession = nil
}
}
请注意,此代码仅处理登录窗口。您需要使用深层链接响应 URL 单独兑换代币代码。
请注意,您无法使用网站登录移动应用程序。例如,如果网站发布 cookie,WKWebView 将不会与上述登录窗口共享它们,因为 WKWebView 是私人浏览会话并使用不同的 cookie jar。
有关使用通用链接的 iOS 移动登录的更多信息,您可以运行我的代码示例并浏览随附的博客文章。请注意,登录响应需要
user gesture
才能可靠地返回到应用程序。这通常由某种 interstitial page
来处理。