1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SwiftUI】FirebaseAuthのApple, Googleログインを簡単に実装しよう

Posted at

Firebase Authを使ってアプリを開発するとき、アプリごとに毎回同じようなコードを書いていませんか?
今回、Firebase Auth関連の実装を簡単にするライブラリ、FirebaseAuthEasierを作成したので、ご紹介します!!
ぜひStarしてね!⭐️

これを使うと、以下のイメージのように2行コードを書くだけで簡単にSign in with AppleとSign in with Googleを実装できます!これで開発爆速化間違いなし!

image.png

この記事では、このFirebaseAuthEasierの使い方やセットアップ方法をご紹介します!
以下、Firebaseのセットアップはできている前提で、Firebase Authの準備からセットアップ方法を解説します!

1. Firebase Authの準備

1-1. Firebaseコンソールでの準備

FirebaseのコンソールからAuthenticationタブを開き、始めるをクリックしましょう
名称未設定 1.png

1-2. Sign in with Appleの有効化

まず、ログインプロバイダ一覧からAppleを選択します
名称未設定 2.png

ポップアップが表示されるので、有効にするのトグルをONにして、保存をクリックします
名称未設定 3.png

以下のスクリーンショットのようにAppleが追加されていれば完了です!
image.png

1-3. Sign in with Googleの有効化

またログインプロバイダの一覧画面を開き、今度はGoogleを選択します
名称未設定 4.png

表示されたポップアップの有効にするのトグルをONにして、必要な情報を埋めてから保存をクリックします。
ここでは、Sign in with Googleで表示されるこのアプリの名前と、サポートメールを設定する必要があります。
名称未設定 5.png

保存できると、以下のようなポップアップが出ることがあります!これは、Sign in with Googleを新しく設定したことで、既に作成さているGoogleService-Info.plistが古くなってしまったので、更新してね!というポップアップです!
指示に従って、既にセットアップしたGoogleService-Info.plistを、新しいものに置き換えましょう!
image.png

最終的にこのように、AppleとGoogleのプロバイダが設定済みになっていれば、Firebaseコンソールでの作業は終了です!
image.png

2. Xcodeでのセットアップ

次に、XcodeでFirebaseAuthEasierを使うための準備をしていきましょう!

2-1.パッケージをインストール

まずはパッケージをインストールしましょう

XcodeのFileタブから、Add Package Dependencies...を選択しましょう
名称未設定 6.png

するとこのような画面になるので、
↓こちらのURLをコピペして、FirebaseAuthEasierを探し、見つかったらAdd Packageを押しましょう!

https://github.com/sugijotaro/FirebaseAuthEasier.git

名称未設定 7.png

すると、どのTargetにPackageを追加するか聞かれるので、対象のアプリを選択し、Add Packageを選択しましょう
名称未設定 8.png
これでFirebaseAuthEasierのパッケージを追加することができました!

2-2. Sign in with Appleを設定

アプリ内でSign in with Appleを使用するために、設定が必要です!

まず、以下の画像の通りに選択していき、Signing & Capabilitiesタブの中の+ Capabilityを押しましょう!
名称未設定 10.jpg

するとポップアップが出るので、ここからSign in with Appleを検索し、出てきたCapabilityをドラッグ&ドロップでアプリに組み込みましょう!
ezgif-8262574c5f28fe.gif

これでSign in with Appleのセットアップは完了です

2-3. Sign in with Googleを設定

アプリ内でSign in with Googleを使用するために、設定が必要です!

まず、以下の画像のように、アプリ内にあるGoogleService-Info.plistを開き、その中のREVERSED_CLIENT_IDValueを探します
見つけたら、それをコピーしましょう!
image.png

次に、そのコピーした値をペーストする場所を探しましょう。
以下の画像を参考に、InfoタブのURL Typesの中身を開き、+ボタンを押してください。
名称未設定 12.jpg

するとこのような画面になるので、右側のURL Schemesの部分に先ほどコピーした値をペーストしてください!
image.png

これでSign in with Googleのセットアップも完了です!

3. FirebaseAuthEasierを使う

セットアップお疲れ様でした!
ここまでできれば、あとは超簡単です!

3-1. 超簡単に使おう!

ログイン画面を使用したいところに以下のようにコードを追加します

import SwiftUI
+ import FirebaseAuthEasier

struct ContentView: View {
    
    var body: some View {
+        FirebaseAuthView()
    }
}

すると、こんな感じで認証画面が出てきてくれます!嬉しい!
image.png
自動的にアプリのアイコンとアプリ名を持ってきて、表示してくれるよ!

3-2. カスタマイズして使おう!

ここまでで「一瞬でFirebase Authが使える!」ことが分かったと思いますが、
「自分のアプリに合わせて、もっと見た目や動きをこだわりたい」
そんな方のために、FirebaseAuthEasierのカスタマイズ術をまとめました!

