Angular と Firebase
Angular も Firebase も Google が提供する人気のライブラリ・サービスです。
Angular の開発で Firebase をバックエンドに用いる場合、Firebaseのライブラリをそのまま使うのではなく、Angularから利用するFirebaseに特化した AngularFire というライブラリを使います。
AngularFire は、Angular のチームが開発している公式のライブラリです。
npm の @angular/fire と angularfire2
いろいろとネット上でサンプルを見ていたら、npm install
で @angular/fire
と angularfire2
という2つのライブラリが見られますが、新しいのは @angular/fire の方みたいなのでこちらを利用します。
angularfire2
をインストールして使っているサンプルは、新しいほうに置き換えればそのまま使えるはずです。
サンプル
以下、angularfire2 で Authentication(認証管理) を使うサンプルアプリを作ってみます。
SNS認証(Google) と メールアドレスとパスワードによる認証、匿名認証をそれぞれ試します。また匿名認証のユーザーをアップグレードして認証する方法も試します。
環境
サンプルプログラムの動作確認環境は以下の通りです。
- Angular CLI: 7.0.6
- Node: 10.13.0
- OS: win32 x64
- Angular: 7.0.4
angular プロジェクトを作る
まずは、@angular/cli
をインストールしてプロジェクトを作成します。
$ npm install -g @angular/cli
適当なパスで適当にプロジェクトを作成します。質問には適当に答えておきます。
$ ng new my-app
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
これでひな型となるプロジェクトが作成されました。
必要なパッケージのインストール
作成したプロジェクトのディレクトリに移動し、firebase
と @angular/fire
のパッケージをインストールします。
$ npm install firebase @angular/fire --save
Firebaseプロジェクトを作成する
Firebaseのコンソールから新しいプロジェクトを追加します。
プロジェクト名の設定等は適宜行ってください。ここでは、angularfire-test という名前でプロジェクトを作成しました。
プロジェクトの管理画面に入って、設定値を取得します。画面の [\</>] をクリックすると Web から利用する場合の設定値が取得できます。
configの設定内容をAngularの環境設定ファイルにコピーして使います。src/app/enviroment.ts
に次のように設定してください。
export const environment = {
production: false,
firebase: {
apiKey: "xxxxxx-xxxxxxxxxxxxxxxx-xxx",
authDomain: "angularfire-test-xxxx.firebaseapp.com",
databaseURL: "https://angularfire-test-xxxxx.firebaseio.com",
projectId: "angularfire-test-xxxxx",
storageBucket: "angularfire-test-xxxxx.appspot.com",
messagingSenderId: "1234567890"
}
};
angularからこの設定を参照してモジュールを初期化して使っていきます。
Firebase Authentication を使ってみる
ログイン方法を設定
まずはコンソールにログインし、開発メニューの中にある Authentication を開きます。[ログイン方法を設定] ボタンからこのプロジェクトで許可するログイン方法を設定していきます。
デフォルトだとすべてのログイン方法が無効になっています。今回利用する “メール / パスワード”, “Google”, “匿名” を有効にします。
これでFirebase側の初期設定は完了です。Angular側の実装に移ります。
コンポーネントの作成
ログイン機能を管理するコンポーネントを作成します。
$ ng g component Login
Angular app.module.ts の編集
まずは app.module.ts の @NgModule
にインポートを追加します。以下のように追加してください。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';
import { environment } from '../environments/environment';
import { AngularFireModule } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { LoginComponent } from './login/login.component';
@NgModule({
declarations: [
AppComponent,
LoginComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule, // バインド用
AngularFireModule.initializeApp(environment.firebase), // angularfireの設定
AngularFireAuthModule, // angularfireのAuth用モジュール
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
コメント行が追加した箇所で、あと必要なimport文が追加されています。これで後は各コンポーネントでコンストラクタから使えるようになります。
先ほど作成した Login
コンポーネントは cli で自動で追加されています。
app.component.html を次のように書き換えます。
<app-login></app-login>
ここまでで ng serve
コマンドで起動して動作を確認すると、”login works!” と表示されるはずです。login.component.html の初期状態の内容です。
Loginコンポーネントの編集
では Loginコンポーネントの実装に移ります。
login.component.ts
import { Component, OnInit } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import * as firebase from 'firebase/app';
import { Observable } from 'rxjs';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
user: Observable<firebase.User>;
email: string;
password: string;
constructor(private angularFireAuth: AngularFireAuth) { }
ngOnInit() {
// 認証状態の変更を監視しておく
this.user = this.angularFireAuth.authState;
this.user.subscribe(u => console.log(u.providerData))
}
// ログアウト
async logout() {
this.angularFireAuth.auth.signOut();
}
// Google認証によるログイン
async loginWithGoogle() {
const provider = new firebase.auth.GoogleAuthProvider();
const credential = await this.angularFireAuth.auth.signInWithPopup(provider);
}
// 匿名認証
async loginAnonymously() {
const credential = await this.angularFireAuth.auth.signInAnonymously();
}
// メールアドレスとパスワード
async loginWithEmailAndPassword() {
try {
// ユーザーの登録
const credential = await this.angularFireAuth.auth.createUserAndRetrieveDataWithEmailAndPassword(this.email, this.password);
} catch (error) {
if (error.code='auth/email-already-in-use') {
// すでに使われている場合は、ログインに切り替える
await this.angularFireAuth.auth.signInWithEmailAndPassword(this.email, this.password);
}
console.log(error);
} finally {
this.email = '';
this.password = '';
}
}
// 匿名ユーザーをグーグル認証でアップグレード
async upgradeAnonymouosWithGoogle() {
const provider = new firebase.auth.GoogleAuthProvider();
const credential = await this.angularFireAuth.auth.currentUser.linkWithPopup(provider);
}
}
まず認証用コードの実装ですが、authState
で認証状態を監視します。変更があれば受け取って画面の状態を制御するために使っています。
ログアウトですが、これは signOut
メソッドを呼び出すだけなので簡単です。
次に Google認証です。これも簡単で、プロバイダーを使って signInWithXxx
メソッドを呼び出すだけです。今回は popup ですが、redirect のメソッドもあります。認証フローを使い分けることができます。
匿名認証は書いてあるとおり、1行で実装できます。
メールアドレスとパスワードの認証はユーザーを新規で作成しています。作成に失敗して、すでにメールアドレスが使われている場合は、ログインに切り替えて再度実行しています。このあたりは画面ごと分けてしまうほうがわかりやすいかもですが、ここではひとまとめにしています。
最後に匿名認証のユーザーをGoogle認証に更新しています。匿名認証はログインが出来ないので、1度認証情報を失うと再び認証してデータを弄るということができないため、何かしらの認証情報と紐づけて更新する必要があります(アプリの仕様にもよりますが)。ここではGoogle認証で更新しています。
なお、すでに登録済のメールアドレスがある状態で、そのメールアドレスに紐づくGoogle認証を行うと、アカウントがGoogle認証で更新され、メールアドレスとパスワードによる認証ができなくなります。これはFirebaseの設定で、同一のメールアドレスを持つアカウントを異なる認証プロパイダで複数持てなくなっているためです。ログイン方法の設定で変更可能です。
次に画面のコードです。
login.component.html
<div *ngIf="(user | async) || {} as user">
<div *ngIf="!user.uid;">
<!-- 認証されていない場合 -->
<div>
<button (click)="loginWithGoogle()">Login With Google</button>
</div>
<div>
<input type="email" [(ngModel)]="email" placeholder="email">
<input type="password" [(ngModel)]="password" placeholder="password">
<button (click)="loginWithEmailAndPassword()">Login With Email</button>
</div>
<div>
<button (click)="loginAnonymously()">Login Anonymously</button>
</div>
</div>
<div *ngIf="user.isAnonymous">
<!-- 匿名ユーザーの場合 -->
<button (click)="upgradeAnonymouosWithGoogle()">Google認証に更新</button>
</div>
<div *ngIf="user.uid">
<!-- 認証されている場合 -->
<p>すでにログインしています。uid: {{user.uid}}</p>
<button (click)="logout()">ログアウト</button>
</div>
</div>
user
変数には、認証状態を監視する変数があり、これの変更を待機しています。受け取った値があればそれを使い、ログインされていなければ空のオブジェクトで処理を行います。userにuidがあればログイン済と判定しています。
ログインされていない場合は、ログイン用のボタンを表示し、ログイン済の場合は、uidとログアウトボタンを表示します。匿名認証の場合は、Google認証に更新するためのボタンが表示されます。
動作を確認する
実行すると次のような画面が表示されます。
Login With Google ボタンを押すと、次のようなログインポップアップが表示されます。
ログインが正しく完了すれば画面が更新されて登録されたユーザーのuidが表示されます。FirebaseのコンソールでもGoogleアカウントのメールアドレスがユーザー情報として確認できます。
ログアウトすると元の画面の状態に戻ります。匿名認証、メールアドレスとパスワードによる認証も同様です。
匿名認証でログインし、Google認証に更新ボタンを押して更新してみましょう。匿名認証のuidが引き継がれた状態で、Google認証になっています。uidが引き継がれるため、匿名状態で管理していた状態もそのまま引き継げるようになります。
雑感
シンプルなコードで認証周りの煩雑な処理をお手軽に実装できるのがFirebaseの強みだと思います。今回は1画面で済ませるために雑な作りにもなっていますが、基本的な扱い方はこんな感じだと思います。
今回は実装していませんが、メールアドレスの確認やパスワードの再発行等もFirebaseの機能として用意されています。
認証の管理はFiresore等の機能を扱う際にもセキュリティの設定で必要になったりもするので、ぜひ使い方をマスターしておくのが良いと思います。
次回は、このコードの実装すら面倒だという人のために用意されている、FirebaseUI というツールの使い方を見ていきます。これは Firebase による認証をまとめて提供してくれる便利なツールです。これを AngularFire と組み合わせて使う方法を試してみます。
Angularなしで単体で使うのは以前記事にまとめています。
これを Angular に対応させてみます。以下のページにまとめました。
以上。
コメントを書く