diff --git a/.changeset/fair-beds-wash.md b/.changeset/fair-beds-wash.md new file mode 100644 index 00000000..01c9cb4c --- /dev/null +++ b/.changeset/fair-beds-wash.md @@ -0,0 +1,5 @@ +--- +"@capacitor-firebase/authentication": minor +--- + +feat(ios): support Game Center Sign-In diff --git a/packages/authentication/README.md b/packages/authentication/README.md index dce6bf5e..98ac2a2f 100644 --- a/packages/authentication/README.md +++ b/packages/authentication/README.md @@ -36,6 +36,7 @@ The further installation steps depend on the selected authentication method: - [Apple Sign-In](/packages/authentication/docs/setup-apple.md) - [Facebook Sign-In](/packages/authentication/docs/setup-facebook.md) +- [Game Center Sign-In](/packages/authentication/docs/setup-game-center.md) - [GitHub Sign-In](/packages/authentication/docs/setup-github.md) - [Google Sign-In](/packages/authentication/docs/setup-google.md) - [Microsoft Sign-In](/packages/authentication/docs/setup-microsoft.md) @@ -62,7 +63,7 @@ These configuration values are available: | Prop | Type | Description | Default | Since | | -------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- | | **`skipNativeAuth`** | boolean | Configure whether the plugin should skip the native authentication. Only needed if you want to use the Firebase JavaScript SDK. This configuration option has no effect on Firebase account linking. **Note that the plugin may behave differently across the platforms.** Only available for Android and iOS. | false | 0.1.0 | -| **`providers`** | string[] | Configure the providers that should be loaded by the plugin. Possible values: `["apple.com", "facebook.com", "github.com", "google.com", "microsoft.com", "playgames.google.com", "twitter.com", "yahoo.com", "phone"]` Only available for Android and iOS. | [] | 0.1.0 | +| **`providers`** | string[] | Configure the providers that should be loaded by the plugin. Possible values: `["apple.com", "facebook.com", "gc.apple.com", "github.com", "google.com", "microsoft.com", "playgames.google.com", "twitter.com", "yahoo.com", "phone"]` Only available for Android and iOS. | [] | 0.1.0 | ### Examples @@ -214,6 +215,11 @@ const signInWithApple = async () => { return result.user; }; +const signInWithGameCenter = async () => { + const result = await FirebaseAuthentication.signInWithGameCenter(); + return result.user; +}; + const signInWithCustomToken = async () => { const result = await FirebaseAuthentication.signInWithCustomToken({ token: '1234', @@ -383,6 +389,7 @@ const useEmulator = async () => { * [`signInWithMicrosoft(...)`](#signinwithmicrosoft) * [`signInWithPhoneNumber(...)`](#signinwithphonenumber) * [`signInWithPlayGames(...)`](#signinwithplaygames) +* [`signInWithGameCenter(...)`](#signinwithgamecenter) * [`signInWithTwitter(...)`](#signinwithtwitter) * [`signInWithYahoo(...)`](#signinwithyahoo) * [`signOut()`](#signout) @@ -1061,6 +1068,25 @@ Starts the Play Games sign-in flow. -------------------- +### signInWithGameCenter(...) + +```typescript +signInWithGameCenter(options?: SignInWithOAuthOptions | SignInOptions | undefined) => Promise +``` + +Starts the Game Center sign-in flow. + +| Param | Type | +| ------------- | ----------------------------------------------------------------------------------------------------------------------- | +| **`options`** | SignInWithOAuthOptions \| SignInOptions | + +**Returns:** Promise<SignInResult> + +**Since:** 1.3.0 + +-------------------- + + ### signInWithTwitter(...) ```typescript @@ -1547,18 +1573,19 @@ Callback to receive the user's sign-in state change notifications. #### ProviderId -| Members | Value | -| ---------------- | ----------------------------------- | -| **`APPLE`** | 'apple.com' | -| **`FACEBOOK`** | 'facebook.com' | -| **`GITHUB`** | 'github.com' | -| **`GOOGLE`** | 'google.com' | -| **`MICROSOFT`** | 'microsoft.com' | -| **`PLAY_GAMES`** | 'playgames.google.com' | -| **`TWITTER`** | 'twitter.com' | -| **`YAHOO`** | 'yahoo.com' | -| **`PASSWORD`** | 'password' | -| **`PHONE`** | 'phone' | +| Members | Value | +| ----------------- | ----------------------------------- | +| **`APPLE`** | 'apple.com' | +| **`FACEBOOK`** | 'facebook.com' | +| **`GAME_CENTER`** | 'gc.apple.com' | +| **`GITHUB`** | 'github.com' | +| **`GOOGLE`** | 'google.com' | +| **`MICROSOFT`** | 'microsoft.com' | +| **`PLAY_GAMES`** | 'playgames.google.com' | +| **`TWITTER`** | 'twitter.com' | +| **`YAHOO`** | 'yahoo.com' | +| **`PASSWORD`** | 'password' | +| **`PHONE`** | 'phone' | diff --git a/packages/authentication/android/src/main/java/io/capawesome/capacitorjs/plugins/firebase/authentication/FirebaseAuthenticationPlugin.java b/packages/authentication/android/src/main/java/io/capawesome/capacitorjs/plugins/firebase/authentication/FirebaseAuthenticationPlugin.java index 7c83b7e2..37e461be 100644 --- a/packages/authentication/android/src/main/java/io/capawesome/capacitorjs/plugins/firebase/authentication/FirebaseAuthenticationPlugin.java +++ b/packages/authentication/android/src/main/java/io/capawesome/capacitorjs/plugins/firebase/authentication/FirebaseAuthenticationPlugin.java @@ -380,6 +380,11 @@ public void signInWithApple(PluginCall call) { } } + @PluginMethod + public void signInWithGameCenter(PluginCall call) { + call.reject("Not available on Android."); + } + @PluginMethod public void signInWithCustomToken(PluginCall call) { try { diff --git a/packages/authentication/docs/setup-game-center.md b/packages/authentication/docs/setup-game-center.md new file mode 100644 index 00000000..75ed8ef2 --- /dev/null +++ b/packages/authentication/docs/setup-game-center.md @@ -0,0 +1,15 @@ +# Set up authentication using Game Center Sign-In + +## Android + +🚧 Currently not supported. + +## iOS + +1. Add `gc.apple.com` to the `providers` [configuration](https://github.com/capawesome-team/capacitor-firebase/tree/main/packages/authentication#configuration) array. +1. Make sure you register your Apple app with Firebase. This means entering your app's bundle ID in the registration section along with additional optional information such as App Store ID and Team ID, etc. This will be required for securely verifying the audience of the user's Game Center credential before completing sign-in. +1. Enable Game Center as a sign-in provider for your Firebase project. + +## Web + +🚧 Currently not supported. diff --git a/packages/authentication/ios/Plugin.xcodeproj/project.pbxproj b/packages/authentication/ios/Plugin.xcodeproj/project.pbxproj index b4b78749..14cbba5c 100644 --- a/packages/authentication/ios/Plugin.xcodeproj/project.pbxproj +++ b/packages/authentication/ios/Plugin.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ 7CD588F22688B5A4002BDF65 /* OAuthProviderHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CD588F12688B5A4002BDF65 /* OAuthProviderHandler.swift */; }; 7CD588F42688B6A7002BDF65 /* AppleAuthProviderHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CD588F32688B6A7002BDF65 /* AppleAuthProviderHandler.swift */; }; 7CE70B7526D1AA220025E915 /* FacebookAuthProviderHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CE70B7426D1AA220025E915 /* FacebookAuthProviderHandler.swift */; }; + D8872AD52913A78800CF6CED /* GameCenterAuthProviderHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8872AD42913A78800CF6CED /* GameCenterAuthProviderHandler.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -57,6 +58,7 @@ 7CE70B7426D1AA220025E915 /* FacebookAuthProviderHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacebookAuthProviderHandler.swift; sourceTree = ""; }; 91781294A431A2A7CC6EB714 /* Pods-Plugin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Plugin.release.xcconfig"; path = "Pods/Target Support Files/Pods-Plugin/Pods-Plugin.release.xcconfig"; sourceTree = ""; }; 96ED1B6440D6672E406C8D19 /* Pods-PluginTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PluginTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.debug.xcconfig"; sourceTree = ""; }; + D8872AD42913A78800CF6CED /* GameCenterAuthProviderHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterAuthProviderHandler.swift; sourceTree = ""; }; F65BB2953ECE002E1EF3E424 /* Pods-PluginTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PluginTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PluginTests/Pods-PluginTests.release.xcconfig"; sourceTree = ""; }; F6753A823D3815DB436415E3 /* Pods_PluginTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PluginTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -131,6 +133,7 @@ isa = PBXGroup; children = ( 7CD588F32688B6A7002BDF65 /* AppleAuthProviderHandler.swift */, + D8872AD42913A78800CF6CED /* GameCenterAuthProviderHandler.swift */, 7CE70B7426D1AA220025E915 /* FacebookAuthProviderHandler.swift */, 7C8E530726656FD100FF4B87 /* GoogleAuthProviderHandler.swift */, 7CD588F12688B5A4002BDF65 /* OAuthProviderHandler.swift */, @@ -368,6 +371,7 @@ buildActionMask = 2147483647; files = ( 7CE70B7526D1AA220025E915 /* FacebookAuthProviderHandler.swift in Sources */, + D8872AD52913A78800CF6CED /* GameCenterAuthProviderHandler.swift in Sources */, 7C8E530826656FD100FF4B87 /* GoogleAuthProviderHandler.swift in Sources */, 7C3D92CA26D3CC62000C0B29 /* PhoneAuthProviderHandler.swift in Sources */, 7CD588F02688B4EF002BDF65 /* FirebaseAuthenticationHelper.swift in Sources */, diff --git a/packages/authentication/ios/Plugin/FirebaseAuthentication.swift b/packages/authentication/ios/Plugin/FirebaseAuthentication.swift index eae21f79..73295906 100644 --- a/packages/authentication/ios/Plugin/FirebaseAuthentication.swift +++ b/packages/authentication/ios/Plugin/FirebaseAuthentication.swift @@ -10,6 +10,7 @@ public typealias AuthStateChangedObserver = () -> Void private let plugin: FirebaseAuthenticationPlugin private let config: FirebaseAuthenticationConfig private var appleAuthProviderHandler: AppleAuthProviderHandler? + private var gameCenterAuthProviderHandler: GameCenterAuthProviderHandler? private var facebookAuthProviderHandler: FacebookAuthProviderHandler? private var googleAuthProviderHandler: GoogleAuthProviderHandler? private var oAuthProviderHandler: OAuthProviderHandler? @@ -168,6 +169,11 @@ public typealias AuthStateChangedObserver = () -> Void self.facebookAuthProviderHandler?.link(call: call) } + @objc func linkWithGameCenter(_ call: CAPPluginCall) { + self.savedCall = call + self.gameCenterAuthProviderHandler?.link(call: call) + } + @objc func linkWithGithub(_ call: CAPPluginCall) { self.savedCall = call self.oAuthProviderHandler?.link(call: call, providerId: ProviderId.gitHub) @@ -333,6 +339,11 @@ public typealias AuthStateChangedObserver = () -> Void self.facebookAuthProviderHandler?.signIn(call: call) } + @objc func signInWithGameCenter(_ call: CAPPluginCall) { + self.savedCall = call + self.gameCenterAuthProviderHandler?.signIn(call: call) + } + @objc func signInWithGithub(_ call: CAPPluginCall) { self.savedCall = call self.oAuthProviderHandler?.signIn(call: call, providerId: ProviderId.gitHub) @@ -480,6 +491,9 @@ public typealias AuthStateChangedObserver = () -> Void if config.providers.contains(ProviderId.apple) { self.appleAuthProviderHandler = AppleAuthProviderHandler(self) } + if config.providers.contains(ProviderId.gameCenter) { + self.gameCenterAuthProviderHandler = GameCenterAuthProviderHandler(self) + } if config.providers.contains(ProviderId.facebook) { self.facebookAuthProviderHandler = FacebookAuthProviderHandler(self) } diff --git a/packages/authentication/ios/Plugin/FirebaseAuthenticationHelper.swift b/packages/authentication/ios/Plugin/FirebaseAuthenticationHelper.swift index 7f12c1b4..7042157e 100644 --- a/packages/authentication/ios/Plugin/FirebaseAuthenticationHelper.swift +++ b/packages/authentication/ios/Plugin/FirebaseAuthenticationHelper.swift @@ -5,6 +5,7 @@ import FirebaseAuth public struct ProviderId { static let apple = "apple.com" + static let gameCenter = "gc.apple.com" static let facebook = "facebook.com" static let gitHub = "github.com" static let google = "google.com" diff --git a/packages/authentication/ios/Plugin/FirebaseAuthenticationPlugin.m b/packages/authentication/ios/Plugin/FirebaseAuthenticationPlugin.m index e32673d8..cdb8b1db 100644 --- a/packages/authentication/ios/Plugin/FirebaseAuthenticationPlugin.m +++ b/packages/authentication/ios/Plugin/FirebaseAuthenticationPlugin.m @@ -15,6 +15,7 @@ CAP_PLUGIN_METHOD(linkWithEmailAndPassword, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(linkWithEmailLink, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(linkWithFacebook, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(linkWithGameCenter, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(linkWithGithub, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(linkWithGoogle, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(linkWithMicrosoft, CAPPluginReturnPromise); @@ -33,6 +34,7 @@ CAP_PLUGIN_METHOD(signInWithEmailAndPassword, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(signInWithEmailLink, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(signInWithFacebook, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(signInWithGameCenter, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(signInWithGithub, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(signInWithGoogle, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(signInWithMicrosoft, CAPPluginReturnPromise); diff --git a/packages/authentication/ios/Plugin/FirebaseAuthenticationPlugin.swift b/packages/authentication/ios/Plugin/FirebaseAuthenticationPlugin.swift index 66e65ce4..6bc7bfdc 100644 --- a/packages/authentication/ios/Plugin/FirebaseAuthenticationPlugin.swift +++ b/packages/authentication/ios/Plugin/FirebaseAuthenticationPlugin.swift @@ -135,6 +135,10 @@ public class FirebaseAuthenticationPlugin: CAPPlugin { implementation?.linkWithFacebook(call) } + @objc func linkWithGameCenter(_ call: CAPPluginCall) { + implementation?.linkWithGameCenter(call) + } + @objc func linkWithGithub(_ call: CAPPluginCall) { implementation?.linkWithGithub(call) } @@ -291,6 +295,10 @@ public class FirebaseAuthenticationPlugin: CAPPlugin { implementation?.signInWithFacebook(call) } + @objc func signInWithGameCenter(_ call: CAPPluginCall) { + implementation?.signInWithGameCenter(call) + } + @objc func signInWithGithub(_ call: CAPPluginCall) { implementation?.signInWithGithub(call) } diff --git a/packages/authentication/ios/Plugin/Handlers/GameCenterAuthProviderHandler.swift b/packages/authentication/ios/Plugin/Handlers/GameCenterAuthProviderHandler.swift new file mode 100644 index 00000000..8323de6a --- /dev/null +++ b/packages/authentication/ios/Plugin/Handlers/GameCenterAuthProviderHandler.swift @@ -0,0 +1,66 @@ +import Foundation +import Capacitor +import FirebaseCore +import FirebaseAuth +import AuthenticationServices +import GameKit + +class GameCenterAuthProviderHandler: NSObject { + public let errorGetCredentialFailed = "getCredential failed." + private var pluginImplementation: FirebaseAuthentication + + init(_ pluginImplementation: FirebaseAuthentication) { + self.pluginImplementation = pluginImplementation + super.init() + } + + func signIn(call: CAPPluginCall) { + startSignInWithGameCenterFlow(call, isLink: false) + } + + func link(call: CAPPluginCall) { + startSignInWithGameCenterFlow(call, isLink: true) + } + + func startSignInWithGameCenterFlow(_ call: CAPPluginCall, isLink: Bool) { + GKLocalPlayer.local.authenticateHandler = { viewController, error in + if let viewController = viewController { + DispatchQueue.main.async { + self.pluginImplementation.getPlugin().bridge?.viewController?.present(viewController, animated: true, completion: nil) + } + return + } + if error != nil { + if isLink { + self.pluginImplementation.handleFailedLink(message: nil, error: error) + } else { + self.pluginImplementation.handleFailedSignIn(message: nil, error: error) + } + return + } + GameCenterAuthProvider.getCredential { (credential, error) in + if error != nil { + if isLink { + self.pluginImplementation.handleFailedLink(message: nil, error: error) + } else { + self.pluginImplementation.handleFailedSignIn(message: nil, error: error) + } + return + } + guard let credential = credential else { + if isLink { + self.pluginImplementation.handleFailedLink(message: self.errorGetCredentialFailed, error: nil) + } else { + self.pluginImplementation.handleFailedSignIn(message: self.errorGetCredentialFailed, error: nil) + } + return + } + if isLink { + self.pluginImplementation.handleSuccessfulLink(credential: credential, idToken: nil, nonce: nil, accessToken: nil) + } else { + self.pluginImplementation.handleSuccessfulSignIn(credential: credential, idToken: nil, nonce: nil, accessToken: nil) + } + } + } + } +} diff --git a/packages/authentication/src/definitions.ts b/packages/authentication/src/definitions.ts index 9ec5ccc6..7460df9f 100644 --- a/packages/authentication/src/definitions.ts +++ b/packages/authentication/src/definitions.ts @@ -27,7 +27,7 @@ declare module '@capacitor/cli' { /** * Configure the providers that should be loaded by the plugin. * - * Possible values: `["apple.com", "facebook.com", "github.com", "google.com", "microsoft.com", "playgames.google.com", "twitter.com", "yahoo.com", "phone"]` + * Possible values: `["apple.com", "facebook.com", "gc.apple.com", "github.com", "google.com", "microsoft.com", "playgames.google.com", "twitter.com", "yahoo.com", "phone"]` * * Only available for Android and iOS. * @@ -314,6 +314,14 @@ export interface FirebaseAuthenticationPlugin { signInWithPlayGames( options?: SignInOptions | SignInWithOAuthOptions, ): Promise; + /** + * Starts the Game Center sign-in flow. + * + * @since 1.3.0 + */ + signInWithGameCenter( + options?: SignInOptions | SignInWithOAuthOptions, + ): Promise; /** * Starts the Twitter sign-in flow. * @@ -1050,6 +1058,7 @@ export interface ActionCodeSettings { export enum ProviderId { APPLE = 'apple.com', FACEBOOK = 'facebook.com', + GAME_CENTER = 'gc.apple.com', GITHUB = 'github.com', GOOGLE = 'google.com', MICROSOFT = 'microsoft.com', diff --git a/packages/authentication/src/web.ts b/packages/authentication/src/web.ts index 8adfb0fa..812f2874 100644 --- a/packages/authentication/src/web.ts +++ b/packages/authentication/src/web.ts @@ -437,6 +437,10 @@ export class FirebaseAuthenticationWeb throw new Error('Not available on web.'); } + public async signInWithGameCenter(): Promise { + throw new Error('Not available on web.'); + } + public async signInWithTwitter( options?: SignInOptions, ): Promise {