3-2-1. 日本語で表示してほしい

まずはカスタマイズというより基本的な使い方ですが、、
「Sign in with Apple」などの文言を日本語などローカライズした言語で表示することができます!

PROJECTを選択し、InfoのなかのLocalizationsJapaneseなど任意の言語に設定すれば、日本語の表示にできます!

image.png

イメージ

simulator_screenshot_7A7551EB-80F9-42A4-B49A-625C18DE9748.png

3-2-2. サインイン画面をカスタマイズ

FirebaseAuthViewのイニシャライザ引数を活用すれば、見た目も機能もあなた好みに仕上げられます。

主要なカスタマイズ例:

サインインプロバイダの種類をカスタマイズ

FirebaseAuthView(providers: [.apple]) //Appleのみ
FirebaseAuthView(providers: [.google]) //Googleのみ
FirebaseAuthView(providers: [.google, .apple]) //並び順を変える

ボタンの文言を「サインアップ」や「続ける」に

FirebaseAuthView(labelType: .signIn) //サインイン
FirebaseAuthView(labelType: .signUp) //登録
FirebaseAuthView(labelType: .continue) //続ける

利用規約・プライバシーポリシーを表示したい

FirebaseAuthView(
    termsOfServiceURL: URL(string: "https://example.com/terms")!, //利用規約
    privacyPolicyURL: URL(string: "https://example.com/privacy")! //プライバシーポリシー
)

画面上部を自分のデザインに差し替えたい

FirebaseAuthView {
    VStack {
        Text("MyAppへようこそ!")
        Image(systemName: "sparkles")
    }
}

サインイン開始や完了時にイベントを仕込みたい

FirebaseAuthView(
    onSignInStart: { provider in
        print("サインイン開始: \(provider)")
    },
    didSignIn: { result in
        switch result {
        case .success(let authData):
            // ログイン成功時の処理
        case .failure(let error):
            // エラー処理
        }
    }
)

いろいろまとめて使いたい時はこう!

import SwiftUI
import FirebaseAuthEasier

struct ContentView: View {
    var body: some View {
        FirebaseAuthView(
            providers: [.apple, .google],
            labelType: .signIn,
            termsOfServiceURL: URL(string: "apple.com")!,
            privacyPolicyURL: URL(string: "apple.com")!,
            onSignInStart: { provider in
                print("Sign-in started with provider: \(provider)")
            },
            didSignIn: { result in
                switch result {
                case .success(let authResult):
                    print("Sign-in successful")
                case .failure(let error):
                    print("Sign-in failed: \(error.localizedDescription)")
                }
            }
        ) {
            VStack {
                Image(systemName: "person.circle")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("ようこそ!")
            }
        }
    }
}

image.png

3-2-3. 認証状態に合わせて画面を切り替える

「ログインしている人はホーム画面、未ログインなら認証画面」といった切り替えもとても簡単です。
FirebaseAuthEasierライブラリで提供しているFirebaseAuthServiceを使えば、下記のような実装もすぐにできます。

import SwiftUI
import FirebaseAuth
import FirebaseAuthEasier

class AuthViewModel: ObservableObject {
    @Published var currentUser: FirebaseAuth.User? = nil
    private let authService = FirebaseAuthService()
    private var handle: AuthStateDidChangeListenerHandle?

    init() {
        handle = authService.addAuthStateDidChangeListener { [weak self] _, user in
            self?.currentUser = user
        }
    }
    deinit {
        if let handle = handle {
            authService.removeAuthStateDidChangeListener(handle)
        }
    }

    func signOut() {
        authService.signOut { _ in }
    }
}

struct ContentView: View {
    @StateObject private var viewModel = AuthViewModel()

    var body: some View {
        if viewModel.currentUser == nil {
            FirebaseAuthView()
        } else {
            VStack {
                Text("ログイン中です")
                Button("サインアウト") {
                    viewModel.signOut()
                }
            }
        }
    }
}

これで、ログインしていなければFirebaseAuthView()を表示して、ログインされていれば他のViewを表示する実装ができます!

3-2-4. ボタン単体での利用・デザインも自由自在

「既存画面にサインインボタンだけ置きたい」「独自UIと並べたい」という場合は、SignInButtonコンポーネントの出番です!

import SwiftUI
import FirebaseAuthEasier

SignInButton(
    provider: .apple,
    buttonStyle: .black,
    labelStyle: .titleAndIcon,
    labelType: .signIn,
    cornerStyle: .radius(12),
    hasBorder: true
) {
    // ボタン押下時処理
}

色・角丸・アイコン・ラベル、すべて好みに合わせて調整できます。

3-2-5. 直接APIでさらに細かい制御も可能

「匿名認証も使いたい」「再認証やアカウント削除もしたい」といった時は、FirebaseAuthServiceのメソッドを直接呼び出して活用できます。

