質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

1872閲覧

firebaseのカスタム認証で500が返ってくる(LINEログイン)

abc1222

総合スコア24

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2021/10/16 01:36

前提・実現したいこと

WEBアプリでfirebaseを利用しており、LINEのLIFFを使いログインできるようにしたいと考えています。
下記のサイトを参考にコードを書いてみたところ、殆どの場合ログインできるのですが、たまに失敗します。

https://qiita.com/Arahabica/items/8f5c7472ded92128535f

複数の友達にテストしてもらっているのですが、失敗する人が同じ人なので実行環境側の原因を疑いました。
しかしLIFFに必要なLINEのバージョンも問題なく、キャッシュをクリアしてみても同じでした。
なので、コード側に問題があると思うのですが、糸口すらつかめずにいます。

原因の探し方でも構いませんので、何かアドバイスをいただけますと幸いです。

発生している問題・エラーメッセージ

サーバー(Functions)のログ

login

Function execution took 78 ms, finished with status code: 500

Functionsの正常性の欄に表示されているエラー

login

Unhandled error TypeError: Cannot destructure property 'accessToken' of 'data' as it is null. at /workspace/index.js:1269:17 at func (/workspace/node_modules/firebase-functions/lib/providers/https.js:336:32) at processTicksAndRejections (internal/process/task_queues.js:95:5)

testSet(テストとして、ログインできたらDBに書き込みを行う処理を追加しているのですが、その関数でもエラー)

Error: Request failed with status code 400 at createError (/workspace/node_modules/axios/lib/core/createError.js:16:15) at settle (/workspace/node_modules/axios/lib/core/settle.js:17:12) at IncomingMessage.handleStreamEnd (/workspace/node_modules/axios/lib/adapters/http.js:260:11) at IncomingMessage.emit (events.js:412:35) at IncomingMessage.emit (domain.js:532:15) at endReadableNT (internal/streams/readable.js:1317:12) at processTicksAndRejections (internal/process/task_queues.js:82:21) {

該当のソースコード

クライアント側

javascript

1window.onload = function() { 2 liff.init({liffId: "*****"}) 3 .then(() => { 4 initializeApp(); 5 }) 6 .catch((err) => { 7 console.log(err) 8 }); 9}; 10 11function initializeApp() { 12 if (liff.isLoggedIn()) { 13 firebaseLoginCheck() 14 } else { 15 liff.login({ redirectUri: "*****" }); 16 } 17} 18 19function firebaseLoginCheck() { 20 auth().onAuthStateChanged(async user => { 21 if (user) { 22 testesSet(); 23 } else { 24 const accessToken = liff.getAccessToken() 25 const login = functions.httpsCallable('login') 26 login({ accessToken }) 27 .then((result) => { 28 auth().signInWithCustomToken(result.data.token) 29 .then((userCredential) => { 30 testesSet(); 31 }) 32 .catch((error) => { 33 console.log(error) 34 }); 35 }) 36 .catch((error) => { 37 console.log(error) 38 }); 39 } 40 }) 41} 42 43async function testesSet() { 44 const accessToken = liff.getAccessToken() 45 const testSet = functions.httpsCallable('testSet') 46 const result = await testSet({ accessToken: accessToken }) 47 console.log(result.data) 48}

サーバー(Functions)側

javascript

1const axios = require('axios') 2const axiosInstance = axios.create({ 3 baseURL: 'https://api.line.me', 4 responseType: 'json' 5}) 6 7// 渡されたLINEトークンが正しいものかを検証 8const verifyToken = async accessToken => { 9 const response = await axiosInstance.get('/oauth2/v2.1/verify', { params: { access_token: accessToken } }) 10 if (response.status !== 200) { 11 console.error(response.data.error_description) 12 throw new Error(response.data.error) 13 } 14 // チャネルIDをチェック 15 if (response.data.client_id !== channelId) { 16 throw new Error('client_id does not match.') 17 } 18 //アクセストークンの有効期限 19 if (response.data.expires_in < 0) { 20 throw new Error('access token is expired.') 21 } 22} 23 24// プロフィールの取得 25const getProfile = async(accessToken) => { 26 const response = await axiosInstance.get('/v2/profile', { 27 headers: { 28 'Authorization': `Bearer ${accessToken}` 29 }, 30 data: {} 31 }) 32 if (response.status !== 200) { 33 console.error(response.data.error_description) 34 throw new Error(response.data.error) 35 } 36 return response.data 37} 38 39// カスタムトークンを活用したログイン処理 40exports.login = functions.region(REGION).https 41 .onCall(async data => { 42 const { accessToken } = data 43 try { 44 // LINEのアクセストークンが正しいか検証 45 await verifyToken(accessToken); 46 // アクセストークンを利用してプロフィール取得 47 const profile = await getProfile(accessToken); 48 // user情報をDBに登録 49 db.collection('user').doc(profile.userId).set({ 50 imgRef: profile.pictureUrl, 51 name: profile.displayName, 52 update: admin.firestore.FieldValue.serverTimestamp() 53 }); 54 // LINEのuserIdを利用してfirebaseのカスタム認証トークンを発行 55 const token = await admin.auth().createCustomToken(profile.userId); 56 return { token } 57 } catch (e) { 58 console.error(JSON.stringify(e, null, ' ')) 59 throw new functions.https.HttpsError('unknown', 'ログインに失敗しました ' + e); 60 } 61 }) 62 63exports.testSet = functions.region(REGION).https 64 .onCall(async(data, context) => { 65 66 const uid = context.auth.uid; 67 const accessToken = data.accessToken 68 69 const testRef = db.collection("test").doc(uid) 70 71 try { 72 await verifyToken(accessToken) 73 const profile = await getProfile(accessToken) 74 75 const value = { 76 imgRef: profile.pictureUrl, 77 name: profile.displayName, 78 update: admin.firestore.FieldValue.serverTimestamp() 79 } 80 await testRef.set(value) 81 return "成功しました" 82 } catch (error) { 83 console.log(error) 84 return "失敗しました" 85 } 86 })

試したこと

LINEのLIFFのログイン機能を使ってfirebaseのカスタム認証を利用する方法について調べているのですが、情報が少なく、何が問題なのか全く分かっていません。
エラーから、アクセストークンがnullの場合があるのかな?と思ってコードを読み直したのですが、アクセストークンは取得して格納しているようですし、殆どの場合は成功しているのでよく分からないでいます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

エラーになるのはこの行ですか?返すdataがnullになってるようです。

js

1const accessToken = data.accessToken

なぜnullなのかは、リクエストの詳細を調べる必要があります。こちら参考にできるかもしれないです。

https://stackoverflow.com/questions/60296909/firebase-functions-https-oncall-returns-null

投稿2021/10/29 03:33

heroyct

総合スコア434

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

自己解決

原因はLIFFでプロフィール情報を取得する際に、pictureUrlがundifineになる可能性があることでした。
LINEアカウントの画像を未設定にしている方の場合、undifineになるようです。
undifineの場合にnoimage画像URLをimgRef:に設定することで、エラーが出なくなりました。

投稿2021/12/15 04:24

abc1222

総合スコア24

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問