본문 바로가기

Dart & Flutter/Firebase auth + Spring boot

Flutter + Spring boot 연결 및 카카오 로그인 연동 (인가코드/Access token/ user info ) #05

오늘 포스팅은 실제 카카오 로그인 후 인가 코드/accessToken/user정보를 가져오는 코드를 작성하고 최종 결과인 User정보를 확인한다.

Index

  • Flutter 앱 kakao 로그인 버튼 추가 및 Flutter_web_auth 패키지 설정
  • Spring boot 서버 MainContorller.java, KakaoService.java 파일생성
  • 카카오 로그인 테스트 ( 파이어베이스 연동은 아직 하지 않은 상태)

Flutter 앱 kakao 로그인 버튼 추가 및 Flutter_web_auth 패키지 설정

1. fultter_web_auth 패키지 추가
pub.dev 접속 > flutter_web_auth 검색 > Installing 탭 패키지복사 > 프로젝트 pubspec.yaml 파일에 추가


2. AndroidManifest.xml 에 activity 추가
pub.dev 접속 > flutter_web_auth 검색 > Readme 탭 하단 Setup라인 > activity 복사 > android/app/src/main/AndroidManifest.xml 파일에 activity 추가

flutter_web_auth - activity



activity 안 data태그에 ( android:scheme="YOUR_CALLBACK_URL_SCHEME_HERE" ) scheme을 넣어준다.
( url scheme이 생소한 사람은 검색해서 한번 쯤 읽어보고 오면 더 좋다. )

Spring boot server


scheme 은 api server( Spring boot )에서 kakaoSignIn() 에서 return 해주는 redirect의 url scheme을 넣어주면 된다.
위 이미지에서 url scheme 은 "webauthcallback" 이다. 이 부분을 data태그안에 넣어준다.

android:scheme 세팅



3. pub.dev 접속 > uuid 검색 > Installing 탭 패키지복사 > 프로젝트 pubspec.yaml 파일에 추가

firebase_auth, firebase_core, google_sign_in은 이전의 포스팅에서 이미 추가했기 때문에 오늘은 flutter_web_auth, uuid 두개만 추가해 주면 된다.

4. login.dart 파일 변경 ( 카카오로그인 버튼 추가 , signInWithKakao() 생성, uuid 사용 )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:uuid/uuid.dart';
import 'package:flutter_web_auth/flutter_web_auth.dart';
 
class Login extends StatelessWidget {
  const Login({Key key}) : super(key: key);
 
  Future<UserCredential> signInWithGoogle() async {
    // Trigger the authentication flow
    final GoogleSignInAccount googleUser = await GoogleSignIn().signIn();
 
    // Obtain the auth details from the request
    final GoogleSignInAuthentication googleAuth =
        await googleUser.authentication;
 
    // Create a new credential
    final credential = GoogleAuthProvider.credential(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
 
    // Once signed in, return the UserCredential
    return await FirebaseAuth.instance.signInWithCredential(credential);
  }
 
  Future<UserCredential> signInWithKakao() async {
    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.158.217:8080/kakao/sign_in',
      'state': clientState,
    });
 
    final result = await FlutterWebAuth.authenticate(
        url: url.toString(), callbackUrlScheme: "webauthcallback");
 
    final body = Uri.parse(result).queryParameters;
    print(body);
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("SNS Login"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              child: Text("Google Login"),
              onPressed: signInWithGoogle,
            ),
            TextButton(
              child: Text("KaKao Login"),
              onPressed: signInWithKakao,
            ),
          ],
        ),
      ),
    );
  }
}
 
cs

 


Spring boot 서버 MainController.java, KakaoService.java 파일생성

프로젝트 구조


1. KakaoService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package com.example.testsnslogin_server.controller;
 
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
 
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
 
import org.springframework.stereotype.Service;
 
@Service
public class KakaoService {
 
        public void execKakaoLogin(String authorize_code) {
            
            // 엑세스 토큰 받기
            String accessToken = getAccessToken(authorize_code);
 
            // 사용자 정보 읽어오기 
            Map<String,Object> userInfo = getUserInfo(accessToken);
 
 
            System.out.println(userInfo.toString());
        }
 