let authService = FirebaseAuthService()

// 匿名サインイン
authService.signInAnonymously { result in
    // 結果に応じた処理
}

// サインアウト
authService.signOut { result in
    // 完了時の処理
}

その他詳細な使い方は、sampleプロジェクトを見てみてください!

より詳細なFirebaseAuthServiceのメソッド(例と使い方)

認証状態リスナーの追加・削除

ユーザーのサインイン・サインアウト状態を監視したいとき

// 追加
let handle = authService.addAuthStateDidChangeListener { auth, user in
    if let user = user {
        print("Signed in as \(user.uid)")
    } else {
        print("Signed out")
    }
}
// 削除
authService.removeAuthStateDidChangeListener(handle)

Appleサインイン & Appleアカウントのリンク

// Appleサインイン
authService.startSignInWithApple { result in
    switch result {
    case .success(let authResult):
        print("Appleサインイン成功: \(authResult.user.uid)")
    case .failure(let error):
        print("Appleサインイン失敗: \(error)")
    }
}

// Appleアカウントを既存ユーザーにリンク
authService.startLinkWithApple { result in
    switch result {
    case .success(let authResult):
        print("Appleアカウントのリンク成功: \(authResult.user.uid)")
    case .failure(let error):
        print("Appleアカウントのリンク失敗: \(error)")
    }
}

Googleサインイン & Googleアカウントのリンク

Google認証の処理を行う場合、startSignInWithGoogleやstartLinkWithGoogleのpresentingViewControllerには、RootViewControllerを指定する必要があります。

// Googleサインイン
if let rootVC = getRootViewController() {
    authService.startSignInWithGoogle(presentingViewController: rootVC) { result in
        switch result {
        case .success(let authResult):
            print("Googleサインイン成功: \(authResult.user.uid)")
        case .failure(let error):
            print("Googleサインイン失敗: \(error)")
        }
    }
}

// Googleアカウントを既存ユーザーにリンク
if let rootVC = getRootViewController() {
    authService.startLinkWithGoogle(presentingViewController: rootVC) { result in
        switch result {
        case .success(let authResult):
            print("Googleアカウントのリンク成功: \(authResult.user.uid)")
        case .failure(let error):
            print("Googleアカウントのリンク失敗: \(error)")
        }
    }
}


// rootViewControllerの取得方法
func getRootViewController() -> UIViewController? {
    let scenes = UIApplication.shared.connectedScenes
    let windowScene = scenes.first as? UIWindowScene
    return windowScene?.keyWindow?.rootViewController
}

このようにして、Googleサインインやリンク処理時は
「rootViewControllerを取得 → presentingViewControllerとして渡す」
という実装を行ってください。

再認証フロー(認証し直しが必要な操作時)

// 例:アカウント削除時や機密操作の直前に
authService.reauthenticateIfNeeded(
    presentingViewController: self,
    for: { completion in
        // ここに本来の操作を書く(例:user.deleteなど)
        completion(.success(()))
    },
    completion: { result in
        switch result {
        case .success:
            print("再認証→操作完了")
        case .failure(let error):
            print("再認証失敗: \(error)")
        }
    }
)

アカウント削除(再認証付き)

authService.deleteAccount(
    presentingViewController: self
) { result in
    switch result {
    case .success:
        print("アカウント削除完了")
    case .failure(let error):
        print("削除失敗: \(error)")
    }
}

認証プロバイダのリンク(汎用)

let credential: AuthCredential = // 任意のプロバイダーのcredential
authService.linkCurrentUserWithCredential(credential) { result in
    switch result {
    case .success(let authResult):
        print("リンク成功")
    case .failure(let error):
        print("リンク失敗: \(error)")
    }
}

任意の認証情報でサインイン

let credential: AuthCredential = // 任意のcredential
authService.signInWithCredential(credential) { result in
    switch result {
    case .success(let authResult):
        print("サインイン成功")
    case .failure(let error):
        print("サインイン失敗: \(error)")
    }
}

現在のユーザーが持つプロバイダIDの一覧取得

if let user = Auth.auth().currentUser {
    let providerIDs = FirebaseAuthService.providerIDs(for: user)
    print(providerIDs) // [.apple, .google] など
}

そのほか、必要に応じてAPIを追加予定!
「このAPIほしい」「こういうケース対応したい」等リクエストはぜひGitHub Issueまでどうぞ!

まとめ

FirebaseAuthEasierなら、「とりあえず導入」から「細かく作り込む」まで、どちらも超ラク&超早いです!
SwiftUIらしい使い方ができるので、ぜひ使ってみてください!

もし「ここをもっとこうしたい」「このオプションって?」という質問やリクエストがあれば、
ぜひGitHubリポジトリまでどうぞ!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?