본문 바로가기
JavaScript/JS & TS

카카오 파이어베이스 커스텀토큰 로그인(팝업x)

by noddu 2022. 8. 3.
728x90
반응형

https://fpem3309.tistory.com/127

 

[Vue]카카오 로그인 액세스 토큰 발행

https://injekim97.tistory.com/137 [2021.03.17] 인턴 +16 카카오 로그인(REST API) - 정리 완료 [2021.03.17] 인턴 +16  카카오 로그인(REST API) - 정리 완료 developers.kakao.com/docs/latest/ko/ka..

fpem3309.tistory.com

이어서 엑세스 토큰으로
Firebase Functions를 사용해서 커스텀 토큰을 만들고 로그인
 

 

firebase-functions 설정

/functions/index.js

const functions = require('firebase-functions')
const admin = require('firebase-admin')

require('dotenv').config();

var serviceAccount = require("./service-account.json");

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount)
})

exports.token = functions.https.onRequest(require('./token'))

service-account.json에 Admin-SDK 키를 넣어둠
token을 다른 파일에 분리시켰다
 


파이어베이스 커스텀토큰 생성

/functions/token/index.js

const app = require('express')()
const cors = require('cors')
const axios = require('axios')
const admin = require('firebase-admin')

// cors open
app.use(cors())

app.get('/:id', async (req, res) => {
    console.log(req.params.id)
    var i = await createFirebaseToken(req.params.id)
    console.log(i);
    res.send(i)
})

function createFirebaseToken(kakaoAccessToken) {
    return requestMe(kakaoAccessToken).then((response) => {
        const body = response.data
        console.log(body)
        const userId = `kakao:${body.id}`
        
        if (!userId) {
            return res.status(404)
                .send({ message: 'There was no user with the given access token.' })
        }
        let nickname = null
        let profileImage = null
        let email = null
         
        if (body.kakao_account) {
            nickname = body.kakao_account.profile.nickname
            email = body.kakao_account.email
            profileImage = body.kakao_account.profile_image
        }

        return updateOrCreateUser(userId, email, nickname, profileImage)
    }).then((userRecord) => {
        const userId = userRecord.uid
        console.log(`creating a custom firebase token based on uid ${userId}`)
        return admin.auth().createCustomToken(userId, { provider: 'KAKAO' })
        .then((customToken)=>{
            console.log(`created custom token for user ${customToken}`)
            return customToken
        }).catch((error) => {
            console.log('Error'+error)
        })
        
    })
}

function updateOrCreateUser(userId, email, displayName, photoURL) {
    console.log('updating or creating a firebase user');
        const updateParams = {
            provider: 'KAKAO',
            displayName: displayName,
            email: email,
        };
        if (displayName) {
            updateParams['displayName'] = displayName;
        } else {
            updateParams['displayName'] = email;
        }
        if (photoURL) {
            updateParams['photoURL'] = photoURL;
        }
        console.log(updateParams);
        return admin.auth().updateUser(userId, updateParams)
            .catch((error) => {
                if (error.code === 'auth/user-not-found') {
                    updateParams['uid'] = userId;
                    if (email) {
                        updateParams['email'] = email;
                    }
                    return admin.auth().createUser(updateParams);
                }
                throw error;
            });
    }

function requestMe(kakaoAccessToken) {
    console.log('Requesting user profile from Kakao API server.')
    return axios.get(`https://kapi.kakao.com/v2/user/me`, { headers: { 'Authorization': 'Bearer ' + kakaoAccessToken } })
}

module.exports = app

 

반응형

 

 

코드 내용


  https://github.com/everything-of-firebase/custom-auth-functions-samples

 

GitHub - everything-of-firebase/custom-auth-functions-samples

Contribute to everything-of-firebase/custom-auth-functions-samples development by creating an account on GitHub.

