|
125 | 125 | // No recaptcha on internal build system. |
126 | 126 | return actionString |
127 | 127 | #else |
128 | | - return try await withCheckedThrowingContinuation { continuation in |
129 | | - FIRRecaptchaGetToken(siteKey, actionString, |
130 | | - "NO_RECAPTCHA") { (token: String, error: Error?, |
131 | | - linked: Bool, actionCreated: Bool) in |
132 | | - guard linked else { |
133 | | - continuation.resume(throwing: AuthErrorUtils.recaptchaSDKNotLinkedError()) |
134 | | - return |
135 | | - } |
136 | | - guard actionCreated else { |
137 | | - continuation.resume(throwing: AuthErrorUtils.recaptchaActionCreationFailed()) |
138 | | - return |
139 | | - } |
140 | | - if let error { |
141 | | - continuation.resume(throwing: error) |
142 | | - return |
143 | | - } else { |
144 | | - if token == "NO_RECAPTCHA" { |
145 | | - AuthLog.logInfo(code: "I-AUT000031", |
146 | | - message: "reCAPTCHA token retrieval failed. NO_RECAPTCHA sent as the fake code.") |
147 | | - } else { |
148 | | - AuthLog.logInfo( |
149 | | - code: "I-AUT000030", |
150 | | - message: "reCAPTCHA token retrieval succeeded." |
151 | | - ) |
152 | | - } |
153 | | - continuation.resume(returning: token) |
154 | | - } |
155 | | - } |
| 128 | + |
| 129 | + let (token, error, linked, actionCreated) = await recaptchaToken( |
| 130 | + siteKey: siteKey, |
| 131 | + actionString: actionString, |
| 132 | + fakeToken: "NO_RECAPTCHA" |
| 133 | + ) |
| 134 | + |
| 135 | + guard linked else { |
| 136 | + throw AuthErrorUtils.recaptchaSDKNotLinkedError() |
| 137 | + } |
| 138 | + guard actionCreated else { |
| 139 | + throw AuthErrorUtils.recaptchaActionCreationFailed() |
| 140 | + } |
| 141 | + if let error { |
| 142 | + throw error |
156 | 143 | } |
| 144 | + if token == "NO_RECAPTCHA" { |
| 145 | + AuthLog.logInfo(code: "I-AUT000031", |
| 146 | + message: "reCAPTCHA token retrieval failed. NO_RECAPTCHA sent as the fake code.") |
| 147 | + } else { |
| 148 | + AuthLog.logInfo( |
| 149 | + code: "I-AUT000030", |
| 150 | + message: "reCAPTCHA token retrieval succeeded." |
| 151 | + ) |
| 152 | + } |
| 153 | + return token |
157 | 154 | #endif // !(COCOAPODS || SWIFT_PACKAGE) |
158 | 155 | } |
159 | 156 |
|
| 157 | + private static var recaptchaClient: (any RCARecaptchaClientProtocol)? |
| 158 | + |
| 159 | + private func recaptchaToken(siteKey: String, |
| 160 | + actionString: String, |
| 161 | + fakeToken: String) async -> (token: String, error: Error?, |
| 162 | + linked: Bool, actionCreated: Bool) { |
| 163 | + if let recaptchaClient { |
| 164 | + return await retrieveToken( |
| 165 | + actionString: actionString, |
| 166 | + fakeToken: fakeToken, |
| 167 | + recaptchaClient: recaptchaClient |
| 168 | + ) |
| 169 | + } |
| 170 | + |
| 171 | + if let recaptcha = |
| 172 | + NSClassFromString("RecaptchaEnterprise.RCARecaptcha") as? RCARecaptchaProtocol.Type { |
| 173 | + do { |
| 174 | + let client = try await recaptcha.fetchClient(withSiteKey: siteKey) |
| 175 | + recaptchaClient = client |
| 176 | + return await retrieveToken( |
| 177 | + actionString: actionString, |
| 178 | + fakeToken: fakeToken, |
| 179 | + recaptchaClient: client |
| 180 | + ) |
| 181 | + } catch { |
| 182 | + return ("", error, true, true) |
| 183 | + } |
| 184 | + } else { |
| 185 | + // RecaptchaEnterprise not linked. |
| 186 | + return ("", nil, false, false) |
| 187 | + } |
| 188 | + } |
| 189 | + |
| 190 | + private func retrieveToken(actionString: String, |
| 191 | + fakeToken: String, |
| 192 | + recaptchaClient: RCARecaptchaClientProtocol) async -> (token: String, |
| 193 | + error: Error?, |
| 194 | + linked: Bool, |
| 195 | + actionCreated: Bool) { |
| 196 | + if let recaptchaAction = |
| 197 | + NSClassFromString("RecaptchaEnterprise.RCAAction") as? RCAActionProtocol.Type { |
| 198 | + let action = recaptchaAction.init(customAction: actionString) |
| 199 | + let token = try? await recaptchaClient.execute(withAction: action) |
| 200 | + return (token ?? "NO_RECAPTCHA", nil, true, true) |
| 201 | + } else { |
| 202 | + // RecaptchaEnterprise not linked. |
| 203 | + return ("", nil, false, false) |
| 204 | + } |
| 205 | + } |
| 206 | + |
160 | 207 | func retrieveRecaptchaConfig(forceRefresh: Bool) async throws { |
161 | 208 | if !forceRefresh { |
162 | 209 | if let tenantID = auth?.tenantID { |
|
0 commit comments