LoginSignup
51
41

More than 3 years have passed since last update.

Firebase Authentication Custom Tokenの取得と利用

Last updated at Posted at 2019-12-09

既存の認証システムや標準プロバイダがない場合に利用できるのがcustom tokenによる認証。
要は何か識別IDとなる文字列を渡してやればそれに対応したtokenが帰ってくる。その後はそのtokenを利用してログインすればよい。

取得

まずtokenの取得。admin権限が必要みたい。
hogehogeとなっているところ、既存の認証システムでのIDにすればよい。

ここをProvider:userIdとかするといろいろ便利らしい。

getToken.js
const admin = require('firebase-admin');
const serviceAccount = require('path/to/key.json');

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: 'https://staging-xxxxx.firebaseio.com',
});


admin.auth().createCustomToken('hogehoge')
    .then(token => {
        console.log(token);
    })
    .catch(e => {
        console.log(e);
    });

上記プログラムを実行すると下記のようなレスポンス。これがtoken。

node getToken.js

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJodHRwczovL2lkZW50aXR5dG9vbGtpdC5nb29nbGVhcGlzLmNvbS9nb29nbGUuaWRlbnRpdHkuaWRlbnRpdHl0b29sa2l0LnYxLklkZW50aXR5VG9vbGtpdCIsImlhdCI6MTU3NTkyNDIwNSwiZXhwIjoxNTc1OTI3ODA1LCJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay12YW9lYkBzdGFnaW5nLWE1OTQ2LmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic3ViIjoiZmlyZWJhc2UtYWRtaW5zZGstdmFvZWJAc3RhZ2luZy1hNTk0Ni5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInVpZCI6ImhvZ2Vob2dlIn0.BuY23mqh26evnsN7Rh_0QkugBTpL0992P763P_n9fcYPHsTWz-VzHKqXMOviITSLFPNNiDXRcFPsPGYmfwaOcIrW8QfgNtfF12coymqK16XeqOkZEHlj-TLqxuMMRIkoZcDW6PcYsYVel_hplYOzuKD5hvNiHiNv8jQKRsLq2EbVGeOCizS0CCVK_6GsB34QUTsHp717vO6Ek2L0IPRijil9xRunCnYh2Tjz-PdyZ3H2eY6iqM7YW0qZ32TjfhEvGpJxabCKMrHmOlh4WZIxINO43fI17Kln45wniVaDN0zKt1sG1StdVXVcbD0wAX8cZl6JpP347nCskPxxxxxxxx

DBにアカウントと紐付けてtokenを保存しておいて利用とかする。

tokenの有効期限は1時間なのでdbに保存するまでもないかも(どうrefreshするか問題はある)。

利用

利用はクライアント側。

上記で取得したtokenを利用。

authClient
const firebase = require('firebase');

const firebaseConfig = {
    apiKey: "AIzaSyD7HtQGZhfL4T1ttrElxsgDwqoxxxxxxxx",
    authDomain: "test-xxxxx.firebaseapp.com",
    databaseURL: "https://test-xxxxx.firebaseio.com",
    projectId: "test-xxxxx",
    storageBucket: "test-xxxxx.appspot.com",
    messagingSenderId: "250622200000",
    appId: "1:250622212741:web:ff33a2e77b61e8990xxxxx",
    measurementId: "G-VVQ2BXXXXX"
};

firebase.initializeApp(firebaseConfig);

