새소식

250x250
Framework, Library

[Social Login] Access Token과 Refresh Token, 그리고 Auto Login까지

  • -
728x90

이번 나다 NADA 어플 릴리즈를 준비하면서 가장 많이 공부한 부분이 "로그인"과 관련된 부분일 거다.

처음 아요끼리 담당 기능, 파트를 나눌 때, 내가 로그인을 맡겠다고 (겁 없이) 지원했었는데...
왜 그랬는지... 모르겠다... 사실 로그인이 이렇게 공부할 점이 많고 많은 이슈가 생길지는 몰랐기 때문ㅇ.....

아무튼 그래도 배운 점은 진짜 많았다.

사실, 서버에 '서'자도 모르는 나였는데, 내가 도-약할 수 있었던 두 가지 계기가
첫째는 라이브러리 Moya를 사용했을 때, 둘째는 소셜 로그인 API를 사용했을 때일 것이다.

아무튼, 오늘은 내가 피나게(?) 공부했었던 로그인에 대한 추가적인 내용들을 정리해보는 시간을 가져보도록 하겠다.

(공부했던 두 가지 소셜 로그인 방법(카카오톡, 애플)은 아래 포스팅에서 정리해두었다 ^__^)

 

[iOS] 소셜 로그인을 구현해보자! 1탄 - 카카오톡 로그인

오늘은 최신 어플이라면, 빠지지 않고 가장 기본적으로 들어가는 기능 "소셜 로그인"에 대해 시리즈로 글을 다루어보려 한다. 오늘은 그 첫 번째로, 카카오톡 간편 로그인에 대해 다뤄보겠다. Kak

mini-min-dev.tistory.com

 

[AuthenticationServices] 소셜 로그인을 구현해보자! 2탄 - Apple 로그인

