Skip to content

Commit 5614990

Browse files
email link sign-in
1 parent 52b92fb commit 5614990

3 files changed

Lines changed: 55 additions & 8 deletions

File tree

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/AuthServiceError.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public enum AuthServiceError: LocalizedError {
1616
case invalidEmailLink
1717
case notConfiguredProvider(String)
1818
case clientIdNotFound(String)
19-
case notConfiguredActionCodeSettings
19+
case notConfiguredActionCodeSettings(String)
2020
case reauthenticationRequired(String)
2121
case invalidCredentials(String)
2222
case signInFailed(underlying: Error)
@@ -30,8 +30,8 @@ public enum AuthServiceError: LocalizedError {
3030
return description
3131
case let .clientIdNotFound(description):
3232
return description
33-
case .notConfiguredActionCodeSettings:
34-
return "ActionCodeSettings has not been configured for `AuthConfiguration.emailLinkSignInActionCodeSettings`"
33+
case let .notConfiguredActionCodeSettings(description):
34+
return description
3535
case let .reauthenticationRequired(description):
3636
return description
3737
case let .invalidCredentials(description):

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Services/AuthService.swift

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ public final class AuthService {
124124
guard let actionCodeSettings = configuration
125125
.emailLinkSignInActionCodeSettings else {
126126
throw AuthServiceError
127-
.notConfiguredActionCodeSettings
127+
.notConfiguredActionCodeSettings(
128+
"ActionCodeSettings has not been configured for `AuthConfiguration.emailLinkSignInActionCodeSettings`"
129+
)
128130
}
129131
return actionCodeSettings
130132
}
@@ -285,7 +287,7 @@ public extension AuthService {
285287
public extension AuthService {
286288
func sendEmailSignInLink(to email: String) async throws {
287289
do {
288-
let actionCodeSettings = try safeActionCodeSettings()
290+
let actionCodeSettings = try updateActionCodeSettings()
289291
try await auth.sendSignInLink(
290292
toEmail: email,
291293
actionCodeSettings: actionCodeSettings
@@ -304,10 +306,15 @@ public extension AuthService {
304306
throw AuthServiceError.invalidEmailLink
305307
}
306308
let link = url.absoluteString
307-
// TODO: - get anonymous id here and check against current user before linking accounts
308-
// put anonymous uid on link and get it back: https://github.com/firebase/FirebaseUI-iOS/blob/main/FirebaseEmailAuthUI/Sources/FUIEmailAuth.m#L822
309+
309310
if auth.isSignIn(withEmailLink: link) {
310-
let result = try await auth.signIn(withEmail: email, link: link)
311+
let anonymousUserID = CommonUtils.getQueryParamValue(from: link, paramName: "ui_auid")
312+
if shouldHandleAnonymousUpgrade, anonymousUserID == currentUser?.uid {
313+
let credential = EmailAuthProvider.credential(withEmail: email, link: link)
314+
try await handleAutoUpgradeAnonymousUser(credentials: credential)
315+
} else {
316+
let result = try await auth.signIn(withEmail: email, link: link)
317+
}
311318
updateAuthenticationState()
312319
emailLink = nil
313320
}
@@ -318,6 +325,38 @@ public extension AuthService {
318325
throw error
319326
}
320327
}
328+
329+
private func updateActionCodeSettings() throws -> ActionCodeSettings {
330+
let actionCodeSettings = try safeActionCodeSettings()
331+
guard var urlComponents = URLComponents(string: actionCodeSettings.url!.absoluteString) else {
332+
throw AuthServiceError
333+
.notConfiguredActionCodeSettings(
334+
"ActionCodeSettings.url has not been configured for `AuthConfiguration.emailLinkSignInActionCodeSettings`"
335+
)
336+
}
337+
338+
var queryItems: [URLQueryItem] = []
339+
340+
if shouldHandleAnonymousUpgrade {
341+
if let currentUser = currentUser {
342+
let anonymousUID = currentUser.uid
343+
let auidItem = URLQueryItem(name: "ui_auid", value: anonymousUID)
344+
queryItems.append(auidItem)
345+
}
346+
}
347+
348+
// We don't have config for forceSameDevice so it is set as default
349+
let forceSameDevice = "1"
350+
let sameDeviceItem = URLQueryItem(name: "ui_sd", value: forceSameDevice)
351+
queryItems.append(sameDeviceItem)
352+
353+
urlComponents.queryItems = queryItems
354+
if let finalURL = urlComponents.url {
355+
actionCodeSettings.url = finalURL
356+
}
357+
358+
return actionCodeSettings
359+
}
321360
}
322361

323362
// MARK: - Google Sign In

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Utils/CommonUtils.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,12 @@ public class CommonUtils {
4646
}
4747
return hash.map { String(format: "%02x", $0) }.joined()
4848
}
49+
50+
public static func getQueryParamValue(from urlString: String, paramName: String) -> String? {
51+
guard let urlComponents = URLComponents(string: urlString) else {
52+
return nil
53+
}
54+
55+
return urlComponents.queryItems?.first(where: { $0.name == paramName })?.value
56+
}
4957
}

0 commit comments

Comments
 (0)