github.com

  1.  파이어 베이스의 모든것! 공식 GITHUB의 파일을 가져와 수정(axios 등)
  2. Front에서 전달받은 엑세스 토큰을 createFirebaseToken 메소드 인자로 전달
  3. createFirebaseToken 메소드에서는 requestMe 메소드 인자로 엑세스 토큰을 전달
  4. 맨 밑에 requestMe 메소드는 axios를 사용해 유저정보를 가져오는 url을 통해 값을 리턴
  5. createFirebaseToken에서 requestMe에서 반환한 값을 updateOrCreateUser메서드의 인자로 넘깁니다.
  6. updateOrCreateUser 메서드에서는 Firebase Admin SDK가 사용되는데,
    Firebase Authentication 정보에 이미 등록이 되어 있다면 업데이트를,
    정보가 없다면 admin.auth().createUser 메서드를 통해 새로운 Firebase Authentication 계정을 생성
  7. 다시 createFirebaseToken으로 돌아와 생성되거나 업데이트 된 계정의 uid를 가져와 admin.auth().createCustomToken(uid, {provider: ‘KAKAO’})의 결과값을 반환
  8. 커스텀 토큰 생성된게 안보여서 return customtoken을해서 console로 찍어보니 잘 나왔습니다
     Front에 res.send()로 전송

 

 Front에서 token 로그인

src/view/LoginMenu/loginToken.js

import axios from "axios";
import firebase from "firebase";

const kakaoHeader = {
    'Authorization': 'JavscriptKey? REST API Key?',
    'Content-type': 'application/x-www-form-urlencoded;charset=utf-8',
};
var result = '';
const getKakaoToken = async (code) => {
    console.log('loginWithKakao');
    try {
        const data = {
            grant_type: 'authorization_code',
            client_id: 'YOUR KEY',  // JavaScript 키
            redirect_uri: 'http://localhost:3000/KakaoLogin',
            code: code,
        };
        const queryString = Object.keys(data)
            .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(data[k]))
            .join('&');
        console.log(queryString)
        console.log(('https://kauth.kakao.com/oauth/token', queryString, { headers: kakaoHeader }))
        result = await axios.post(`https://kauth.kakao.com/oauth/token`, queryString, { headers: kakaoHeader });
        console.log('카카오 토큰', queryString);
        console.log(result)
        // 토큰 할당
        Kakao.Auth.setAccessToken(result.data.access_token);
        return result;
    } catch (e) {
        return e;
    }
};
const getKakaoUserInfo = async (data) => {
    console.log(result.data.access_token)
    await Kakao.API.request({
        url: '/v2/user/me',
        success: function (response) {
            data = response;
        },
        fail: function (error) {
            console.log(error);
        },
    });
    console.log('카카오 계정 정보', data);
    return data;
}

// Functions 요청
const customToken = async (token) => {
    await axios.get(`MY FUNCTION URL/token/${token}`)
        .then((r) => {
            console.log(r.data)

            // 커스텀 토큰으로 로그인
            firebase.auth().signInWithCustomToken(r.data)
                .then((userCredential) => {
                    var user = userCredential.user;
                    console.log(user)
                })
                .catch((error) => {
                    var errorCode = error.code;
                    var errorMessage = error.message;
                    console.log(errorCode)
                    console.log(errorMessage)
                })
        })
        .catch((error) => {
            console.log(error.message)
        })
}


export {
    getKakaoToken,
    getKakaoUserInfo,
    customToken
};

전달받은 커스텀 토큰으로 로그인
 
 

KakaoLogin.vue

import { getKakaoToken, customToken } from './loginToken.js';
const params = new URLSearchParams(location.search);

// 인가 코드
var code = params.get('code');
export default {
    data() {
        return {
            code,
        }
    },
    created() {
        this.setKakaoToken();
    },
    methods: {
        async setKakaoToken() {
            console.log('카카오 인증 코드', code);
            const { data } = await getKakaoToken(code);
            if (data.error) {
                alert('카카오톡 로그인 오류입니다.');
                return;
            }
            await this.setUserInfo();
        },
        async setUserInfo() {
            //getKakaoUserInfo();
            tokenTest();
            customToken();
            await this.redirectHome();
        },

export한 customToken함수를 불러와 실행시킨다

반응형