AWS の開始方法

iOS アプリケーションを構築する

AWS Amplify を使用してシンプルな iOS アプリケーションを作成する

モジュール 3: 認証を追加する

このモジュールでは、Amplify CLI とライブラリを使用して、認証を設定し、アプリに追加します。

はじめに

次に追加する機能はユーザー認証です。このモジュールでは、マネージド型のユーザー ID プロバイダーである Amazon Cognito を利用して、Amplify CLI とライブラリでユーザーを認証する方法を学びます。

また、Cognito でホストされるユーザーインターフェイスを使用してユーザー認証フロー全体を表示する方法を学び、ユーザーが数行のコードでサインアップ、サインイン、パスワードのリセットを行えるようにします。

「ホストされたユーザーインタフェイス」を使用するということは、アプリケーションで Cognito のウェブページを利用して、サインインとサインアップのユーザーインタフェイスフローを行うということです。アプリケーションのユーザーは、Cognito でホストされるウェブページにリダイレクトされ、サインイン後にアプリにリダイレクトされます。当然、Cognito と Amplify もネイティブ UI をサポートします。カスタム認証 UI の詳細については、こちらのワークショップ手順を参照してください。

学習内容

  • 認証サービスを作成してデプロイする
  • Cognito でホストされる UI 認証を含めるように iOS アプリを設定する

主要な概念

Amplify ライブラリ – Amplify ライブラリにより、ウェブまたはモバイルアプリケーションから AWS のサービスを操作できます。

認証 – ソフトウェアでは、認証は、認証サービスまたは API を使用してユーザーの ID を確認および管理するプロセスです。

 所要時間

10 分

 使用するサービス

