Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion FirebaseAuth.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ supports email and password accounts, as well as several 3rd party authenticatio
s.dependency 'GoogleUtilities/AppDelegateSwizzler', '~> 8.0'
s.dependency 'GoogleUtilities/Environment', '~> 8.0'
s.dependency 'GTMSessionFetcher/Core', '>= 3.4', '< 5.0'
s.ios.dependency 'RecaptchaInterop', '~> 100.0'
s.ios.dependency 'RecaptchaInterop', '~> 101.0'
s.test_spec 'unit' do |unit_tests|
unit_tests.scheme = { :code_coverage => true }
# Unit tests can't run on watchOS.
Expand Down
4 changes: 4 additions & 0 deletions FirebaseAuth/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Unreleased
- [changed] Using reCAPTCHA Enterprise and Firebase Auth requires reCAPTCHA
Enterprise 18.7.0 or later.

# 11.8.0
- [added] Added `ActionCodeSettings.linkDomain` to customize the Firebase Hosting link domain
that is used in out-of-band email action flows.
Expand Down
88 changes: 0 additions & 88 deletions FirebaseAuth/Sources/ObjC/FIRRecaptchaBridge.m

This file was deleted.

33 changes: 0 additions & 33 deletions FirebaseAuth/Sources/Public/FirebaseAuth/FIRRecaptchaBridge.h

This file was deleted.

1 change: 0 additions & 1 deletion FirebaseAuth/Sources/Public/FirebaseAuth/FirebaseAuth.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@
#import "FIRGoogleAuthProvider.h"
#import "FIRMultiFactor.h"
#import "FIRPhoneAuthProvider.h"
#import "FIRRecaptchaBridge.h"
#import "FIRTwitterAuthProvider.h"
103 changes: 75 additions & 28 deletions FirebaseAuth/Sources/Swift/Utilities/AuthRecaptchaVerifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,38 +125,85 @@
// No recaptcha on internal build system.
return actionString
#else
return try await withCheckedThrowingContinuation { continuation in
FIRRecaptchaGetToken(siteKey, actionString,
"NO_RECAPTCHA") { (token: String, error: Error?,
linked: Bool, actionCreated: Bool) in
guard linked else {
continuation.resume(throwing: AuthErrorUtils.recaptchaSDKNotLinkedError())
return
}
guard actionCreated else {
continuation.resume(throwing: AuthErrorUtils.recaptchaActionCreationFailed())
return
}
if let error {
continuation.resume(throwing: error)
return
} else {
if token == "NO_RECAPTCHA" {
AuthLog.logInfo(code: "I-AUT000031",
message: "reCAPTCHA token retrieval failed. NO_RECAPTCHA sent as the fake code.")
} else {
AuthLog.logInfo(
code: "I-AUT000030",
message: "reCAPTCHA token retrieval succeeded."
)
}
continuation.resume(returning: token)
}
}

let (token, error, linked, actionCreated) = await recaptchaToken(
siteKey: siteKey,
actionString: actionString,
fakeToken: "NO_RECAPTCHA"
)

guard linked else {
throw AuthErrorUtils.recaptchaSDKNotLinkedError()
}
guard actionCreated else {
throw AuthErrorUtils.recaptchaActionCreationFailed()
}
if let error {
throw error
}
if token == "NO_RECAPTCHA" {
AuthLog.logInfo(code: "I-AUT000031",
message: "reCAPTCHA token retrieval failed. NO_RECAPTCHA sent as the fake code.")
} else {
AuthLog.logInfo(
code: "I-AUT000030",
message: "reCAPTCHA token retrieval succeeded."
)
}
return token
#endif // !(COCOAPODS || SWIFT_PACKAGE)
}

private static var recaptchaClient: (any RCARecaptchaClientProtocol)?

private func recaptchaToken(siteKey: String,
actionString: String,
fakeToken: String) async -> (token: String, error: Error?,
linked: Bool, actionCreated: Bool) {
if let recaptchaClient {
return await retrieveToken(
actionString: actionString,
fakeToken: fakeToken,
recaptchaClient: recaptchaClient
)
}

if let recaptcha =
NSClassFromString("RecaptchaEnterprise.RCARecaptcha") as? RCARecaptchaProtocol.Type {
do {
let client = try await recaptcha.fetchClient(withSiteKey: siteKey)
recaptchaClient = client
return await retrieveToken(
actionString: actionString,
fakeToken: fakeToken,
recaptchaClient: client
)
} catch {
return ("", error, true, true)
}
} else {
// RecaptchaEnterprise not linked.
return ("", nil, false, false)
}
}

private func retrieveToken(actionString: String,
fakeToken: String,
recaptchaClient: RCARecaptchaClientProtocol) async -> (token: String,
error: Error?,
linked: Bool,
actionCreated: Bool) {
if let recaptchaAction =
NSClassFromString("RecaptchaEnterprise.RCAAction") as? RCAActionProtocol.Type {
let action = recaptchaAction.init(customAction: actionString)
let token = try? await recaptchaClient.execute(withAction: action)
return (token ?? "NO_RECAPTCHA", nil, true, true)
} else {
// RecaptchaEnterprise not linked.
return ("", nil, false, false)
}
}

func retrieveRecaptchaConfig(forceRefresh: Bool) async throws {
if !forceRefresh {
if let tenantID = auth?.tenantID {
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ let package = Package(
),
.package(
url: "https://github.com/google/interop-ios-for-google-sdks.git",
"100.0.0" ..< "101.0.0"
"101.0.0" ..< "102.0.0"
),
.package(url: "https://github.com/google/app-check.git",
"11.0.1" ..< "12.0.0"),
Expand Down
Loading