        public String getAccessToken (String authorize_code) {
            String access_Token = "";
            String refresh_Token = "";
            String reqURL = "https://kauth.kakao.com/oauth/token";
 
            try {
                URL url = new URL(reqURL);
 
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 
                // POST 요청을 위해 기본값이 false인 setDoOutput을 true로
 
                conn.setRequestMethod("POST");
                conn.setDoOutput(true);
 
                // POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송
                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
                StringBuilder sb = new StringBuilder();
                sb.append("grant_type=authorization_code");
                sb.append("&client_id=75be45c34d7befda1bd48e88afe5fe44");  //본인이 발급받은 key

// 설정 redirect_uri 는 카카오에 등록된 경로를 작성하면 된다.
                sb.append("&redirect_uri=http://192.168.0.6:8080/kakao/sign_in"); // 본인이 설정해 놓은 경로
                sb.append("&code=" + authorize_code);
                bw.write(sb.toString());
                bw.flush();
 
                // 결과 코드가 200이라면 성공
                int responseCode = conn.getResponseCode();
 
                // 요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String line = "";
                String result = "";
 
                while ((line = br.readLine()) != null) {
                    result += line;
                }
 
                // Gson 라이브러리에 포함된 클래스로 JSON파싱 객체 생성
                JsonElement element = JsonParser.parseString(result);
 
                access_Token = element.getAsJsonObject().get("access_token").getAsString();
                refresh_Token = element.getAsJsonObject().get("refresh_token").getAsString();
 
                br.close();
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
 
            return access_Token;
        }
 
 
 
        public Map<String, Object> getUserInfo (String access_Token) {
 
            //    요청하는 클라이언트마다 가진 정보가 다를 수 있기에 HashMap타입으로 선언
            Map<String, Object> userInfo = new HashMap<>();
            String reqURL = "https://kapi.kakao.com/v2/user/me";
            try {
                URL url = new URL(reqURL);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
 
                //    요청에 필요한 Header에 포함될 내용
                conn.setRequestProperty("Authorization""Bearer " + access_Token);
 
                int responseCode = conn.getResponseCode();
 
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
 
                String line = "";
                String result = "";
 
                while ((line = br.readLine()) != null) {
                    result += line;
                }
 
                JsonElement element = JsonParser.parseString(result);
 
                JsonObject properties = element.getAsJsonObject().get("properties").getAsJsonObject();
                JsonObject kakao_account = element.getAsJsonObject().get("kakao_account").getAsJsonObject();
 
                String nickname = properties.getAsJsonObject().get("nickname").getAsString();
                String profile_image = properties.getAsJsonObject().get("profile_image").getAsString();
                String email = kakao_account.getAsJsonObject().get("email").getAsString();
 
                userInfo.put("nickname", nickname);
                userInfo.put("email", email);
                userInfo.put("profile_image", profile_image);
 
            } catch (IOException e) {
                e.printStackTrace();
            }
 
            return userInfo;
        }
}
cs
 
 
 

execKakaoLogin() : getAceesToken(), getUserInfo() 호출
getAccessToken() : 인가 코드를 받아서 카카오에 AccessToken을 요청하고, 전달받은 AccessToken을 return 한다.
getUserInfo() : AccessToken을 받아서 User정보를 획득하고 return 한다.



1. MainController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.example.testsnslogin_server.controller;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import com.fasterxml.jackson.databind.JsonNode;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.2;.
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
@Controller
public class MainController {
 
    @Autowired
    KakaoService kakaoService;
    
    @RequestMapping("test")
    @ResponseBody
    public String testConnect() {
        return "연결성공";
    }
 
    @RequestMapping("kakao/sign_in")
    public String kakaoSignIn(@RequestParam("code"String code) {
       Map<String,Object> result = kakaoService.execKakaoLogin(code);
        return "redirect:webauthcallback://success?customToken="+result.get("customToken").toString();
    }
}
 
cs

kakaoSignIn : 카카오에서 Redirect 요청으로 들어온 인가코드(authorization code)를 받아서 kakaoService의 execKakaoLogin() 메서드에 authorization code를 넘겨준다

카카오 로그인 테스트 ( 파이어베이스 연동은 아직 하지않았음. )

1. Spring boot server 기동

2. Spring boot server 에서 KakaoService.java 파일 27번 라인에 debug break 걸기 ( 실제 User 정보를 가져오는지 확인하는 테스트)

KakaoService.java


3. Flutter test_sns_login 앱 기동


4. Kakao Login 버튼 클릭 > 카카오 로그인페이지 Login in with KakaoTalk 클릭 > 정보입력 및 Login버튼 클릭


5. 로그인 요청 카카오톡 확인


6. Spring boot debugging > user 정보확인

Spring boot debug


오늘은 카카오 REST API로 연결하는 부분에 대해서 만 다뤘다. 실제 카카오만 사용한다면 카카오로그인은 대부분 끝났다. 하지만 우리는 Firebase연동을 해야된다. 다음 포스팅은 Firebase 연동으로 카카오 로그인 마지막 포스팅을 할 예정이다.