var google = new firebase.auth.GoogleAuthProvider(); firebase.auth().signInWithPopup(google);
signInWithCustomToken
http://localhost:8080/instagram-callback
https:///instagram-callback
// Instagram OAuth 2 の設定 const credentials = { client: { id:YOUR_INSTAGRAM_CLIENT_ID, // 要変更 secret:YOUR_INSTAGRAM_CLIENT_SECRET, // 要変更 }, auth: { tokenHost: 'https://api.instagram.com', tokenPath: '/oauth/access_token' } }; const oauth2 = require('simple-oauth2').create(credentials);
/instagram-callback
app.get('/redirect', (req, res) => { // ランダムな状態検証 Cookie を生成 const state = req.cookies.state || crypto.randomBytes(20).toString('hex'); // localhost で安全でない Cookie を許可 const secureCookie = req.get('host').indexOf('localhost:') !== 0; res.cookie('state', state.toString(), {maxAge: 3600000, secure: secureCookie, httpOnly: true}); const redirectUri = oauth2.authorizationCode.authorizeURL({ redirect_uri: `${req.protocol}://${req.get('host')}/instagram-callback`, scope: 'basic', state: state }); res.redirect(redirectUri); });
function onSignInButtonClick() { // ポップアップで Auth フローをオープン window.open('/redirect', 'firebaseAuth', 'height=315,width=400'); };
code
state
app.get('/instagram-callback',(req, res) => { // state Cookie を受け取ったことを確認 if (!req.cookies.state) { res.status(400).send('State cookie not set or expired.Maybe you took too long to authorize.Please try again.'); // state Cookie が state パラメータと一致することを確認 } else if (req.cookies.state !== req.query.state) { res.status(400).send('State validation failed'); } // アクセス トークン用に認証コードを交換 oauth2.authorizationCode.getToken({ code: req.query.code, redirect_uri: `${req.protocol}://${req.get('host')}/instagram-callback` }).then(results => { // Instagram アクセス トークンとユーザー ID の取得が完了 const accessToken = results.access_token; const instagramUserID = results.user.id; const profilePic = results.user.profile_picture; const userName = results.user.full_name; // ... }); });
app.get('/instagram-callback', (req, res) => { // ... }).then(results => { // Instagram アクセス トークンとユーザー ID の取得が完了 const accessToken = results.access_token; const instagramUserID = results.user.id; const profilePic = results.user.profile_picture; const userName = results.user.full_name; // Firebase カスタム認証トークンの作成 const firebaseToken = createFirebaseToken(instagramUserID); // ログインを実行し、ユーザー プロフィールをアップデートする HTML ページの提供 res.send( signInFirebaseTemplate(firebaseToken, userName, profilePic, accessToken))); }); });
service-account.json
const firebase = require('firebase'); const serviceAccount = require('./service-account.json'); firebase.initializeApp({ serviceAccount: serviceAccount });
function createFirebaseToken(instagramID) { // ユーザーに割り当てる uid const uid = `instagram:${instagramID}`; // カスタム トークンの作成 return firebase.auth().createCustomToken(uid); }
app.get('/instagram-callback', (req, res) => { // ... // ログインを実行し、ユーザー プロフィールをアップデートする HTML ページの提供 res.send( signInFirebaseTemplate(firebaseToken, userName, profilePic, accessToken))); }); }); function signInFirebaseTemplate(token, displayName, photoURL, instagramAccessToken) { return ` <script src="https://www.gstatic.com/firebasejs/3.4.0/firebase.js"></script> <script src="promise.min.js"></script><!-- Promise Polyfill for older browsers --> <script> var token = '${token}'; var config = { apiKey:MY_FIREBASE_API_KEY, // 要変更 databaseURL:MY_DATABASE_URL // 要変更 }; // 一時 Firebase アプリにログインしてプロフィールをアップデート var tempApp = firebase.initializeApp(config, '_temp_'); tempApp.auth().signInWithCustomToken(token).then(function(user) { // Realtime Database に Instagram API アクセス トークンを保存 const tasks = [tempApp.database().ref('/instagramAccessToken/' + user.uid) .set('${instagramAccessToken}')]; // 必要に応じて displayname と photoURL をアップデート if ('${displayName}' !== user.displayName || '${photoURL}' !== user.photoURL) { tasks.push(user.updateProfile({displayName: '${displayName}', photoURL: '${photoURL}'})); } // 以上のタスクの完了を待機 return Promise.all(tasks).then(function() { // 一時 Firebase アプリを削除し、デフォルト Firebase アプリにログインし、ポップアップをクローズ var defaultApp = firebase.initializeApp(config); Promise.all([ defaultApp.auth().signInWithCustomToken(token), tempApp.delete()]).then(function() { window.close(); // 完了!ポップアップをクローズ }); }); }); </script>`; }