実装

  • 認証サービスを作成するには、ターミナルを開いてこのコマンドを実行します

    amplify add auth
    
    ? Do you want to use the default authentication and security configuration? Select Default configuration with Social Provider and press enter
    ? How do you want users to be able to sign in? Select the default Username and press enter
    ? Do you want to configure advanced settings? Select the default No, I am done and press enter
    ? What domain name prefix do you want to use? Select the default and press enter
    Enter your redirect signin URI: type gettingstarted:// and press enter
    ? Do you want to add another redirect signin URI? Select the default N and press enter
    Enter your redirect signout URI: type gettingstarted:// and press enter
    ? Do you want to add another redirect signout URI? Select the default N and press enter
    ? Select the social providers you want to configure for your user pool: do not select any provider and press enter

    設定が成功すると、次のメッセージが表示されます (リソースの正確な名前は異なります)。

    Successfully added resource iosgettingstartedfc5a4717 locally
  • 認証サービスがローカルで設定されたので、認証サービスをクラウドにデプロイできます。ターミナルのプロジェクトディレクトリでこのコマンドを実行します

    amplify push
    
    # press Y when asked to continue

    しばらくすると、次のメッセージが表示されます。

    ✔ All resources are updated in the cloud
    
    Hosted UI Endpoint: https://iosgettingstarted-dev.auth.eu-central-1.amazoncognito.com/
    Test Your Hosted UI Endpoint: https://iosgettingstarted-dev.auth.eu-central-1.amazoncognito.com/login?response_type=code&client_id=1234567890&redirect_uri=gettingstarted://
  • コードに進む前に、Amplify 認証ライブラリをプロジェクトの依存関係に追加します。Podfile を開き、AmplifyPlugins/AWSCognitoAuthPlugin という行を追加するか、次のファイル全体をコピーして貼り付けます。

    # you need at least version 13.0 for this tutorial, more recent versions are valid too
    platform :ios, '13.0'
    
    target 'getting started' do
      # Comment the next line if you don't want to use dynamic frameworks
      use_frameworks!
    
      # Pods for getting started
      pod 'Amplify', '~> 1.0'                             # required amplify dependency
      pod 'Amplify/Tools', '~> 1.0'                       # allows to call amplify CLI from within Xcode
    
      pod 'AmplifyPlugins/AWSCognitoAuthPlugin', '~> 1.0' # support for Cognito user authentication
    
    end

    ターミナルでこのコマンドを実行します

    pod install

    このコマンドが完了するまでに数秒かかります。次のように表示されます (実際のバージョン番号は異なる場合があります)。

    Analyzing dependencies
    Downloading dependencies
    Installing AWSAuthCore (2.14.1)
    Installing AWSCognitoIdentityProvider (2.14.1)
    Installing AWSCognitoIdentityProviderASF (1.0.1)
    Installing AWSCore (2.14.1)
    Installing AWSMobileClient (2.14.1)
    Installing AWSPluginsCore (1.0.4)
    Installing AmplifyPlugins (1.0.4)
    Generating Pods project
    Integrating client project
    Pod installation complete! There are 3 dependencies from the Podfile and 8 total pods installed.
  • Xcode に戻り、バックエンド.swift ファイルを開きます。バックエンドクラスで、

    • AmplifyPlugins のインポートステートメントを追加します
    • 前のセクションで追加した Amplify 初期化コードに行を追加します

    コードのブロックが完成すると、以下のようになります。

    // at the top of the file
    import AmplifyPlugins
    
    private init () {
      // initialize amplify
      do {
         try Amplify.add(plugin: AWSCognitoAuthPlugin())
         try Amplify.configure()
         print("Initialized Amplify")
      } catch {
         print("Could not initialize Amplify: \(error)")
      }
    }

    すべてが想定どおりに動作することを検証するには、プロジェクトをビルドします。[Product (製品)] メニューをクリックして [Build (構築)] を選択するか、または ⌘B を押します。操作エラーがないようにします。

  • 残りのコードを変更すると、ユーザーのステータスを追跡できます (サインインの有無)。また、ユーザーがサインインしていない場合に、サインイン/サインアップのユーザーインターフェイスをトリガーします。 

    a.サインインとサインアウトのコードを追加バックエンドクラスの任意の場所に次の 3 つのメソッドを追加します。

     

    // MARK: - User Authentication
    
    // signin with Cognito web user interface
    public func signIn() {
    
        _ = Amplify.Auth.signInWithWebUI(presentationAnchor: UIApplication.shared.windows.first!) { result in
            switch result {
            case .success(_):
                print("Sign in succeeded")
            case .failure(let error):
                print("Sign in failed \(error)")
            }
        }
    }
    
    // signout
    public func signOut() {
    
        _ = Amplify.Auth.signOut() { (result) in
            switch result {
            case .success:
                print("Successfully signed out")
            case .failure(let error):
                print("Sign out failed with error \(error)")
            }
        }
    }
    
    // change our internal state, this triggers an UI update on the main thread
    func updateUserData(withSignInStatus status : Bool) {
        DispatchQueue.main.async() {
            let userData : UserData = .shared
            userData.isSignedIn = status
        }
    }

    b.認証ハブのリスナーを追加

    認証ステータスの変更を追跡するには、Amplify によって送信される認証イベントにサブスクライブするためのコードを追加します。ハブは Backend.init() メソッドで初期化します。

    認証イベントを受信したら、updateUserData() メソッドを呼び出します。このメソッドによって UserData オブジェクトの同期が維持されます。UserData.isSignedIn プロパティは @Published です。つまり、値が変更されるとユーザーインタフェイスが自動的に更新されます。 

    また、アプリケーションの起動時に以前の認証ステータスを確認するコードも追加します。アプリケーションが起動すると、Cognito セッションがすでに存在するかどうかを確認し、それに応じて UI を更新します。

    Backend.init() で、Amplify の初期化後に次のコードを追加します

    // in private init() function
    // listen to auth events.
    // see https://github.com/aws-amplify/amplify-ios/blob/master/Amplify/Categories/Auth/Models/AuthEventName.swift
    _ = Amplify.Hub.listen(to: .auth) { (payload) in
    
        switch payload.eventName {
    
        case HubPayload.EventName.Auth.signedIn:
            print("==HUB== User signed In, update UI")
            self.updateUserData(withSignInStatus: true)
    
        case HubPayload.EventName.Auth.signedOut:
            print("==HUB== User signed Out, update UI")
            self.updateUserData(withSignInStatus: false)
    
        case HubPayload.EventName.Auth.sessionExpired:
            print("==HUB== Session expired, show sign in UI")
            self.updateUserData(withSignInStatus: false)
    
        default:
            //print("==HUB== \(payload)")
            break
        }
    }
     
    // let's check if user is signedIn or not
     _ = Amplify.Auth.fetchAuthSession { (result) in
         do {
             let session = try result.get()
                    
    // let's update UserData and the UI
         self.updateUserData(withSignInStatus: session.isSignedIn)
                    
         } catch {
              print("Fetch auth session failed with error - \(error)")
        }
    }    

    c.ユーザーインターフェイスコードを更新する

    コードの最後の変更はユーザーインターフェイスに関連しています。ContentView に ZStack を追加します。UserData.isSignedIn の値に応じて UI には SigninButton ビューまたはメインリストビューが表示されます。

    ContentView.swift を開き、ContentView struct 内で次のように本文を置き換えます

    var body: some View {
    
        ZStack {
            if (userData.isSignedIn) {
                NavigationView {
                    List {
                        ForEach(userData.notes) { note in
                            ListRow(note: note)
                        }
                    }
                    .navigationBarTitle(Text("Notes"))
                    .navigationBarItems(leading: SignOutButton())
                }
            } else {
                SignInButton()
            }
        }
    }

    同じファイルで、次のように SignInButton ビューと SignOutButton ビューを追加します

    struct SignInButton: View {
        var body: some View {
            Button(action: { Backend.shared.signIn() }){
                HStack {
                    Image(systemName: "person.fill")
                        .scaleEffect(1.5)
                        .padding()
                    Text("Sign In")
                        .font(.largeTitle)
                }
                .padding()
                .foregroundColor(.white)
                .background(Color.green)
                .cornerRadius(30)
            }
        }
    }
    
    struct SignOutButton : View {
        var body: some View {
            Button(action: { Backend.shared.signOut() }) {
                    Text("Sign Out")
            }
        }
    }

    すべてが想定どおりに動作することを検証するには、プロジェクトをビルドします。[Product (製品)] メニューをクリックして [Build (構築)] を選択するか、または ⌘B を押します。操作エラーがないようにします。

    d.Info.plist を更新

    最後に、Cognito でホストされるユーザーインターフェイスによって提供されるウェブ認証シーケンスの最後でアプリが起動されるか確認する必要があります。gettingstarted URI スキームをアプリの Info.plist ファイルに追加します。

    Xcode で Info.plist ファイルを選択し、右クリックしてから、[Open As (As を開く)]、[Source Code (ソースコード)] の順に選択します

    次の <key> 要素と <array> 要素を 一番上の <dict> 要素のに追加します。

    <plist version="1.0">
    
        <dict>
        <!-- YOUR OTHER PLIST ENTRIES HERE -->
    
        <!-- ADD AN ENTRY TO CFBundleURLTypes for Cognito Auth -->
        <!-- IF YOU DO NOT HAVE CFBundleURLTypes, YOU CAN COPY THE WHOLE BLOCK BELOW -->
        <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>gettingstarted</string>
                </array>
            </dict>
        </array>
    
        <!-- ... -->
        </dict>

    e.ビルドとテスト

    すべてが想定どおりに動作することを検証するには、プロジェクトをビルドします。[Product (製品)] メニューをクリックして [Run (実行)] を選択するか、または ⌘R を押します。操作エラーがないようにします。アプリは [Sign In (サインイン)] ボタンをクリックすると起動します。

    サインアップの全体的な流れは次のとおりです。

まとめ

これで、数行のコードでユーザー認証がアプリに追加されました。 次のモジュールでは、アプリに API を追加します。

このモジュールは役に立ちましたか?

GraphQL API とデータベースを追加する