Skip to content

Commit 7ac16e2

Browse files
committed
using FIRAllocatedUnfairLock type to combine token and its lock
1 parent a638100 commit 7ac16e2

File tree

1 file changed

+28
-23
lines changed

1 file changed

+28
-23
lines changed

FirebaseAuth/Sources/Swift/Auth/Auth.swift

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import FirebaseAppCheckInterop
1818
import FirebaseAuthInterop
1919
import FirebaseCore
2020
import FirebaseCoreExtension
21+
import FirebaseCoreInternal
2122
#if COCOAPODS
2223
internal import GoogleUtilities
2324
#else
@@ -88,21 +89,30 @@ extension Auth: AuthInterop {
8889
return
8990
}
9091
/// Before checking for a standard user, check if we are in a token-only session established
91-
/// by a successful `exchangeToken` call.
92-
let rGCIPToken = self.rGCIPStateLock.withLock { self._rGCIPFirebaseToken }
92+
/// by a successful exchangeToken call.
93+
let rGCIPToken = self.rGCIPFirebaseTokenLock.withLock { $0 }
9394

9495
if let token = rGCIPToken {
95-
/// If a token exists, this session is active. Check for expiration.
96-
if forceRefresh || token.expirationDate < Date() {
97-
let errorMessage = forceRefresh ? "A new token was requested via forceRefresh." :
98-
"The session token has expired."
99-
let error = AuthErrorUtils.userTokenExpiredError(message: errorMessage)
96+
/// Logic for tokens obtained via exchangeToken (R-GCIP mode)
97+
if token.expirationDate < Date() {
98+
/// Token expired
99+
let error = AuthErrorUtils
100+
.userTokenExpiredError(
101+
message: "The firebase access token obtained via exchangeToken() has expired."
102+
)
103+
Auth.wrapMainAsync(callback: callback, with: .failure(error))
104+
} else if forceRefresh {
105+
/// Token is not expired, but forceRefresh was requested which is currently unsupported
106+
let error = AuthErrorUtils
107+
.operationNotAllowedError(
108+
message: "forceRefresh is not supported for firebase access tokens obtained via exchangeToken()."
109+
)
100110
Auth.wrapMainAsync(callback: callback, with: .failure(error))
101111
} else {
102-
/// The token is valid; return it.
112+
/// The token is valid and not expired.
103113
Auth.wrapMainAsync(callback: callback, with: .success(token.token))
104114
}
105-
/// Exit here to prevent falling through to the standard `currentUser` logic.
115+
/// Exit here as this path is for rGCIPFirebaseToken only.
106116
return
107117
}
108118
/// Fallback to standard `currentUser` logic if not in token-only mode.
@@ -2312,9 +2322,7 @@ public struct FirebaseToken: Sendable {
23122322
/// invalidated to prevent a conflicting auth state.
23132323
/// Clear any R-GCIP session state when a standard user signs in. This ensures we exit
23142324
/// Token-Only Mode.
2315-
self.rGCIPStateLock.withLock {
2316-
self._rGCIPFirebaseToken = nil
2317-
}
2325+
self.rGCIPFirebaseTokenLock.withLock { $0 = nil }
23182326
/// ... rest of original function
23192327
do {
23202328
try self.updateCurrentUser(authResult.user, byForce: false, savingToDisk: true)
@@ -2497,16 +2505,13 @@ public struct FirebaseToken: Sendable {
24972505

24982506
// MARK: - R-GCIP Token-Only Session State
24992507

2500-
/// The session token obtained from a successful `exchangeToken` call.
2508+
/// The session token obtained from a successful `exchangeToken` call, protected by a lock.
25012509
///
25022510
/// This property is used to support a "token-only" authentication mode for Regionalized
25032511
/// GCIP, where no `User` object is created. It is mutually exclusive with `_currentUser`.
2504-
/// If this property is non-nil, the `AuthInterop` layer will use it for token generation
2512+
/// If the wrapped value is non-nil, the `AuthInterop` layer will use it for token generation
25052513
/// instead of relying on a `currentUser`.
2506-
private var _rGCIPFirebaseToken: FirebaseToken?
2507-
2508-
/// A lock to ensure thread-safe access to the R-GCIP token state.
2509-
private let rGCIPStateLock = NSLock()
2514+
private var rGCIPFirebaseTokenLock = FIRAllocatedUnfairLock<FirebaseToken?>(initialState: nil)
25102515
}
25112516

25122517
@available(iOS 13, *)
@@ -2558,14 +2563,14 @@ public extension Auth {
25582563
token: response.firebaseToken,
25592564
expirationDate: response.expirationDate
25602565
)
2561-
self.rGCIPStateLock.withLock {
2566+
self.rGCIPFirebaseTokenLock.withLock { token in
25622567
// Activating token-only mode requires two steps:
25632568
// 1. Ensure no standard user is active, as these states are mutually exclusive.
25642569
if self._currentUser != nil {
25652570
try? self.signOut()
25662571
}
2567-
// 2. Store the new session token for `getToken`.
2568-
self._rGCIPFirebaseToken = firebaseToken
2572+
// 2. Store the new session token for getToken.
2573+
token = firebaseToken
25692574
}
25702575
Auth.wrapMainAsync(callback: completion, with: .success(firebaseToken))
25712576
} catch {
@@ -2612,11 +2617,11 @@ public extension Auth {
26122617
token: response.firebaseToken,
26132618
expirationDate: response.expirationDate
26142619
)
2615-
rGCIPStateLock.withLock {
2620+
rGCIPFirebaseTokenLock.withLock { token in
26162621
if self._currentUser != nil {
26172622
try? self.signOut()
26182623
}
2619-
self._rGCIPFirebaseToken = firebaseToken
2624+
token = firebaseToken
26202625
}
26212626
return firebaseToken
26222627
} catch {

0 commit comments

Comments
 (0)