[Flutter] 네이버, 카카오 Social Login 구현 (3. 카카오 로그인 구현)
카카오 Social Login을 구현해 보자! 앞에서 네이버 로그인을 구현하는 방식과 동일하다. 서버 설정을 하지 않았거나 네이버 로그인이 궁금하다면 아래 링크를 참고.
[Flutter] 네이버, 카카오 Social Login 구현 (1. 서버 설정)
[Flutter] 네이버, 카카오 Social Login 구현 (2. 네이버 로그인 구현)
카카오 설정
Kakao developers 홈페이지로 가서 로그인 후 애플리케이션을 추가한다.
앱 이름과 사업자명을 입력하고 저장을 클릭한다.
생성 후 플랫폼 설정하기를 클릭한다.
Web 플랫폼 등록을 클릭한다.
REST API 주소를 적어준다. api를 제외하고 적어야 한다.
도메인을 성공적으로 등록한 모습이다. 아래 등록하러 가기를 클릭하여 Redirect URI를 등록하러 가자
상태를 활성화하고 Redirect URI 등록을 클릭한다.
아까 입력한 REST API 주소에서 /api/kakao/login과 /api/kakao/token을 붙여서 넣어주면 끝!
추가적으로 동의 항목들을 원하는대로 설정해준다.
서버 코딩
아래 내용을 해당 파일에 그대로 코딩한다. /naver/login 경로의 location에 있는 callback을 통해 앱으로 redirect 해준다. 네이버 로그인과 같이 사용하는 경우 기존 index.js에서 case만 추가해주면 된다.
index.js
'use_strict';
const kakao_auth = require('kakao_auth');
exports.handler = async (event) => {
switch (event.path) {
case '/kakao/login':
if (event.httpMethod === 'GET') {
const params = event.queryStringParameters;
return {
statusCode: 307,
headers: {
Location: `callback://success?${new URLSearchParams(params)}`
},
body: JSON.stringify(params)
};
}
break;
case '/kakao/token':
if (event.httpMethod === 'GET') {
const accessToken = event.queryStringParameters.accessToken;
const result = await kakao_auth.createFirebaseToken(accessToken);
return {
statusCode: 200,
body: result
};
}
break;
}
};
카카오로부터 토큰을 발급받는 함수들을 만들어준다.
kakao_auth.js
'use strict';
// https://github.com/FirebaseExtended/custom-auth-samples/tree/master/kakao
const admin = require('./firebase_admin.js');
const axios = require('axios');
const URL = 'https://kapi.kakao.com/v2/user/me';
async function requestMe(accessToken) {
const result = await axios.get(URL, {
method: 'GET',
headers: {'Authorization': 'Bearer ' + accessToken}
});
return result.data;
}
async function updateOrCreateUser(userId, email, displayName, photoURL) {
const updateParams = {
provider: 'KAKAO',
displayName: displayName,
};
if (displayName) {
updateParams['displayName'] = displayName;
} else {
updateParams['displayName'] = email;
}
if (photoURL) {
updateParams['photoURL'] = photoURL;
}
try {
return await admin.auth().updateUser(userId, updateParams);
} catch (e) {
if (e.code === 'auth/user-not-found') {
updateParams['uid'] = userId;
if (email) {
updateParams['email'] = email;
}
return await admin.auth().createUser(updateParams);
}
throw (e);
}
}
async function createFirebaseToken(accessToken) {
const me = await requestMe(accessToken);
const userId = `kakao:${me.id}`;
let nickname = null;
let profileImage = null;
if (me.properties) {
nickname = me.properties.nickname;
profileImage = me.properties.profile_image;
}
const userRecord = await updateOrCreateUser(userId, me.kakao_account.email, nickname, profileImage);
const updateParams = {
uid: userRecord.id,
email: me.kakao_account.email,
provider: 'KAKAO',
displayName: nickname,
};
if (nickname) {
updateParams['displayName'] = nickname;
} else {
updateParams['displayName'] = me.kakao_account.email;
}
if (profileImage) {
updateParams['photoURL'] = profileImage;
}
return await admin.auth().createCustomToken(userId, {provider: 'KAKAO'});
}
module.exports = {
createFirebaseToken
};
앱 코딩
여기까지 서버 설정을 마무리하고 Flutter 앱으로 가보자. 먼저 필요한 dependency를 추가해준다. 버전은 최신 버전을 확인하여 넣어주자.
dependencies:
firebase_core: ^1.0.2
firebase_auth: ^1.0.1
uuid: ^3.0.2
flutter_web_auth: ^0.2.4
http: ^0.13.1
android/app/src/main/AndroidManifest.xml로 가서 아래 코드를 추가한다. android:scheme의 callback은 서버에서 redirect에 사용하는 값으로 동일하게 해주면 된다.
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" >
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="callback" />
</intent-filter>
</activity>
로그인 함수를 만든다. 로그인 클릭 시 아래 함수를 실행시키자. REST_API_KEY에 카카오에서 발급받은 키를 넣는다.
static const String BASE_URL = 'https://s80lt7nefi.execute-api.ap-northeast-2.amazonaws.com/api';
Future<UserCredential> loginWithKakao() async {
final clientState = Uuid().v4();
final authUri = Uri.https('kauth.kakao.com', '/oauth/authorize', {
'response_type': 'code',
'client_id': {REST_API_KEY},
'response_mode': 'form_post',
'redirect_uri': '${Server.BASE_URL}/kakao/login',
'scope': 'account_email profile',
'state': clientState,
});
final authResponse = await FlutterWebAuth.authenticate(
url: authUri.toString(),
callbackUrlScheme: "webauthcallback"
);
final code = Uri.parse(authResponse).queryParameters['code'];
final tokenUri = Uri.https('kauth.kakao.com', '/oauth/token', {
'grant_type': 'authorization_code',
'client_id': {REST_API_KEY},
'redirect_uri': '${Server.BASE_URL}/kakao/login',
'code': code,
});
final tokenResult = await http.post(tokenUri);
final accessToken = json.decode(tokenResult.body)['access_token'];
final response = await http.get(
Uri.parse('${Server.BASE_URL}/kakao/token?accessToken=$accessToken')
);
return await FirebaseAuth.instance.signInWithCustomToken(response.body);
}
로그인 후 UserCredential에서 원하는 데이터를 가져오면 된다. 아래는 이메일을 가져와서 보여주는 예시이다.
이미 로그인이 되어 있어서 로그인 창은 뜨지 않음
이렇게 네이버와 카카오 로그인 모두 완료하였다. 이 방법으로 다른 웹 플랫폼을 지원하는 소셜 로그인을 사용할 수 있으니 알아두면 도움이 될 것이다.