diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt index d23af170b..6f7c09ab2 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -66,6 +66,8 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase. actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = android.sendSignInLinkToEmail(email, actionCodeSettings.toAndroid()).await().run { Unit } + actual fun isSignInWithEmailLink(link: String) = android.isSignInWithEmailLink(link) + actual suspend fun signInWithEmailAndPassword(email: String, password: String) = AuthResult(android.signInWithEmailAndPassword(email, password).await()) @@ -77,6 +79,9 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase. actual suspend fun signInWithCredential(authCredential: AuthCredential) = AuthResult(android.signInWithCredential(authCredential.android).await()) + actual suspend fun signInWithEmailLink(email: String, link: String) = + AuthResult(android.signInWithEmailLink(email, link).await()) + actual suspend fun signOut() = android.signOut() actual suspend fun updateCurrentUser(user: FirebaseUser) = android.updateCurrentUser(user.android).await().run { Unit } diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 02fcc5d9b..4e0653ab2 100644 --- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -39,7 +39,12 @@ actual object GithubAuthProvider { } actual object GoogleAuthProvider { - actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken)) + actual fun credential(idToken: String?, accessToken: String?): AuthCredential { + require(idToken != null || accessToken != null) { + "Both parameters are optional but at least one must be present." + } + return AuthCredential(com.google.firebase.auth.GoogleAuthProvider.getCredential(idToken, accessToken)) + } } actual class OAuthProvider(val android: com.google.firebase.auth.OAuthProvider) { diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt index ea9981b40..c27b137ac 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -27,10 +27,12 @@ expect class FirebaseAuth { suspend fun fetchSignInMethodsForEmail(email: String): List suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings? = null) suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) + fun isSignInWithEmailLink(link: String): Boolean suspend fun signInWithEmailAndPassword(email: String, password: String): AuthResult suspend fun signInWithCustomToken(token: String): AuthResult suspend fun signInAnonymously(): AuthResult suspend fun signInWithCredential(authCredential: AuthCredential): AuthResult + suspend fun signInWithEmailLink(email: String, link: String): AuthResult suspend fun signOut() suspend fun updateCurrentUser(user: FirebaseUser) suspend fun verifyPasswordResetCode(code: String): String @@ -67,7 +69,11 @@ data class ActionCodeSettings( val iOSBundleId: String? = null ) -data class AndroidPackageName(val packageName: String, val installIfNotAvailable: Boolean, val minimumVersion: String?) +data class AndroidPackageName( + val packageName: String, + val installIfNotAvailable: Boolean = true, + val minimumVersion: String? = null +) expect open class FirebaseAuthException : FirebaseException expect class FirebaseAuthActionCodeException : FirebaseAuthException diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index d0fcf08f0..ae23f85ab 100644 --- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -26,7 +26,7 @@ expect object GithubAuthProvider { } expect object GoogleAuthProvider { - fun credential(idToken: String, accessToken: String): AuthCredential + fun credential(idToken: String?, accessToken: String?): AuthCredential } expect class OAuthProvider constructor( diff --git a/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt index 9a94d09e9..2fe59c4c6 100644 --- a/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -103,6 +103,14 @@ class FirebaseAuthTest { assertEquals(uid, result.user!!.uid) } + @Test + fun testIsSignInWithEmailLink() { + val validLink = "http://localhost:9099/emulator/action?mode=signIn&lang=en&oobCode=_vr0QcFcxcVeLZbrcU-GpTaZiuxlHquqdC8MSy0YM_vzWCTAQgV9Jq&apiKey=fake-api-key&continueUrl=https%3A%2F%2Fexample.com%2Fsignin" + val invalidLink = "http://localhost:9099/emulator/action?mode=signIn&lang=en&&apiKey=fake-api-key&continueUrl=https%3A%2F%2Fexample.com%2Fsignin" + assertTrue(Firebase.auth.isSignInWithEmailLink(validLink)) + assertFalse(Firebase.auth.isSignInWithEmailLink(invalidLink)) + } + private suspend fun getTestUid(email: String, password: String): String { val uid = Firebase.auth.let { val user = try { diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt index 9c83e881e..96e5a152e 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -58,6 +58,8 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = ios.await { sendSignInLinkToEmail(email, actionCodeSettings.toIos(), it) }.run { Unit } + actual fun isSignInWithEmailLink(link: String) = ios.isSignInWithEmailLink(link) + actual suspend fun signInWithEmailAndPassword(email: String, password: String) = AuthResult(ios.awaitResult { signInWithEmail(email = email, password = password, completion = it) }) @@ -70,6 +72,9 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) { actual suspend fun signInWithCredential(authCredential: AuthCredential) = AuthResult(ios.awaitResult { signInWithCredential(authCredential.ios, it) }) + actual suspend fun signInWithEmailLink(email: String, link: String) = + AuthResult(ios.awaitResult { signInWithEmail(email = email, link = link, completion = it) }) + actual suspend fun signOut() = ios.throwError { signOut(it) }.run { Unit } actual suspend fun updateCurrentUser(user: FirebaseUser) = ios.await { updateCurrentUser(user.ios, it) }.run { Unit } diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 7702b0118..f20b884e1 100644 --- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -31,7 +31,11 @@ actual object GithubAuthProvider { } actual object GoogleAuthProvider { - actual fun credential(idToken: String, accessToken: String): AuthCredential = AuthCredential(FIRGoogleAuthProvider.credentialWithIDToken(idToken, accessToken)) + actual fun credential(idToken: String?, accessToken: String?): AuthCredential { + requireNotNull(idToken) { "idToken must not be null" } + requireNotNull(accessToken) { "accessToken must not be null" } + return AuthCredential(FIRGoogleAuthProvider.credentialWithIDToken(idToken, accessToken)) + } } actual class OAuthProvider(val ios: FIROAuthProvider) { @@ -80,4 +84,4 @@ actual interface PhoneVerificationProvider { actual object TwitterAuthProvider { actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(FIRTwitterAuthProvider.credentialWithToken(token, secret)) -} \ No newline at end of file +} diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt index 50f97e2c4..70d3ea304 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -53,6 +53,8 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = rethrow { js.sendSignInLinkToEmail(email, actionCodeSettings.toJson()).await() } + actual fun isSignInWithEmailLink(link: String) = rethrow { js.isSignInWithEmailLink(link) } + actual suspend fun signInWithEmailAndPassword(email: String, password: String) = rethrow { AuthResult(js.signInWithEmailAndPassword(email, password).await()) } @@ -65,6 +67,9 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { actual suspend fun signInWithCredential(authCredential: AuthCredential) = rethrow { AuthResult(js.signInWithCredential(authCredential.js).await()) } + actual suspend fun signInWithEmailLink(email: String, link: String) = + rethrow { AuthResult(js.signInWithEmailLink(email, link).await()) } + actual suspend fun signOut() = rethrow { js.signOut().await() } actual suspend fun updateCurrentUser(user: FirebaseUser) = @@ -119,6 +124,7 @@ actual class AuthTokenResult(val js: firebase.auth.IdTokenResult) { } internal fun ActionCodeSettings.toJson() = json( + "url" to url, "android" to (androidPackageName?.run { json("installApp" to installIfNotAvailable, "minimumVersion" to minimumVersion, "packageName" to packageName) } ?: undefined), "dynamicLinkDomain" to (dynamicLinkDomain ?: undefined), "handleCodeInApp" to canHandleCodeInApp, diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 0074b5704..f5f911cc1 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -29,8 +29,12 @@ actual object GithubAuthProvider { } actual object GoogleAuthProvider { - actual fun credential(idToken: String, accessToken: String): AuthCredential = - AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) + actual fun credential(idToken: String?, accessToken: String?): AuthCredential { + require(idToken != null || accessToken != null) { + "Both parameters are optional but at least one must be present." + } + return AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) + } } actual class OAuthProvider(val js: firebase.auth.OAuthProvider) { @@ -81,4 +85,4 @@ actual interface PhoneVerificationProvider { actual object TwitterAuthProvider { actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(firebase.auth.TwitterAuthProvider.credential(token, secret)) -} \ No newline at end of file +} diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index 980de9219..3485345b0 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -56,12 +56,14 @@ external object firebase { fun fetchSignInMethodsForEmail(email: String): Promise> fun sendPasswordResetEmail(email: String, actionCodeSettings: Any?): Promise fun sendSignInLinkToEmail(email: String, actionCodeSettings: Any?): Promise + fun isSignInWithEmailLink(link: String): Boolean fun signInWithEmailAndPassword(email: String, password: String): Promise fun signInWithCustomToken(token: String): Promise fun signInAnonymously(): Promise fun signInWithCredential(authCredential: AuthCredential): Promise fun signInWithPopup(provider: AuthProvider): Promise fun signInWithRedirect(provider: AuthProvider): Promise + fun signInWithEmailLink(email: String, link: String): Promise fun getRedirectResult(): Promise fun signOut(): Promise fun updateCurrentUser(user: user.User?): Promise