아주 예전에 작성했던 "소셜 로그인" 시리즈, 오랜만에 그 2탄을 써보려고 한다. 오늘은 "Apple 로그인"에 대해서 알아보도록 하자. (👇🏻예전 카카오톡 소셜 로그인을 다뤘던 글은 아래에서 확인

mini-min-dev.tistory.com

 

1. 로그인을 구현하기 위해서는 토큰(Token)이 무엇인지 먼저 알아야 한다!


이번 프로젝트에는 jwt 토큰 방식을 사용해서 로그인 기능을 구현했다.

아무것도 몰랐을 때, 그냥 막연하게 로그인을 담당하기로 했을 때는 무슨 토큰, 토큰이라는 이야기를 정말 많이 들었지만,
이 토큰이 무슨 종류가 있는지, 어떻게 사용해야 하는지, 왜 써야 하는지를 아무것도 모르는 상태였다.

그럼, 처음 내가 공부했을 때로 돌아가 토큰이 무엇인지부터 차근차근 초보 개발자의 입장에서 설명해보록 하겠다.

토큰이라는 개념은 OAuth(Open Auth)라는 곳에서 나온 개념이다.

위키백과를 살펴보면, OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로써 사용되는, 접근 위임을 위한 개방형 표준이라고 나타나 있다.

간단하게 말하면, 카카오톡을 기준으로 카카오톡이 아닌 다른 앱에서도 이 OAuth라는 프로토콜을 사용한다면,
회원가입을 할 때, 카카오 로그인에서 사용했던 개인정보(예를 들어, 아이디, 닉네임, 프로필 사진 등)이용할 수 있게 된다는 뜻이다.

그냥 마냥 저 개인정보를 이용할 수 있게 하면 안 되니,

클라이언트와 서버 간에 인증(Authentication)과 권한 부여(Authorization) 과정에서 필요한 수단으로 이 Token을 사용하는 것이다.

클라이언트와 서버와의 OAuth방식 (출처: 진중권의 iOS 앱 개발 알아가기)

즉, 정리하자면,
토큰은 클라이언트가 사용자의 개인정보를 필요로 하는데, 그때 클라가 서버에게 요청을 해야 하는 과정에서 필요한 값이다.

클라이언트가 서버에게 토큰(Token)이라는 일종의 비밀번호, 우리만의 열쇠(?) 값을 받아와,
이 토큰(Token)을 가지고 다시 서버에 요청할 때만, 원하는 자료를 클라이언트가 받을 수 있는 순서로 이루어지는 것이다.

 

2. 토큰이 Access Token과 Refresh Token으로 나뉘는 이유


하지만, 이 토큰은 다시 두 개로 나누어진다.

그냥 편하게 하나의 토큰이라는 이름으로 사용하면 될 것이지, 굳이 Access Token과 Refresh Token이라는 이름으로 구분해 둔 이유는 무엇일까? (나도 처음에는 굉장히 이 부분이 궁금했다.)

이 질문에 대한 답은, 다시 위로 올라가 Token값이 언제 필요한지에 대해 다시 읽어보면 얻을 수 있다.

하지만, 다시 올라가서 읽기는 싫을테니...여기서 다시 복습하자면...
토큰(Token)은 클라이언트가 사용자의 개인정보를 필요로 할 때, 그 정보에 접근하기 위한 열쇠와 같은 역할을 한다. 고 했다.

토큰이 언제 필요하다고?

클라이언트가 사용자의 개인정보를 필요로 할 때 필요한 거라고.
개인정보를 다룬다는 자체가 굉장히 민감한 내용이니만큼, 보안 또한 중요한 요소로 고려해야 된다는 거!

그럼 여기서 답을 얻을 수 있다.
토큰(Token)을 두 가지의 종류로 나누어둔 이유는 보안을 위해서다. (아래 기사를 보면 실제로 토큰과 보안에 대한 내용을 언급하고 있다.)

 

"페북 액세스 토큰 주의하세요"…내 계정 '좋아요 좀비'된다 | 연합뉴스

(서울=연합뉴스) 김태균 기자 = 토큰(Token)이란 말을 들으면 30대 이상은 1990년대까지 시내버스에서 받았던 동전 모양 승차권을 연상할...

www.yna.co.kr

개인정보에 접근할 수 있는 액세스 토큰(Access Token)에는 유효기간을 아주 짧게 설정해두는 편이다.

하지만, 정보에 접근할 수 있는 토큰의 유효기간이 짧다면, 유효기간이 끝나게 되면 다시는 그 정보에 다시 접근하지 못한다는 것이니.
이 상황을 대처하기 위해 만들어둔 것이 리프레쉬 토큰(Refresh token)이다.

리프레쉬 토큰은 그 유효기간을 보통 길게 만들어둔다. 

즉, 액세스 토큰(Access Token)이 만료됐으나 리프레쉬 토큰(Refresh token)이 만료되지 않은 경우에, 리프레쉬 토큰(Refresh token)을 사용해서 액세스 토큰(Access Token)을 갱신하여 유효하게 사용할 수 있도록 하는 것이다.

액세스 토큰(Access Token)
  - 보안을 위해서 유효기간이 짧은 토큰(보통 1시간 내외), 사용자의 개인정보를 접근하기 위해 사용되는 토큰이다.

리프레쉬 토큰(Refresh token)
 - 유효기간이 비교적 긴 토큰(보통 2주), 액세스 토큰이 만료되었을 때 갱신을 위한 목적으로 사용되는 토큰이다.

 

3. 이를 바탕으로 로그인 로직을 구현해보자!


이 정도 내용을 읽었으면, 이제 로그인 구현을 위한 기본 지식은 갖췄다고 봐도 된다!

그럼 이제 난이도를 조금 높여서 자동 로그인을 어떻게 구현해줄지 로직을 생각해보자.
(잠깐! 서비스 상으로 사용자가 탈퇴를 하는 경우에는 추가 분기처리가 필요하다! (이게 무슨 말인고 하면, 카카오톡으로 로그인을 했을 때, 카카오톡으로 연결된 앱 관리에서 사용자가 직접 연결 해제를 했을 경우를 의미))

1. 사용자가 로그인한다. (서버에 통신 시작)
 
2. 서버에서는 회원 DB에서 값을 비교한다. 
 
3. 로그인이 완료되면 Access Token, Refresh Token을 발급한다. 이때, 회원 DB(여기서 말하는 회원 DB는 보통 UserDefaults나 KeyChain을 의미)에는 Access Token과 Refresh Token을 저장해둔다. (추후에 자동 로그인을 위함)
 
4. 클라이언트는 이제 서버 통신을 할 때마다 Access Token을 헤더에 실어 요청을 보낸다.
 
5. 서버는 Access Token을 검증하여 이에 맞는 데이터를 보낸다.
 
6. 만약, 시간이 지나 Access Token이 만료되었을 경우, 클라이언트는 이전과 동일하게 Access Token을 헤더에 실어 요청을 보낸다.
 
7. 서버는 Access Token이 만료됨을 확인하고 이에 맞는 메시지를 반환한다. or 클라이언트가 Access Token의 Payload를 통해 유효기간을 미리 알고 있을 수도 있음
 
8. 클라이언트는 Refresh Token과 Access Token을 함께 토큰 재발급 서버로 보낸다.
 
9. 서버는 Refresh Token과 사용자의 DB에 저장되어 있던 Refresh Token을 비교한 후, 만약 Refresh Token이 동일하고 유효기간도 지나지 않았다면 새로운 Access Token을 발급해준다.
 
10. 클라이언트는 새로 발급받은 Access Token을 통신 때마다, 헤더에 실어 요청을 보낸다.

11. 만약, 시간이 더더더 지나 Access Token과 Refresh Token이 모두 만료되었을 경우에는 사용자가 다시 로그인을 할 수 있도록 화면을 전환시킨다.

여기서 자동 로그인은 별것 없다(?)
Refresh Token과 Access Token을 앱 자체에서 저장해 두고, 앱을 실행할 때마다(AppDelegate에서) 이 Token이 저장되어 있는지, 유효한지를 체크하고 화면 전환을 진행하면 된다.

화면 전환을 하기 위한 전 단계는 스플래시 화면에서 처리를 하는 것이다.

스플래시 화면에 구현해둔 코드를 살펴보자.
AppDelegate에서 토큰에 대한 유효성을 체크한 후, 그 상태에 따라 메인화면으로 전환할지 로그인 화면으로 전달할지 구분해둔 것이다.

override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
        
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
            if self.appDelegate?.isLogin == true {
                self.presentToMain()
            } else {
                self.presentToLogin()
            }
        }
    }
    
    // MARK: - Functions
    private func presentToMain() {
        guard let mainVC = UIStoryboard(name: Const.Storyboard.Name.tabBar, bundle: nil).instantiateViewController(withIdentifier: Const.ViewController.Identifier.tabBarViewController) as? TabBarViewController else { return }
        mainVC.modalPresentationStyle = .fullScreen
        mainVC.modalTransitionStyle = .crossDissolve
        self.present(mainVC, animated: true, completion: nil)
    }
    
    private func presentToLogin() {
        guard let loginVC = UIStoryboard(name: Const.Storyboard.Name.login, bundle: nil).instantiateViewController(withIdentifier: Const.ViewController.Identifier.loginViewController) as? LoginViewController else { return }
        loginVC.modalPresentationStyle = .fullScreen
        loginVC.modalTransitionStyle = .crossDissolve
        self.present(loginVC, animated: true, completion: nil)
    }