const token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJodHRwczovL2lkZW50aXR5dG9vbGtpdC5nb29nbGVhcGlzLmNvbS9nb29nbGUuaWRlbnRpdHkuaWRlbnRpdHl0b29sa2l0LnYxLklkZW50aXR5VG9vbGtpdCIsImlhdCI6MTU3NTkyNDIwNSwiZXhwIjoxNTc1OTI3ODA1LCJpc3MiOiJmaXJlYmFzZS1hZG1pbnNkay12YW9lYkBzdGFnaW5nLWE1OTQ2LmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic3ViIjoiZmlyZWJhc2UtYWRtaW5zZGstdmFvZWJAc3RhZ2luZy1hNTk0Ni5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInVpZCI6ImhvZ2Vob2dlIn0.BuY23mqh26evnsN7Rh_0QkugBTpL0992P763P_n9fcYPHsTWz-VzHKqXMOviITSLFPNNiDXRcFPsPGYmfwaOcIrW8QfgNtfF12coymqK16XeqOkZEHlj-TLqxuMMRIkoZcDW6PcYsYVel_hplYOzuKD5hvNiHiNv8jQKRsLq2EbVGeOCizS0CCVK_6GsB34QUTsHp717vO6Ek2L0IPRijil9xRunCnYh2Tjz-PdyZ3H2eY6iqM7YW0qZ32TjfhEvGpJxabCKMrHmOlh4WZIxINO43fI17Kln45wniVaDN0zKt1sG1StdVXVcbD0wAX8cZl6JpP347nCskPxxxxxxxx";

firebase.auth().signInWithCustomToken(token)
    .then(res => {
        console.log(res.user.uid);
        res.user.updateEmail("hoge@hoge.com"); //emailを設定
    })
    .catch(e => {
        console.log(e);
    })

実行するとログインできる。

node authClient

Authentication UIで見ると下記のような感じ。

スクリーンショット 2019-12-10 5.49.22.png

その他

tokenのrefreshをどうやってやるの?

いろいろなところで議論されているが明確な答えがない。最悪、一度ユーザーをdeleteして、再度createすればいいのだろうけど。。。
引き続き調査。

追記

createしたときにtokenしか戻らないので、どうやってrefreshしたらいいのか?という疑問がありましたが、ログインしたときにuser情報にrefresh_token情報が含まれているのでそれを保存しておいて利用する感じらしい。

が、上記のtokenの有効期限自体が1時間なので、1時間以内にその処理をやる必要がある。

下記のようにログイン時にrefreshTokenを出力。

firebase.auth().signInWithCustomToken(token)
    .then(res => {
        console.log(res.user.uid);
        console.log(res.user.refreshToken);
    })
    .catch(e => {
        console.log(e);
    })

で、下記のようにrefreshTokenを利用して新しいtokenを要求する。

const firebase = require('firebase');
const axios = require('axios');

const firebaseConfig = {
    apiKey: "AIzaSyD7HtQGZhfL4T1ttrElxsgDwqoxxxxxxxx",
    authDomain: "test-xxxxx.firebaseapp.com",
    databaseURL: "https://test-xxxxx.firebaseio.com",
    projectId: "test-xxxxx",
    storageBucket: "test-xxxxx.appspot.com",
    messagingSenderId: "250622200000",
    appId: "1:250622212741:web:ff33a2e77b61e8990xxxxx",
    measurementId: "G-VVQ2BXXXXX"
};

firebase.initializeApp(firebaseConfig);

//上記で取得したリフレッシュToken
const refreshToken = "AEu4IL24RUu8heim0A2kn4U_Yk5lJy1-a7pdDapK08OFUDOA1hoH7oxzoa5Yb9Vafb4SpH8pVUtza4KfyvZZ2IF-r-dIpAXM9B8cnw-k_bXXXXXXXXX-XXXX";

//postパラメータを設定
const params = new URLSearchParams();
params.append('grant_type', 'refresh_token');
params.append('refresh_token', refreshToken);

//リクエスト
axios.post('https://securetoken.googleapis.com/v1/token?key=' + firebaseConfig.apiKey, params)
    .then(res => {
        // console.log(res.data.access_token);
        console.log(res);
    })
    .catch(e => {
        console.log(e);
    })
  • refreshtokenはexpireしないみたい
  • revokeRefreshToken()を呼ぶみたい
admin.auth().revokeRefreshTokens('UID');
51
41
1

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
51
41