最近では、iOSアプリの開発をするエンジニアも増えてきてますが、
それに比例してアプリの開発をサポートするソリューションも増えてきました。その中の一つとしてFirebaseというMBaaSソリューションがあります。
これはGoogleがリリースしたもので、iOSアプリ、Androidアプリに限らずWebのバックエンドの処理をサポートしてくれるツールです。
ここでは、その中の1つであるFirebase Authenticationというツールを紹介します。
このツールはユーザー、パスワードを入力するログイン実装機能をサポートしてくれます。それだけではなく、ここでは扱いませんがソーシャルログインなどGoogleアカウントでログインする実装などもできたりします。
メールアドレスの認証の場合は、以下にメールアドレスとパスワードが保存される。
そして、それ以外でgoogleやtwitterなど使いたい場合は、以下のように選択できる。
これにより認証したときに、各プロパイダの認可サーバへアクセスしてあったら、リダイレクトして認証する仕組み
まずは実装イメージをしてみます。
- SwiftUIでログイン画面(メールアドレスとパスワード)を実装する
- 入力したメールアドレスとパスワードの情報をFirebaseに渡す
- すでにアカウントがあれば認証を、なければ新規登録としてアカウント作成する
- ログイン完了画面、失敗画面を表示する
ですね。
これに則って実装していきたいと思います。
Contents
ログイン画面を実装する
まず簡単にViewにメールアドレスやパスワードの入力欄を作成します。
Firebase AuthenticationはFirebaseをcocoapodsに入れてライブラリをインストーすることで、
そのパッケージ内にFirebaseAuthが入っている。
import SwiftUI import FirebaseAuth struct NewLogin: View { @State public var mail:String = "" @State public var password:String = "" @State public var errorMessage:String = "" var body: some View { VStack(spacing: 30){ // メールアドレス TextField("メールアドレスを入力してください",text: $mail) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // パスワード SecureField("パスワードを入力してください",text:$password) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // 認証 Button( action:{ if(self.mail != ""){ self.errorMessage = "メールアドレスが入力されていません" } else if(self.password != ""){ self.errorMessage = "パスワードが入力されていません" } else { // 認証する処理 } }, label:{ Text("ログインする") }) } } }
上記のように、普通にViewに入力欄を作成して、ボタンを実装し、
入力されていなかったらエラーメッセージを出して認証処理しないようになっている。
Firebase Authenticationで新規会員登録する
import SwiftUI import FirebaseAuth struct NewLogin: View { @State public var mail:String = "" @State public var password:String = "" @State public var errorMessage:String = "" var body: some View { VStack(spacing: 30){ // メールアドレス TextField("メールアドレスを入力してください",text: $mail) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // パスワード SecureField("パスワードを入力してください",text:$password) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // 認証 Button( action:{ if(self.mail == ""){ self.errorMessage = "メールアドレスが入力されていません" } else if(self.password == ""){ self.errorMessage = "パスワードが入力されていません" } else { Auth.auth().createUser(withEmail: self.mail, password: self.password) { authResult, error in print(authResult) } } }, label:{ Text("新規会員登録する") }) } } }
新規会員登録では、上のAuthの処理がそれにあたります。新規会員登録ボタンをクリックすると追加処理です。
Auth.auth().createUser(withEmail: self.mail, password: self.password) { authResult, error in print(authResult) }
上記処理が走ると成功した場合、以下のようにFirebaseにメールアドレスとパスワードの会員情報が連携されます。
Firebase Authenticationで認証する
さて先程作成したログイン情報を用いてログインしてみます。
import SwiftUI import FirebaseAuth struct NewLogin: View { @State public var mail:String = "" @State public var password:String = "" @State public var errorMessage:String = "" var body: some View { VStack(spacing: 30){ // メールアドレス TextField("メールアドレスを入力してください",text: $mail) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // パスワード SecureField("パスワードを入力してください",text:$password) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // 認証 Button( action:{ if(self.mail == ""){ self.errorMessage = "メールアドレスが入力されていません" } else if(self.password == ""){ self.errorMessage = "パスワードが入力されていません" } else { Auth.auth().signIn(withEmail: self.mail, password: self.password) { authResult, error in if authResult?.user != nil { // ログイン成功処理 print("success") } else { // ログイン失敗処理 if let error = error as NSError?, let errorCode = AuthErrorCode(rawValue: error.code) { switch errorCode { case .invalidEmail: self.errorMessage = "メールアドレスの形式が正しくありません" case .userNotFound, .wrongPassword: self.errorMessage = "メールアドレス、またはパスワードが間違っています" case .userDisabled: self.errorMessage = "このユーザーアカウントは無効化されています" default: self.errorMessage = error.domain } } } } } }, label:{ Text("ログインする") }) } } }
先程アカウント登録で入力したメールアドレスとパスワードを入力して、
successとlogで表示されればログイン成功です!
Firebase Authenticationからアカウントの削除をする
次にアカウントの削除をしてみます。
→ よく皆さんのアプリなど使っていて削除するのは、自分がログイン状態でマイページから削除などがあるかと思います。
なので記載するコードとしては以下のようになります。
https://firebase.google.com/docs/auth/ios/manage-users?hl=ja
let user = Auth.auth().currentUser user?.delete { error in if let error = error { // An error happened. } else { // Account deleted. } }
そしてログインしている状態で削除することになるので、
アカウント作成はしていると想定して、
メールアドレスとパスワード入力して「ログインする」ボタンをクリックして、
その後「アカウント削除」ボタンをクリックしてFirebaseからアカウントが削除されていることを確認します。
import SwiftUI import FirebaseAuth struct NewLogin: View { @State public var mail:String = "" @State public var password:String = "" @State public var errorMessage:String = "" @State public var stateLogin:Bool = false // ログイン状態 var body: some View { VStack(spacing: 30){ // メールアドレス TextField("メールアドレスを入力してください",text: $mail) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // パスワード SecureField("パスワードを入力してください",text:$password) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // 認証 Button( action:{ if(self.mail == ""){ self.errorMessage = "メールアドレスが入力されていません" } else if(self.password == ""){ self.errorMessage = "パスワードが入力されていません" } else { Auth.auth().signIn(withEmail: self.mail, password: self.password) { authResult, error in if authResult?.user != nil { // ログイン成功処理 print("success") self.stateLogin = true } else { // ログイン失敗処理 if let error = error as NSError?, let errorCode = AuthErrorCode(rawValue: error.code) { switch errorCode { case .invalidEmail: self.errorMessage = "メールアドレスの形式が正しくありません" case .userNotFound, .wrongPassword: self.errorMessage = "メールアドレス、またはパスワードが間違っています" case .userDisabled: self.errorMessage = "このユーザーアカウントは無効化されています" default: self.errorMessage = error.domain } } } } } }, label:{ Text("ログインする") }) // アカウント削除 Button( action:{ let user = Auth.auth().currentUser user?.delete { error in if let error = error { // An error happened. } else { print("削除成功") } } }, label:{ Text("アカウント削除する") }) } } }
Firebaseからアカウントが削除されているのが確認できると思います!
成功しました!
他のViewに行ってもログイン状態保持?
ログイン状態は別のViewに遷移しても保持されるのかを検証。
ログインしている場合は以下でcurrentUserという値がFirebaseのUIDが入るようになっている。
なので別Viewでこの値が取れるかどうかで検証。
import SwiftUI import FirebaseAuth struct NewLogin: View { @State public var mail:String = "" @State public var password:String = "" @State public var errorMessage:String = "" @State public var stateLogin:Bool = false // ログイン状態 var body: some View { VStack(spacing: 30){ if(self.stateLogin){ LoginRetain() } else { // メールアドレス TextField("メールアドレスを入力してください",text: $mail) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // パスワード SecureField("パスワードを入力してください",text:$password) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() // 認証 Button( action:{ if(self.mail == ""){ self.errorMessage = "メールアドレスが入力されていません" } else if(self.password == ""){ self.errorMessage = "パスワードが入力されていません" } else { Auth.auth().signIn(withEmail: self.mail, password: self.password) { authResult, error in if authResult?.user != nil { // ログイン成功処理 print("success") self.stateLogin = true } else { // ログイン失敗処理 if let error = error as NSError?, let errorCode = AuthErrorCode(rawValue: error.code) { switch errorCode { case .invalidEmail: self.errorMessage = "メールアドレスの形式が正しくありません" case .userNotFound, .wrongPassword: self.errorMessage = "メールアドレス、またはパスワードが間違っています" case .userDisabled: self.errorMessage = "このユーザーアカウントは無効化されています" default: self.errorMessage = error.domain } } } } } }, label:{ Text("ログインする") }) } } } } struct LoginRetain:View{ var body: some View { Text("Login完了") Button( action:{ let user = Auth.auth().currentUser var _ = print(user) }, label:{ Text("状態保持テスト") }) } }
Firebaseのヘルプには以下のようにありました。
''currentUser を使用することでも、現在ログインしているユーザーを取得できます。ユーザーがログインしていない場合、currentUser は nil です。''
参照
そのためLoginRetainというViewを作成して、currentUserが取得できるかどうかをログで確認します。
ログインするボタンを押してログインできると、LoginRetainが表示され、さらに状態保持テストボタンをクリックしてcurrentUserがログで取得できているかを確認します。
実行すると、ログで取得できているのが確認できるかと思います。
別Viewに遷移してもFirebase上でログイン状態の保持をしてくれていました。
ユーザーごとにUID発行
ユーザーが登録すると上のFirebase Authenticationの管理画面に情報が表示されるが、
そこでユーザーごとに個別のUIDを発行してくれる。
これはGoogleアカウントでのログインなどのソーシャルログインで実装した場合もUIDが発行されるので、
このIDを用いて様々な開発をアプリ内で行うことができる。
UIDを発行してくれるのもメリットの一つですね!
Authenticationには2種類存在する。
1つ目はカスタマイズが可能な、Firebase Authenticationそのまま。
2つ目はUIのカスタマイズができない、Firebase Authentication UI
どっちを使うかはその時々で選択する必要があるが、
アプリの独自性を出すだったりすると、カスタマイズ性の富んだ2つ目を利用するのがいい。
Googleアカウントでログインできるように実装
以下で扱ってます。 続きを見る
【SwiftUI】SwiftUIでFirebase Authenticationでプロパイダ認証を実装する(ソーシャルログイン)