AppDelegate 코드를 살펴보면 이렇다.

애플 로그인과 카카오 로그인, 두 가지 방식의 로그인 방법을 구현했기 때문에 이것에 대한 각각의 분기 처리를 해주었다.
토큰의 존재 유무, 유효성에 따라 각각 isLogin값을 바꿔준 것을 확인할 수 있다 ^__^

	if acToken != nil {
            if UserDefaults.standard.bool(forKey: Const.UserDefaultsKey.isAppleLogin) {
                // 애플 로그인으로 연동되어 있을 때, -> 애플 ID와의 연동상태 확인 로직
                let appleIDProvider = ASAuthorizationAppleIDProvider()
                appleIDProvider.getCredentialState(forUserID: UserDefaults.standard.string(forKey: Const.UserDefaultsKey.userID) ?? "") { (credentialState, error) in
                    switch credentialState {
                    case .authorized:
                        print("해당 ID는 연동되어있습니다.")
                        self.isLogin = true
                    case .revoked:
                        print("해당 ID는 연동되어있지않습니다.")
                        self.isLogin = false
                    case .notFound:
                        print("해당 ID를 찾을 수 없습니다.")
                        self.isLogin = false
                    default:
                        break
                    }
                }
            } else {
                if AuthApi.hasToken() {     // 유효한 토큰 존재
                    UserApi.shared.accessTokenInfo { (_, error) in
                        if let error = error {
                            if let sdkError = error as? SdkError, sdkError.isInvalidTokenError() == true {
                                self.isLogin = false
                            }
                        } else {
                            // 토큰 유효성 체크 성공(필요 시 토큰 갱신됨)
                            self.isLogin = true
                        }
                    }
                } else {
                    // 카카오 토큰 없음 -> 로그인 필요
                    self.isLogin = false
                }
            }
        } else {
            self.isLogin = false    // acToken 값이 nil일 때 -> 로그인 뷰로
        }

 

