プログラムを書こう!

実務や自作アプリ開発で習得した役に立つソフトウェア技術情報を発信するブログ

SwiftのGoogleDrive APIでサインインを行う。

この記事は2018年07月23日に投稿しました。

f:id:paveway:20190914064630j:plain

目次

  1. はじめに
  2. サインイン処理
  3. おわりに

作って学ぶ iPhoneアプリの教科書 【Swift4&Xcode 9対応】 ~人工知能アプリを作ってみよう! ~(特典PDF付き)

作って学ぶ iPhoneアプリの教科書 【Swift4&Xcode 9対応】 ~人工知能アプリを作ってみよう! ~(特典PDF付き)

1. はじめに

こんにちは、iOSのエディタアプリPWEditorの開発者の二俣です。
今回はGoogleDrive APIでサインインしてみます。

目次へ

2. サインイン処理

Google Drive APIのサインイン処理は、いろいろ実装しないといけないです。
一部SwiftでGoogleDrive APIの使用する準備を行う paveway.hatenablog.com と重複するコードになっています。

AppDelegate.swfit

import AppAuth

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    /// GoogleDriveサービスドライブ
    let googleDriveServiceDrive = GTLRDriveService()
    
    /// 認証オブジェクト
    var googleDriveAuthorization: GTMAppAuthFetcherAuthorization?

    /// 現在の認証フローオブジェクト
    var googleDriveCurrentAuthorizationFlow: OIDAuthorizationFlowSession?
    
    /**
     GTM認証結果を設定します。

     - Parameter authorization: 認証結果
     */
    func setGtmAuthorization(_ authorization: GTMAppAuthFetcherAuthorization?) {
        if googleDriveAuthorization == authorization {
            // 認証済みのオブジェクトの場合、処理を終了します。
            return
        }
        
        // クロージャーで返却されたオブジェクトをインスタンス変数に保存します。
        googleDriveAuthorization = authorization
        googleDriveServiceDrive.authorizer = googleDriveAuthorization
                
        GoogleDriveサインイン状態を変更する。
        googleDriveSignInStateChanged()
    }
    
    /**
     GoogleDriveサインイン状態を変更します。
     */
    func googleDriveSignInStateChanged() {
        // GoogleDriveのサインイン状態を保存します。
        saveGoogleDriveSignInState()
    }
    
    /**
     GoogleDriveのサインイン状態を保存します。
     */
    func saveGoogleDriveSignInState() {
        let keychainItemName = ”<キーチェーンに保存しておく任意キー名>"
        if let authorization = googleDriveAuthorization, authorization.canAuthorize() {
            // サインイン状態の場合
            GTMAppAuthFetcherAuthorization.save(authorization, toKeychainForName: keychainItemName)

        } else {
            // 未サインイン状態の場合
            GTMAppAuthFetcherAuthorization.removeFromKeychain(forName: keychainItemName)
        }
    }
}

認証処理を行いたいViewControllerなどに以下のメソッドを用意してください。

2016年08月22日にGoogleからアナウンスModernizing OAuth interactions in Native Apps for Better Usability and Securityがあり、以前は認められていたWebView経由での認証が、2017年04月20日から禁止になりました。

代わりにブラウザ経由の認証に変更になりました。

SampleViewController.swft

class SignInViewController: UIViewController {

    let appDelegate = UIApplication.shared.delegate as! AppDelegate

    /**
     ブラウザ経由のGoogleDrive認証を行います。
     参考: https://github.com/google/GTMAppAuth
           http://qiita.com/doki_k/items/fc317dafd714967809cd
     */
    func authGoogleDriveInBrowser() {
        // issuerのURLを生成します。
        guard let issuer = URL(string: "https://accounts.google.com") else {
            // URLが生成できない場合、処理を終了します。
            // 念のためのチェックです。
            // 必要に応じてエラー処理を行っていください。
            return
        }

        // リダイレクト先URLを生成します。
        // <GoogleDriveのクライアントID>には、"SwiftでGoogleDrive APIを使用する準備を行う"で取得した
        // クライアントIDを設定してください。
        let redirectUriString = String(format: "com.googleusercontent.apps.%@:/oauthredirect", ”<GoogleDriveのクライアントID>”)
        guard let redirectURI = URL(string: redirectUriString) else {
            // URLが生成できない場合、処理を終了します。
            // 念のためのチェックです。
            // 必要に応じてエラー処理を行っていください。
            return
        }

        // エンドポイントを検索します。
        OIDAuthorizationService.discoverConfiguration(forIssuer: issuer) { configuration, error in
            guard let configuration = configuration else {
            appDelegate.setGtmAuthorization(nil)
            return
        }

        // 認証要求オブジェクトを作成します。
        let request = OIDAuthorizationRequest.init(
            configuration: configuration,
            clientId:<GoogleDriveのクライアントID>”,
            scopes: ["https://www.googleapis.com/auth/drive"],
            redirectURL: redirectURI,
            responseType: OIDResponseTypeCode,
            additionalParameters: nil)

        appDelegate.googleDriveCurrentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: self) { authState, error in
                if let authState = authState {
                    let gauthorization: GTMAppAuthFetcherAuthorization = GTMAppAuthFetcherAuthorization(authState: authState)
                    appDelegate.setGtmAuthorization(gauthorization)

                } else {
                    appDelegate.setGtmAuthorization(nil)
                }

                if let authorizer = appDelegate.googleDriveServiceDrive.authorizer, let canAuth = authorizer.canAuthorize, canAuth {
                    // サインイン済みの場合
                    // 必要な処理を記述してください。
                }
            }
        }
    }
}

目次へ

おわりに

GoogleDrive APIのサインイン方式は、何回か変更されその都度対応せざる得ないため、めんどくさいです。
しかもDropbox APIに比べて手順が煩雑で、サンプルがないとよくわかりません。

ストアカ

iOSアプリ開発デザインパターン入門 (技術の泉シリーズ(NextPublishing))

iOSアプリ開発デザインパターン入門 (技術の泉シリーズ(NextPublishing))

紹介している一部の記事のコードはGitlabで公開しています。
興味のある方は覗いてみてください。

目次へ


私が勤務しているニューラルでは、主に組み込み系ソフトの開発を行っております。
弊社製品のハイブリッドOS Bi-OSは高い技術力を評価されており、特に制御系や通信系を得意としています。
私自身はiOSモバイルアプリウィンドウズアプリを得意としております。
ソフトウェア開発に関して相談などございましたら、お気軽にご連絡ください。

また一緒に働きたい技術者の方も随時募集中です。
興味がありましたらご連絡ください。

EMAIL : info-nr@newral.co.jp / m-futamata@newral.co.jp
TEL : 042-523-3663
FAX : 042-540-1688

目次へ