말랑한 하루
[Flutter] OAuth, Kakao Login 개발 본문
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter
※ design : https://developers.kakao.com/docs/latest/ko/kakaologin/design-guide
Kakao developers의 개발 및 디자인 가이드에 따라 kakaologin을 시작합니다.
🥕 설치
※ reference : https://developers.kakao.com/docs/latest/ko/flutter/getting-started#apply-sdk
$ flutter pub add kakao_flutter_sdk
$ flutter pub get
🥕 애플리케이션 정보
※ reference : https://developers.kakao.com/console/app
kakaologin을 시작하기에 앞서 내 애플리케이션 항목에서 애플리케이션을 추가하여 관련 정보를 얻어야합니다.
🥕 초기화
※ reference : https://developers.kakao.com/docs/latest/ko/flutter/getting-started#init
애플리케이션에서 다운로드 받은 Flutter SDK를 초기화 시키는 것이 첫 작업입니다.
main()에서 runApp()을 호출하기 전, KakaoSdk를 초기화합니다.
void main() async {
await dotenv.load(fileName: '.env');
KakaoSdk.init(
nativeAppKey: dotenv.get('KAKAO_NATIVE_APP_KEY'),
);
runApp(MyApp());
}
관련 Key는 노출되지 않도록 dotenv 라이브러리를 활용하거나 개별적으로 관리하세요.
또한, Flutter의 minSdkVersion이 21보다 낮은 경우에 버전 문제를 일으킬 수 있습니다. android/app/build.gradle 경로의 android/defaultConfig 속성에 minSdkVersion을 21로 설정하세요
🥕 프로젝트 설정
🍒 인터넷 사용 권한
Flutter Project/android/app/src/AndroidManifest.xml 파일의 <manifest> Element 하위에 인터넷 사용 권한을 설정하는 <uses-permission> Element를 추가합니다.
<uses-permission android:name="android.permission.INTERNET" />
🍒 커스텀 URL 스킴
※ reference : https://developers.kakao.com/docs/latest/ko/flutter/getting-started#project-scheme
커스텀 URL 스킴(Custom URL Scheme)은 사용자가 Android와 iOS 환경에서 카카오톡으로 로그인 후 서비스 앱으로 돌아오거나, 카카오톡 메시지 버튼 또는 링크로 서비스의 앱을 실행하는 데 사용됩니다.
🍇 Android
Flutter Project/android/app/src/AndroidManifest.xml 파일을 수정합니다.
단, AndroidManifest.xml 파일을 수정할 때 생성하는 <activity> Element에 대해 Android 12(API 31) 이상을 타깃하는 경우, android:exported 속성을 반드시 true로 선언해주어야 합니다.
🍌 카카오 로그인
<application> Element 하위에 카카오 로그인 Redirect URI 설정을 위한 <activity> Element를 추가합니다.
<!-- 카카오 로그인 커스텀 URL 스킴 설정 -->
<activity
android:name="com.kakao.sdk.flutter.AuthCodeCustomTabsActivity"
android:exported="true">
<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" />
<!-- "kakao${YOUR_NATIVE_APP_KEY}://oauth" 형식의 앱 실행 스킴 설정 -->
<!-- 카카오 로그인 Redirect URI -->
<data android:scheme="kakao${YOUR_NATIVE_APP_KEY}" android:host="oauth"/>
</intent-filter>
</activity>
🍌 카카오톡 공유, 카카오톡 메세지
android:name=".MainActivity" 속성을 갖는 <activity> Element 하위에 다음 <data> Element를 포함하는 <intent-filter> Element를 추가합니다.
대부분의 경우 <intent-filter> Element가 존재하므로, 내부 <data> Element에 대해서만 추가할 수 있습니다.
<intent-filter>
<data android:host="kakaolink" android:scheme="kakao${YOUR_NATIVE_APP_KEY}" />
</intent-filter>
🍌 API KEY 관리
Flutter Project의 android 폴더 하위에는 local.properties 파일이 있습니다. 대부분의 경우 이 폴더에서 api key를 추가적으로 관리합니다.
local.properties 파일에서 api key를 작성하였다면, Flutter Project/android/app경로의 build.gradle에서 BuildConfig에 변수를 추가하면 완료입니다.
local.properties를 build.gradle에서 사용하기 위해 다음과 같이 properties 객체를 생성합니다.
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
이후, android>defaultConfig에 manifestPlaceholder를 활용하여 api key에 대한 변수를 지정합니다.
※ reference : https://developer.android.com/build/manage-manifests?hl=ko&_gl=1*1pzo7kg*_up*MQ.._gaMTMxMzcyODE0LjE3MDg5MzM5MDI._ga_6HH9YJMN9MMTcwODkzMzkwMS4xLjAuMTcwODkzMzkwMS4wLjAuMA..#inject_build_variables_into_the_manifest
Android의 기본 manifestPlaceholders가 존재하기 때문에, 공식문서처럼 대입하는 것이 아닌 다음과 같이 값을 추가해주어야 한다.
manifestPlaceholders += [KAKAO_NATIVE_APP_KEY:localProperties.getProperty('api.key.kakao.nativeApp')]
🍇 iOS 커스텀 URL 스킴
iOS 디바이스에서는 커스텀 URL 스킴을 사용하기 위해선 Xcode를 활용한 두 개의 설정이 필요합니다.
🍌 앱 실행 허용 목록
🍌 URL Schemes
🥕 구현
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#before-you-begin-type-implementation
Flutter SDK에서는 다양한 서비스 환경에 대응할 수 있도록 여러가지 구현 방식을 제공하고 있으나, 현재 파트에서는 권장 사항인 네이티브 앱 서비스에서 카카오톡으로 로그인방식을 진행하는 경우를 다룹니다.
※ Kakao 로그인을 사용하기 위한 최소 SDK 버전은 21입니다. android/app/build.gradle의 android→defaultConfig→minSdkVersion을 21로 설정하세요.
🍒 사전 설정
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#login-with-kakaotalk
조건부 및 선택형 설정을 제외한 사전 필수 설정 항목은 다음과 같습니다.
🍇 플랫폼 등록
※ reference : https://developers.kakao.com/docs/latest/ko/getting-started/app#platform
내 애플리케이션> 앱 설정> 플랫폼 경로를 통해 Android/iOS 플랫폼 등록을 진행합니다.
android/app/src/main/AndroidManifest.xml 파일의 package 속성 값과 일치한지 확인합니다.
또한 키 해시 값이 등록되어 있는지 확인합니다.
※ reference : https://developers.kakao.com/docs/latest/ko/android/getting-started#before-you-begin-add-key-hash
키 해시(Key Hash)는 인증서(Certificate)의 인증서 지문 값(Certificate fingerprints)을 해시(hash)한 값으로, 악성 앱인지 판별하고 카카오 API를 호출하기 위해 사용됩니다. 키 해시 값은 변경되지 않으나, 여러 개발자들과 함께하는 경우 각 개발자들의 개발 환경에 따라 디버그 키스토어가 다르게 생성되어 있으므로 모두 등록해주어야 합니다.
카카오 API를 호출하면, 카카오 API 서버가 요청 헤더에 추가된 키 해시값과 카카오 플랫폼에 등록한 값이 일치하는지 확인하며, 디버그(Debug)/릴리즈(Release) 키 해시 두 가지가 있습니다.
※ reference : https://code.google.com/archive/p/openssl-for-windows/downloads
다음과 같이 터미널에서 키 해시를 생성하려면 키 해시를 관리하는 키툴(keytool)이 필요합니다. Windows의 경우, Windows 라이브러리를 위한 OpenSSL을 다운로드해야 합니다.
OpenSSL을 사용할 때는, openssl.exe가 존재하는 폴더의 경로를 입력하여 실행될 수 있게 만들어줍니다.
🍌 Debug Key Hash
keytool -exportcert -alias androiddebugkey -keystore %USERPROFILE%\\.android\\debug.keystore -storepass android -keypass android
> | ${path}\\openssl sha1 -binary | ${path}\\openssl base64
🍌 Release Key Hash
…
🍇 카카오 로그인 활성화 설정
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/prerequisite#kakao-login-activate
내 애플리케이션> 제품 설정> 카카오 로그인 경로를 통해 카카오 로그인 활성화 설정을 ON으로 변경합니다.
🍇 동의항목
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/prerequisite#consent-item
내 애플리케이션> 제품 설정> 카카오 로그인> 동의항목에서 카카오 로그인 시 사용자에게 동의받고자 하는 항목을 설정할 수 있습니다. 카카오 로그인 동의 화면에 반영되며, 사용자는 서비스 이용시 필요한 동의항목에 동의할 수 있습니다.
동의 항목을 추가하는 경우, 동의 목적을 반드시 작성해야 합니다.
🍒 로그인 요청
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#kakaologin-sample
로그인 요청은 기존 로그인을 통해 발급받은 토큰이 있는지 확인하거나, isKakaoTalkInstalled()메소드로 카카오톡 실행 가능 여부를 판단하는 방법이 있습니다.
void KakaoLogin() async {
// 카카오톡 실행 가능 여부 확인
// 카카오톡 실행이 가능하면 카카오톡으로 로그인, 아니면 카카오계정으로 로그인
bool result = await isKakaoTalkInstalled();
if (await isKakaoTalkInstalled()) {
print("카카오톡 있음");
try {
await UserApi.instance.loginWithKakaoTalk();
print('카카오톡으로 로그인 성공');
} catch (error) {
print('카카오톡으로 로그인 실패 $error');
// 사용자가 카카오톡 설치 후 디바이스 권한 요청 화면에서 로그인을 취소한 경우,
// 의도적인 로그인 취소로 보고 카카오계정으로 로그인 시도 없이 로그인 취소로 처리 (예: 뒤로 가기)
if (error is PlatformException && error.code == 'CANCELED') {
return;
}
// 카카오톡에 연결된 카카오계정이 없는 경우, 카카오계정으로 로그인
try {
await UserApi.instance.loginWithKakaoAccount();
print('카카오계정으로 로그인 성공');
} catch (error) {
print('카카오계정으로 로그인 실패 $error');
}
}
} else {
print("카카오톡 없음");
try {
OAuthToken token = await UserApi.instance.loginWithKakaoAccount();
print('카카오계정으로 로그인 성공');
} catch (error) {
print('카카오계정으로 로그인 실패 $error');
}
}
}
Kakao 로그인을 에뮬레이터 활용하여 테스트할 때, API 12버전 이상인 경우 "동의하고 계속하기" 부분에서 버그(화면이 표기되지 않는 현상/화면 깜박임 현상)가 발생한다고 합니다.
(https://devtalk.kakao.com/t/topic/134052/2) 이 점 참고하여 에뮬레이터 설정을 변경하세요.
🍒 토큰
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#request-token
토큰은 액세스 토큰(Access token), 리프레시 토큰(Refresh token), ID 토큰(ID token) 세 종류입니다.
액세스 토큰을 활용하면 토큰 정보를 보거나 ID 토큰 유효성 검증을 진행할 수 있습니다.
서비스 서버에서 토큰을 발급받은 후, 서비스 서버에서 액세스 토큰으로 사용자 정보 가져오기를 호출해 회원 가입 및 로그인에 필요한 사용자 정보를 요청할 수 있습니다. 액세스 토큰을 서비스 클라이언트로 전달해 토큰 할당하면, 서비스 클라이언트에서 Flutter SDK를 통한 카카오 API 요청에 사용할 수 있습니다.
🍇 토큰 확인
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#token-presence
AuthAPI의 hasToken()을 호출하여 Flutter SDK에 기존에 발급받아 저장된 토큰이 있는지 확인합니다.
저장된 토큰이 있는 경우, 앱을 실행하거나 카카오 로그인이 필요한 API를 호출하기 전 검증하여 다음 행위를 진행하는데 도움을 줄 수 있습니다.
🍇 토큰 정보 보기
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#get-token-info
UserApi의 accessTokenInfo()를 호출하여 Flutter SDK에 저장중인 액세스 토큰의 정보를 조회합니다. 요청 성공 시, 앱ID/회원번호/남은 유효시간 정보를 담은 AccessTokenInfo 객체가 반환됩니다. 액세스 토큰이 만료되었거나 존재하지 않는 경우에는 에러를 반환하므로, 기존 액세스 토큰의 만료 여부를 확인하는 용도로도 사용할 수 있습니다.
if (await AuthApi.instance.hasToken()) {
try {
AccessTokenInfo tokenInfo = await UserApi.instance.accessTokenInfo();
print('토큰 유효성 체크 성공 ${tokenInfo.id} ${tokenInfo.expiresIn}');
} catch (error) {
if (error is KakaoException && error.isInvalidTokenError()) {
print('토큰 만료 $error');
} else {
print('토큰 정보 조회 실패 $error');
}
try {
// 카카오계정으로 로그인 = 새로운 토큰 발급
OAuthToken token = await UserApi.instance.loginWithKakaoAccount();
print('로그인 성공 ${token.accessToken}');
} catch (error) {
print('로그인 실패 $error');
}
}
}
결과가 true인 이후에도 토큰이 유효한지 확인해야 합니다. 토큰이 유효하지 않다면 다시 카카오 로그인을 통해 새로운 토큰 발급을 진행해야 합니다.
🍒 사용자 정보 가져오기
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#req-user-info
로그인에 성공하고 토큰 유효성 검증이 끝났다면, UserApi의 me()를 호출하여 사용자의 정보를 불러옵니다.
try {
User user = await UserApi.instance.me();
print('사용자 정보 요청 성공'
'\\n회원번호: ${user.id}'
'\\n닉네임: ${user.kakaoAccount?.profile?.nickname}'
'\\n이메일: ${user.kakaoAccount?.email}');
} catch (error) {
print('사용자 정보 요청 실패 $error');
}
🍒 로그아웃
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#logout
로그아웃은 성공 여부와 상관 없이 Flutter SDK에 저장된 사용자 토큰 정보를 삭제합니다. 토큰이 삭제되는 경우, 현재 토큰 값을 통해 카카오 API를 호출할 수 없습니다.
try {
await UserApi.instance.logout();
print('로그아웃 성공, SDK에서 토큰 삭제');
} catch (error) {
print('로그아웃 실패, SDK에서 토큰 삭제 $error');
}
🍒 연결 끊기
※ reference : https://developers.kakao.com/docs/latest/ko/kakaologin/flutter#unlink
요청 성공 시, 앱과 연결이 해제된 사용자의 회원번호를 포함한 UserIdResponse 객체가 반환됩니다. 또한 로그아웃 처리가 함께 이뤄져 Flutter SDK에 저장된 토큰이 삭제됩니다.
try {
UserIdResponse = await UserApi.instance.unlink();
print('연결 끊기 성공, SDK에서 토큰 삭제');
} catch (error) {
print('연결 끊기 실패 $error');
}
로그아웃과 연결 끊기는, Flutter SDK에 저장된 카카오 토큰 정보를 삭제하는 행위입니다.
'개발 > Flutter' 카테고리의 다른 글
[Flutter] (Project) MapleSpy: 37. 앱 액세스 권한 추가 (0) | 2024.04.03 |
---|---|
[Flutter] (Project) MapleSpy: 36. 앱 정지 및 이의제기와 결과 (0) | 2024.04.02 |
[Flutter] (Error) Error type 3: Activity class {com.x.y.MainActivity} does not exist. (0) | 2024.03.30 |
[Flutter] (Project) MapleSpy: 35. 출시 준비 (0) | 2024.03.18 |
[Flutter] (Project) MapleApp: 34. 프로덕션 액세스 신청 (0) | 2024.03.14 |