🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
- https://github.com/SwiftfulThinking/SwiftfulAuthenticating
- https://github.com/SwiftfulThinking/SwiftfulAuthenticatingFirebase
SwiftfulAuthenticating
, is dependency agnostic and decoupled from Firebase. This improves testability, mockability, and allows developers to pick-and-choose their auth source.
SwiftfulAuthenticating
via SwiftfulAuthenticatingFirebase
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
Convenience methods to manage Firebase Authentication in Swift projects.
- âś… Sign In With Apple
- âś… Sign In With Google
- âś… Sign In With Phone
Task {
do {
let (userAuthInfo, isNewUser) = try await authManager.signInApple()
// User is signed in
if isNewUser {
// New user -> Create user profile in Firestore
} else {
// Existing user -> sign in
}
} catch {
// User auth failed
}
}
Sample project: https://github.com/SwiftfulThinking/SwiftfulFirebasePackagesExample
Details (Click to expand)
- File -> Swift Packages -> Add Package Dependency
- Add URL for this repository: https://github.com/SwiftfulThinking/SwiftfulFirebaseAuth.git
import SwiftfulFirebaseAuth
let authManager = AuthManager(configuration: .firebase)
// Use Mock configuration to avoid running Firebase while developing (ex. for SwiftUI Previews).
let authManager = AuthManager(configuration: .mock(.signInAndOut))
// Use Mock configurations to override settings for Previews.
// .signInAndOut (default behavior)
// .signedIn (starts signed in)
// .signedOut (user starts signed out)
#Preview {
MyView()
.environment(\.authManager, AuthManager(configuration: .mock(.signedIn)))
}
Add the Firebase SDK to your application and configure() the SDK on launch.
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
return true
}
Details (Click to expand)
Firebase docs: https://firebase.google.com/docs/auth/ios/apple
- Firebase Console -> Authentication -> Sign-in method -> Add new provider
- Xcode Project Navigator -> Target -> Signing & Capabilities -> + Capability -> Sign in with Apple (requires Apple Developer Account)
SignInWithAppleButtonView()
.frame(height: 50)
try await authManager.signInApple()
Details (Click to expand)
Firebase docs: https://firebase.google.com/docs/auth/ios/google-signin
- Firebase Console -> Authentication -> Sign-in method -> Add new provider
- Firebase Console -> Project Settings -> Your apps -> GoogleService-Info.plist
- GoogleService-Info.plist -> REVERSED_CLIENT_ID
- Xcode Project Navigator -> Target -> Info -> URL Types -> add REVERSED_CLIENT_ID as URL Schemes value
SignInWithGoogleButtonView()
.frame(height: 50)
let clientId = FirebaseApp.app()?.options.clientID
try await authManager.signInGoogle(GIDClientID: clientId)
Details (Click to expand)
Firebase docs: https://firebase.google.com/docs/auth/ios/phone-auth
- Firebase Console -> Authentication -> Sign-in method -> Add new provider
- Create an APNs Authentication Key in Apple Developer Member Center (requires Apple Developer Account)
- Certificates, Identifiers & Profiles -> New Key for Apple Push Notifications service (APNs) -> download .p8 file
- Firebase Console -> Project Settings -> Cloud Messaging -> APNs Authentication Key
- Firebase Console -> Project Settings -> Encoded App ID
- Xcode Project Navigator -> Target -> Info -> URL Types -> add Encoded App ID as URL Schemes value
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Auth.auth().setAPNSToken(deviceToken, type: .prod)
}
func application(_ application: UIApplication, didReceiveRemoteNotification notification: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if Auth.auth().canHandleNotification(notification) {
completionHandler(.noData)
return
}
}
func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
if Auth.auth().canHandle(url) {
return true
}
return false
}
- This SDK does NOT format phone numbers or provide UI for this. You must provide a string in the correct format.
- Phone numbers have to be correctly formatted, such as "+1 650-555-3434" for US numbers.
- See Firebase Docs for details about phone number implementation
- Possible resources for phone number formatting:
SignInWithPhoneButtonView()
.frame(height: 50)
try await authManager.signInPhone_Start(phoneNumber: phoneNumber)
try await authManager.signInPhone_Verify(code: code)
Details (Click to expand)
let userAuthProfile: UserAuthInfo? = authManager.currentUser.profile
let userIsSignedIn: Bool = authManager.currentUser.isSignedIn
let userId: String? = authManager.currentUser.userId
Task {
for await authInfo in authManager.$currentUser.values {
let userAuthProfile: UserAuthInfo? = authInfo.profile
let userIsSignedIn: Bool = authInfo.isSignedIn
let userId: String? = authInfo.userId
}
}
try authManager.signOut()
try await authManager.deleteAuthentication()
Open a PR! New Sign-In Methods must use Swift Concurrency (async/await).