[Kotlin][Firebase] Kakao Login 구현 #2
이번 포스트에서는 서버단에서 작업해주어야 할 것을 구현하고 준비해보도록 하겠다. 그리고 마지막으로 client 부분에서 구현해야 할 소스코드는 다음 포스트에서 다루도록 하겠다.
[ 사전 준비 ]
1. OS : Windows 10 10.0 / VM: OpenJDK 64-Bit Server VM by Oracle Corporation
2. 안드로이드 스튜디오 (Runtime version: 11.0.10+0-b96-7249189 amd64), JDK 설치
3. 카카오 개발자 사이트 회원가입 및 프로젝트 등록 (kakao developers: https://developers.kakao.com/docs)
4. Firebase 회원가입 및 프로젝트 등록 (https://firebase.google.com/)
5. Firebase 콘솔에서 Realtime Database 생성
6. node.js 설치
7. git 설치
[ Firebase Admin 설정 ]
1. 콘솔 > Project Overview > Project Settings > General (일반)
2. 스크롤 내리다보면 Your apps 부분이 나옴 > google-services.json 파일 다운로드 > 프로젝트 안으로 파일 옮김
즉, 이 경로에 저장: C:\Android_Projects\FINAL\trip_planner\app
3. C:\Android_Projects\FINAL > KakaoLoginServer 이름의 디렉토리(폴더) 생성
3-1) Node.js 설치 https://nodejs.org/en/download/
: LTS > Windows Installer 클릭하면 설치 프로그램이 다운로드 됨. 다운받은 다음, 클릭하여 설치를 마무리
3-2) Git 설치 https://git-scm.com/
: Download for Windows 클릭하여 설치
4. Git 설정 및 node 서버 사전 작업
git 버전 관리를 시작할 KakaoLoginServer 폴더 우클릭 > 'Git Bash Here' 클릭
4-1) git 초기화(버전 관리 시작)
$ git init
4-2) github commit에 기록될 사용자 이름, 이메일 설정 (git init 한 뒤에 최초 1번만 해주면 됨)
$ git config --global user.name '이름'
$ git config --global user.email '이메일'
4-3) 버전 확인 (잘 설치되었는지 확인)
$ node -v
4-4) 필요한 패키지 설치할 때 사용할 명령어
$ npm install 패키지명
예를 들면,
$ npm install async
$ npm install firebase
...
*주의 : 아래의 패키지들을 전부 설치해주어야 에러가 없이 잘 실행됨
"패키지명": "설치버전"
"async": "^3.2.1",
"axios": "^0.21.1",
"body-parser": "^1.19.0",
"express": "^4.17.1",
"firebase": "^8.9.1",
"firebase-admin": "^9.11.0",
"firebase-functions": "^3.15.2",
"request": "^2.88.2",
"request-promise": "^4.2.6"
참고글 : https://5coding.tistory.com/16
5. 파이어베이스 콘솔 > Project Overview > Project Settings > Service accounts (서비스 계정) > Node.js 스니펫 복사
이 화면이 안 뜬다면 Create service account 버튼 클릭해서 만들기
var admin = require("firebase-admin");
var serviceAccount = require("./serviceAccountKey.json");
//다운받은 인증키를 serviceAccountKey.json으로 저장
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "개별 부여된 디비 경로"
});
6. 하단에 Generate new private key 클릭해서 파일 다운로드 > 아래의 경로에 저장
경로 : C:\Android_Projects\FINAL\KakaoLoginServer
이 service account key는 노드 서버에서 파이어 베이스로 request를 할 때 사용될 인증키이므로 없으면 안됨
[ 소스코드 ]
[서버] KakaoLoginServer - <app.js>
본인의 시스템에 맞게 수정해줘야하는 부분:
- service account key 다운받았을 때 파일명을 service_account_key.json 으로 바꾸기const serviceAccount = require('./service_account_key.json');
- service_account_key.json 과 app.js 파일 2개가 같은 디렉토리 안에 있는지 확인하기
- 본인의 database url 을 찾아서 firebaseAdmin.initializeApp() 안에 적어줘야 함
Firebase 콘솔 > Realtime Database > database 생성 후 아래 이미지에서 빨간 네모박스에 database url 이 나와있음. 이걸 복사해서 아래 소스코드에 입력
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccount),
databaseURL: "url 복사해온 걸 여기에 붙여넣기"
});
전체 소스코드는 아래와 같다.
*주의 : 포트 8000번을 열어주어야 서버와 클라이언트가 토큰을 주고받으며 통신할 수 있음!!
구글에 "윈도우 포트 열기" 라고 검색하면 쉽게 해결할 수 있음
'use strict';
// import necessary modules
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request-promise');
// Firebase setup
const firebaseAdmin = require('firebase-admin');
const serviceAccount = require('./service_account_key.json');
// Kakao API request url to retrieve user profile based on access token
const requestMeUrl = 'https://kapi.kakao.com/v2/user/me?secure_resource=true';
// Initialize FirebaseApp with service-account.json
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccount),
databaseURL: "DB url 여기 붙여넣기"
});
/**
* requestMe - Returns user profile from Kakao API
*
* @param {String} kakaoAccessToken Access token retrieved by Kakao Login API
* @return {Promiise<Response>} User profile response in a promise
*/
function requestMe(kakaoAccessToken) {
console.log('Requesting user profile from Kakao API server.');
return request({
method: 'GET',
headers: {'Authorization': 'Bearer ' + kakaoAccessToken},
url: requestMeUrl,
});
};
/**
* updateOrCreateUser - Update Firebase user with the give email, create if
* none exists.
*
* @param {String} userId user id per app
* @param {String} email user's email address
* @param {String} displayName user
* @param {String} photoURL profile photo url
* @return {Prommise<UserRecord>} Firebase user record in a promise
*/
function updateOrCreateUser(userId, email, displayName, photoURL) {
console.log('updating or creating a firebase user');
const updateParams = {
provider: 'KAKAO',
displayName: displayName,
};
if (displayName) {
updateParams['displayName'] = displayName;
} else {
updateParams['displayName'] = email;
}
if (photoURL) {
updateParams['photoURL'] = photoURL;
}
console.log(updateParams);
return firebaseAdmin.auth().updateUser(userId, updateParams)
.catch((error) => {
if (error.code === 'auth/user-not-found') {
updateParams['uid'] = userId;
if (email) {
updateParams['email'] = email;
}
return firebaseAdmin.auth().createUser(updateParams);
}
throw error;
});
};
/**
* createFirebaseToken - returns Firebase token using Firebase Admin SDK
*
* @param {String} kakaoAccessToken access token from Kakao Login API
* @return {Promise<String>} Firebase token in a promise
*/
function createFirebaseToken(kakaoAccessToken) {
return requestMe(kakaoAccessToken).then((response) => {
const body = JSON.parse(response);
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;
if (body.properties) {
nickname = body.properties.nickname;
profileImage = body.properties.profile_image;
}
return updateOrCreateUser(userId, body.kaccount_email, nickname,
profileImage);
}).then((userRecord) => {
const userId = userRecord.uid;
console.log(`creating a custom firebase token based on uid ${userId}`);
return firebaseAdmin.auth().createCustomToken(userId, {provider: 'KAKAO'});
});
};
// create an express app and use json body parser
const app = express();
app.use(bodyParser.json());
// default root url to test if the server is up
app.get('/', (req, res) => res.status(200)
.send('KakaoLoginServer for Firebase is up and running!'));
// actual endpoint that creates a firebase token with Kakao access token
app.post('/verifyToken', (req, res) => {
const token = req.body.token;
if (!token) return res.status(400).send({error: 'There is no token.'})
.send({message: 'Access token is a required parameter.'});
console.log(`Verifying Kakao token: ${token}`);
createFirebaseToken(token).then((firebaseToken) => {
console.log(`Returning firebase token to user: ${firebaseToken}`);
res.send({firebase_token: firebaseToken});
});
});
// Start the server
const server = app.listen(process.env.PORT || '8000', () => {
console.log('KakaoLoginServer for Firebase listening on port %s',
server.address().port);
});
원본 소스코드를 보고싶다면 여기 링크로 가면 된다 :
https://github.com/FirebaseExtended/custom-auth-samples/blob/master/kakao/KakaoLoginServer/app.js
[ 서버 구동시키는 방법 ]
앱을 실행시키기 전에 꼭 이 과정을 먼저 셋업해주어야 정상적으로 작동한다. 이 필수 코스는 바로, 서버를 구동시키는 것이다. 서버로부터 토큰 받아오고 사용자 프로필 정보 받아오는 과정은 2가지 방법으로 확인할 수 있다.
1. Git bash창 (밑에 3번 )
방법 : KakaoLoginServer 폴더 우클릭 > 'Git Bash Here' 클릭 > 명령어 입력 ( $ node app.js )
2. Android Studio Terminal 창
방법 : 경로가 KakaoLoginServer로 되어있는지 확인 > 명령어 입력 (> node app.js )
터미널에서 경로 변경하는 방법:
C:\Android_Projects\FINAL>cd KakaoLoginServer
C:\Android_Projects\FINAL\KakaoLoginServer>
이렇게 바뀌면 명령어 입력!
C:\Android_Projects\FINAL\KakaoLoginServer>node app.js
*작동을 멈추고싶다면 ctrl+c 를 누르면 된다!
[ 참고 자료 ]
- 파이어베이스 SDK 추가 : https://firebase.google.com/docs/admin/setup?hl=ko#node.js
- https://sudarlife.tistory.com/entry/flutter-firebase-auth-%ED%94%8C%EB%9F%AC%ED%84%B0-%ED%8C%8C%EC%9D%B4%EC%96%B4%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%97%B0%EB%8F%99-oauth2-%EC%9D%B8%EC%A6%9D-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-part-5?category=1176193
'Android Studio > Kotlin' 카테고리의 다른 글
[Kotlin] KakaoLogin KeyHash 발급 (0) | 2021.08.27 |
---|---|
[Kotlin][Firebase] Kakao Login 구현 #3 (6) | 2021.08.24 |
[Kotlin][Firebase] Kakao Login 구현 #1 (0) | 2021.08.23 |
Intent 예제 (0) | 2021.08.10 |
Singleton (0) | 2021.08.05 |