이제 커스텀 토큰 사용을 위한 firebase 연동도 마무리가 되었으니, 프론트에서 백 서버로 인가코드를 보내는 과정을 진행해보자!
우선, 카카오 로그인 과정에서 알 수 있듯이, 웹 기반의 OAuth2.0 인증을 수행해야 하는데, 이 과정에서 웹 기반의 인증 플로우를 사용할 수 있는 무언가가 필요하다.
이때 활용하는 것이 바로 Flutter_web_auth이다.
나의 경우는 버전2가 있길래 이를 활용했다.
https://pub.dev/packages/flutter_web_auth_2
그리고 해당 기능을 사용하기 위해 Anriod Menifest에 요소를 추가해야한다
<manifest>
<application>
<activity
android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
android:exported="true">
<intent-filter android:label="flutter_web_auth_2">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="YOUR_CALLBACK_URL_SCHEME_HERE" />
</intent-filter>
</activity>
</application>
</manifest>
다음과 같이 권한을 추가해서 안드로이드에서 인증이 가능하도록 만든다.
<data android:scheme="YOUR_CALLBACK_URL_SCHEME_HERE" />
이 부분에는 call back scheme을 넣어줘야 한다.
. 안드로이드 앱에서 OAuth 2.0 또는 다른 웹 기반 인증을 사용할 때, 사용자가 인증을 마치고 앱으로 돌아왔을 때 해당 앱에서 이를 인식하고 처리하기 위해 URL Scheme을 설정해야 한다.
여기서 "YOUR_CALLBACK_URL_SCHEME_HERE" 부분은 사용자가 앱으로 돌아왔을 때의 URL Scheme을 의미한다. 이 부분에는 앱에서 사용할 고유한 URL Scheme을 입력해야 하는데, URL Scheme은 해당 앱을 식별하는 데 사용된다. 또한 사용자가 웹 페이지에서 인증을 마치고 다시 앱으로 돌아오기 위해 사용된다.
즉, 앱과 웹의 인증 과정을 연결하기 위해 쓰이는 것이다.
"scheme"은 URL의 구성 요소 중 하나로, URL의 시작 부분에 온다. Scheme은 리소스에 액세스하는 방법을 지정한다. 예를 들어 redirect:@@:...이면 @@이 Scheme가 되는 것이다.
우선, 백서버로 리다이렉트를 하기 위해 로그인 화면을 구성해보도록 하겠다.
class _LoginHomeState extends State<LoginHome> {
late final String REST_API_KEY;
@override
void initState() {
super.initState();
_initialize();
}
Future<void> _initialize() async {
REST_API_KEY = await dotenv.get("FLUTTER_APP_REST_API_KEY") ?? '';
}
Future<UserCredential?> signInWithKakao() async {
if (REST_API_KEY.isEmpty) {
// REST_API_KEY가 초기화되지 않았으면 처리
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Error'),
content: Text('REST API Key is not initialized.'),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('OK'),
),
],
),
);
}
final clientState = Uuid().v4();
final url = Uri.https('kauth.kakao.com', '/oauth/authorize', {
'response_type': 'code',
'client_id': REST_API_KEY,
'redirect_uri': 'http://192.168.200.165:8080/kakao/oauth',
'state': clientState,
});
final result = await FlutterWebAuth2.authenticate(
url: url.toString(), callbackUrlScheme: "webauthcallback");
final body = Uri.parse(result).queryParameters;
}
로그인을 위해서, 버튼을 누르면 signInWithKakao()가 동작하도록 OnPress만 설정하면 되기 때문에, 이 signInWithKakao()의 동작 과정만 이해하면 된다.
final clientState = Uuid().v4();
final url = Uri.https('kauth.kakao.com', '/oauth/authorize', {
'response_type': 'code',
'client_id': REST_API_KEY,
'redirect_uri': 'http://192.168.200.165:8080/kakao/oauth',
'state': clientState,
});
참고한 예시와 같이, 나의 경우도 clientState를 구분하기 위해 UUID를 이용했다.
OAuth 인증 프로세스에서는 보안을 강화하기 위해 "상태(state)" 매개변수를 사용하는 것이 일반적이다. 이 매개변수는 클라이언트와 서버 간의 상태를 유지하고, 중간자 공격을 방지하는 데 사용된다. 여기서 UUID를 사용하여 client state를 생성하는 이유 중 하나는 "고유성 보장"을 위해서이다.
고유성 보장: UUID(Universally Unique Identifier)는 범용적으로 고유한 값을 생성하는 데 사용됩니다. 따라서 UUID를 사용하면 각 인증 요청마다 고유한 상태 값이 생성되어 중복되지 않게 됩니다.
카카오의 인가코드 rest api이다. 살펴보면 get 방식으로 url을 요청한다고 되어 있다. 그래서 kauth.kakao.com', '/oauth/authorize'이렇게 요청 url을 작성한다.
필수로 요청하는 쿼리 파라미터이다. 해당하는 값들을 넣어준다.
final result = await FlutterWebAuth2.authenticate(
url: url.toString(), callbackUrlScheme: "webauthcallback");
FlutterWebAuth2.authenticate를 통해서 OAuth2.0 인증 과정을 진행한다. 리다이렉트로 인가코드를 받아야 하기 때문에 callbackUrlScheme: "webauthcallback"으로 콜백스키마를 설정한다.
body 정보를 result로 받아주면 과정은 마무리된다.
이렇게 하면 프론트(flutter)에서 인가코드를 받아서 전달하기 위한 과정은 마무리된다!