4. 보안을 위한 한 걸음 더 나아가기, KeyChain


앞에서도 한번 말했지만, 로그인에 대한 부분은 개인정보를 다루다 보니 보안에 있어서 굉장히 민감한 이슈를 갖고 있다.
그러다 보니, Token 같은 민감한 데이터를 저장할 때, 일반적으로 사용하는 UserDefaults 방법보다는 이 KeyChain 방법을 사용하곤 한다.

KeyChain 방법을 사용해서 토큰 데이터를 저장하도록 하는 글을 아래에 작성했으니, 참고하면 좋겠다.

 

5. Reference


 

쉽게 알아보는 서버 인증 2편(Access Token + Refresh Token)

안녕하세요! 이전 포스팅에는 크게 세션/쿠키 인증, 토큰 기반 인증(대표적으로 JWT)에 대하여 알아보았습니다. 저희가 앱, 웹 혹은 서버 개발을 하면서 꼭 사용하게 되는 인증(Authorization)은 아주

tansfil.tistory.com

 

Access Token과 Refresh Token이란 무엇인가?

안녕하세요. 개발자 드리머즈입니다.    [카카오 아이디로 로그인하기]에서나.. 네이버, 페이스북을 통한 로그인 시에 access token과 refresh token에 관한 내용을 들을 수 있습니다. 대충 뭐하는 녀

dreamaz.tistory.com

 

[iOS - swift] 6. 서버 - OAuth, Key Chain, 로그인 관리 토큰

https://documentation.progress.com/output/oe117sp/index.html#page/gssp2/oauth2-concepts-and-terms.html 1. OAuth란?  - Third-party application의 인증 권한부여 및 관리를 위해서 사용 (특정 쇼핑몰 회원..

ios-development.tistory.com

 

[iOS/Swift] Auto Login 기능 구현(자동 로그인, UserDefaults 사용)

Swift Auto Login 기능 만들기 지난번엔 로그인 기능을 해봤으니 이번에는 저장된 데이터로 자동로그인을 하는 기능을 구현해보자 To-do List Checkbox 버튼 만들기 auto login 버튼 체크 후 로그인 성공 시 i

hyesunzzang.tistory.com

 

OAuth2.0

OAuth2.0 안녕하세요. 오늘은 우리가 여러 웹서비스들을 이용할 때 자주 사용되는 요소 중 하나인 OAuth2.0에 대해 살펴보는 시간을 갖도록 하겠습니다. OAuth2.0이란 각종 웹, 모바일 어플리케이션에

baked-corn.tistory.com

 

728x90
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.