Skip to content

Commit

Permalink
feat(authentication): support Game Center Sign-In (#235)
Browse files Browse the repository at this point in the history
Co-authored-by: Mike Solomon <mikesol@Mikes-MacBook-Pro.local>
Co-authored-by: Robin Genz <mail@robingenz.dev>
  • Loading branch information
3 people authored Nov 10, 2022
1 parent 9c66a04 commit fcb0f25
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/fair-beds-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@capacitor-firebase/authentication": minor
---

feat(ios): support Game Center Sign-In
53 changes: 40 additions & 13 deletions packages/authentication/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -62,7 +63,7 @@ These configuration values are available:
| Prop | Type | Description | Default | Since |
| -------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
| **`skipNativeAuth`** | <code>boolean</code> | 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. | <code>false</code> | 0.1.0 |
| **`providers`** | <code>string[]</code> | 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. | <code>[]</code> | 0.1.0 |
| **`providers`** | <code>string[]</code> | 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. | <code>[]</code> | 0.1.0 |

### Examples

Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -383,6 +389,7 @@ const useEmulator = async () => {
* [`signInWithMicrosoft(...)`](#signinwithmicrosoft)
* [`signInWithPhoneNumber(...)`](#signinwithphonenumber)
* [`signInWithPlayGames(...)`](#signinwithplaygames)
* [`signInWithGameCenter(...)`](#signinwithgamecenter)
* [`signInWithTwitter(...)`](#signinwithtwitter)
* [`signInWithYahoo(...)`](#signinwithyahoo)
* [`signOut()`](#signout)
Expand Down Expand Up @@ -1061,6 +1068,25 @@ Starts the Play Games sign-in flow.
--------------------


### signInWithGameCenter(...)

```typescript
signInWithGameCenter(options?: SignInWithOAuthOptions | SignInOptions | undefined) => Promise<SignInResult>
```

Starts the Game Center sign-in flow.

| Param | Type |
| ------------- | ----------------------------------------------------------------------------------------------------------------------- |
| **`options`** | <code><a href="#signinwithoauthoptions">SignInWithOAuthOptions</a> \| <a href="#signinoptions">SignInOptions</a></code> |

**Returns:** <code>Promise&lt;<a href="#signinresult">SignInResult</a>&gt;</code>

**Since:** 1.3.0

--------------------


### signInWithTwitter(...)

```typescript
Expand Down Expand Up @@ -1547,18 +1573,19 @@ Callback to receive the user's sign-in state change notifications.

#### ProviderId

| Members | Value |
| ---------------- | ----------------------------------- |
| **`APPLE`** | <code>'apple.com'</code> |
| **`FACEBOOK`** | <code>'facebook.com'</code> |
| **`GITHUB`** | <code>'github.com'</code> |
| **`GOOGLE`** | <code>'google.com'</code> |
| **`MICROSOFT`** | <code>'microsoft.com'</code> |
| **`PLAY_GAMES`** | <code>'playgames.google.com'</code> |
| **`TWITTER`** | <code>'twitter.com'</code> |
| **`YAHOO`** | <code>'yahoo.com'</code> |
| **`PASSWORD`** | <code>'password'</code> |
| **`PHONE`** | <code>'phone'</code> |
| Members | Value |
| ----------------- | ----------------------------------- |
| **`APPLE`** | <code>'apple.com'</code> |
| **`FACEBOOK`** | <code>'facebook.com'</code> |
| **`GAME_CENTER`** | <code>'gc.apple.com'</code> |
| **`GITHUB`** | <code>'github.com'</code> |
| **`GOOGLE`** | <code>'google.com'</code> |
| **`MICROSOFT`** | <code>'microsoft.com'</code> |
| **`PLAY_GAMES`** | <code>'playgames.google.com'</code> |
| **`TWITTER`** | <code>'twitter.com'</code> |
| **`YAHOO`** | <code>'yahoo.com'</code> |
| **`PASSWORD`** | <code>'password'</code> |
| **`PHONE`** | <code>'phone'</code> |

</docgen-api>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
15 changes: 15 additions & 0 deletions packages/authentication/docs/setup-game-center.md
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 4 additions & 0 deletions packages/authentication/ios/Plugin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -57,6 +58,7 @@
7CE70B7426D1AA220025E915 /* FacebookAuthProviderHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacebookAuthProviderHandler.swift; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
D8872AD42913A78800CF6CED /* GameCenterAuthProviderHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterAuthProviderHandler.swift; sourceTree = "<group>"; };
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 = "<group>"; };
F6753A823D3815DB436415E3 /* Pods_PluginTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PluginTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -131,6 +133,7 @@
isa = PBXGroup;
children = (
7CD588F32688B6A7002BDF65 /* AppleAuthProviderHandler.swift */,
D8872AD42913A78800CF6CED /* GameCenterAuthProviderHandler.swift */,
7CE70B7426D1AA220025E915 /* FacebookAuthProviderHandler.swift */,
7C8E530726656FD100FF4B87 /* GoogleAuthProviderHandler.swift */,
7CD588F12688B5A4002BDF65 /* OAuthProviderHandler.swift */,
Expand Down Expand Up @@ -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 */,
Expand Down
14 changes: 14 additions & 0 deletions packages/authentication/ios/Plugin/FirebaseAuthentication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
}
}
11 changes: 10 additions & 1 deletion packages/authentication/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -314,6 +314,14 @@ export interface FirebaseAuthenticationPlugin {
signInWithPlayGames(
options?: SignInOptions | SignInWithOAuthOptions,
): Promise<SignInResult>;
/**
* Starts the Game Center sign-in flow.
*
* @since 1.3.0
*/
signInWithGameCenter(
options?: SignInOptions | SignInWithOAuthOptions,
): Promise<SignInResult>;
/**
* Starts the Twitter sign-in flow.
*
Expand Down Expand Up @@ -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',
Expand Down
4 changes: 4 additions & 0 deletions packages/authentication/src/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ export class FirebaseAuthenticationWeb
throw new Error('Not available on web.');
}

public async signInWithGameCenter(): Promise<SignInResult> {
throw new Error('Not available on web.');
}

public async signInWithTwitter(
options?: SignInOptions,
): Promise<SignInResult> {
Expand Down

0 comments on commit fcb0f25

Please sign in to comment.