You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS基于Auth2实现多应用SSO的问题求助(使用AuthSwift)

针对跨App OAuth2 SSO的解决方案(基于AuthSwift)

我帮你梳理下怎么解决这个跨App单点登录的问题,结合你用的AuthSwift和遇到的几个痛点,咱们一步步来搞定:

核心问题分析

你遇到的本质问题是:iOS 11+之后,SFSafariViewController的会话Cookie和Safari主App、其他App的SFSVC实例是隔离的;而直接调用Safari虽然能共享Cookie,但跳转体验差。所以咱们得换个思路——不依赖浏览器Cookie,而是在App间直接共享OAuth2的令牌信息,或者用官方支持的凭据共享机制。

方案一:钥匙串共享组(最推荐,体验最优)

这个方案是把OAuth2的access token、refresh token存在共享钥匙串组里,让同开发者的A、B App都能访问这些令牌,完全绕开浏览器的Cookie限制,体验和Facebook/Messenger一致。

步骤1:配置钥匙串共享权限

  1. 打开Xcode,分别给A、B App添加Keychain Sharing Entitlement(在Signing & Capabilities里添加)。
  2. 给两个App设置同一个Group ID,比如com.yourcompany.sso-shared-group(格式一般是你的TeamID.自定义组名)。

步骤2:自定义AuthSwift的存储层

AuthSwift默认的存储是存在App沙盒里的UserDefaults,不能跨App访问,所以咱们要改成存储到共享钥匙串里。可以用KeychainAccess库(直接pod引入)来简化操作,示例代码:

import AuthSwift
import KeychainAccess

// 初始化共享钥匙串实例,用咱们刚才设置的Group ID
let sharedKeychain = Keychain(service: "com.yourcompany.sso-shared-group")

// 创建AuthSwift实例时,指定自定义存储
let authSwift = AuthSwift(
    consumerKey: "你的ConsumerKey",
    consumerSecret: "你的ConsumerSecret",
    requestTokenUrl: "https://你的认证服务器/oauth/request_token",
    authorizeUrl: "https://你的认证服务器/oauth/authorize",
    accessTokenUrl: "https://你的认证服务器/oauth/access_token",
    callbackUrl: "你的AppScheme://callback"
)

// 替换默认存储为共享钥匙串存储
authSwift.storage = SharedKeychainStorage(keychain: sharedKeychain)

// 自定义存储类,实现AuthSwift的存储协议
class SharedKeychainStorage: AuthSwiftStorageProtocol {
    private let keychain: Keychain
    
    init(keychain: Keychain) {
        self.keychain = keychain
    }
    
    func set(_ value: String, forKey key: String) {
        do {
            try keychain.set(value, key: key)
        } catch {
            print("钥匙串存储失败:\(error)")
        }
    }
    
    func string(forKey key: String) -> String? {
        return try? keychain.getString(key)
    }
    
    func remove(forKey key: String) {
        do {
            try keychain.remove(key)
        } catch {
            print("钥匙串删除失败:\(error)")
        }
    }
    
    func allKeys() -> [String] {
        return (try? keychain.allKeys()) ?? []
    }
}

步骤3:启动时自动登录

在A、B App的启动逻辑里,先检查共享钥匙串里有没有有效的令牌:

  • 如果有,直接用令牌调用接口获取用户信息,跳转到首页;
  • 如果没有,再触发OAuth2认证流程(推荐用下面说的ASWebAuthenticationSession)。

方案二:Shared Web Credentials(官方网页凭据共享)

如果你的认证服务器支持,也可以用iOS官方的Shared Web Credentials机制,让App和网页共享登录凭据,同时跨App共享。

步骤1:配置Associated Domains

给A、B App添加com.apple.developer.associated-domains Entitlement,添加webcredentials:你的认证域名.com(比如webcredentials:auth.yourcompany.com)。

步骤2:配置服务器端文件

在你的认证服务器的.well-known目录下,创建apple-app-site-association文件,内容如下(替换成你的TeamID和两个App的Bundle ID):

{
  "webcredentials": {
    "apps": ["ABCDE12345.com.yourcompany.AppA", "ABCDE12345.com.yourcompany.AppB"]
  }
}

步骤3:在AuthSwift中集成

登录成功后,调用SecAddSharedWebCredential把用户名和令牌存储为共享凭据;在另一个App启动时,调用SecRequestSharedWebCredential获取凭据,自动完成登录。

针对你之前尝试的方案的优化

  • WebView方案:放弃吧,WebView的Cookie是App沙盒私有,根本没法跨App共享,完全不适合SSO场景。
  • SFSafariViewController方案:iOS 11+之后确实隔离了Cookie,所以不用纠结这个了,换成上面的钥匙串方案更靠谱。
  • Safari跳转方案:如果一定要用浏览器会话,建议换成ASWebAuthenticationSession(iOS 12+),它是苹果专门为OAuth2认证设计的API,体验比直接调用Safari好很多,而且可以配置prefersEphemeralWebBrowserSession来控制会话是否持久化。另外,结合钥匙串共享,只有当令牌失效时才会触发浏览器认证,平时直接用令牌登录,不会频繁跳转。

总结

优先推荐钥匙串共享组方案,实现起来简单,体验最接近你想要的Facebook/Messenger模式,完全不依赖浏览器的Cookie,跨App令牌共享直接可靠。

内容的提问来源于stack exchange,提问作者ki1234

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:39:13