Skip to content

Github OAuth In iOS

Jungrae Cho edited this page Nov 6, 2020 · 1 revision

작성자 : S057 조정래

최종수정일 : 2020.11.7(토)

GitHub OAuth 적용

iOS App 에서 깃허브 OAuth 요청을 하고 Token을 받아 API 서버에 전달하고, JWT를 발급받기 까지의 과정을 정리한 내용

OAuth application 등록하고 Client-id & Client-secret 값 얻기

스크린샷 2020-11-06 오후 11 40 14

스크린샷 2020-11-06 오후 11 51 35

  • Application name : 말 그대로 적절한 이름의 어플리케이션 이름을 정해주면 된다.

  • Homepage URL : iOS앱 클라이언트에서 인증할 예정이기 때문에 아무 url 이나 입력해주면 된다.

  • Authorization callback URL : 나의 깃허브 계정을 앱에서 사용하겠다는 인증등록에 대한 허가의 증거를 반환해 줄 URL이다. OAuth Access Token 을 앱에서 직접 받으려면 어플리케이션 Scheme으로 직접 연결을 해주어야 한다.

스크린샷 2020-11-06 오후 11 59 28

Xcode 에서 다음과 같이 URL Scheme 을 설정해 두어서 앱을 통해 Token을 받고, 인증 절차가 끝나면 브라우저에서 앱으로 되돌아올 수 있도록 하자.

Code 얻기

다음과 같은 URL에 요청을 한다.

GET https://github.com/login/oauth/authorize

스크린샷 2020-11-07 오전 12 08 17

파라미터의 경우 client_id 는 필수이고 나머지는 선택사항이다. redirect_uri는 기본값이 OAuth 등록할 때 사용했던 값이고, scope는 받을 정보에 대한 범위를 설정하는 값이다.

class LoginManager {
  func requestCode() {
      let scope = "repo,user"
      let urlString = "https://github.com/login/oauth/authorize?client_id=\(client_id)&scope=\(scope)"
      if let url = URL(string: urlString), UIApplication.shared.canOpenURL(url) {
         UIApplication.shared.open(url)
      }
  }
}

다음과 같이 액션 메서드에 호출해주면 된다.

    @IBAction func touchedSignInWithGithub(_ sender: Any) {
        LoginManager.shared.requestCode()
    }

이후 사용자가 로그인 버튼을 누르게 되면 브라우저를 통해 Github 인증을 거치게 되고 이후 redirect 를 해준다.

SceneDelegate(_:openURLContexts:) 를 통해 들어온다.

   func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        if let url = URLContexts.first?.url {
            print(url)
            // ralp://login?code=[code]
        }
    }

Access Token 을 얻기 위해서는 이 코드를 통해 한번 더 github에 요청을 해야한다.

POST https://github.com/login/oauth/access_token

스크린샷 2020-11-07 오전 12 08 17

    func requestAccessToken(with code: String) {
        let url = "https://github.com/login/oauth/access_token"
        
        let parameters = ["client_id": client_id,
                          "client_secret": client_secret,
                          "code": code]
        
        let headers: HTTPHeaders = ["Accept": "application/json"]
        
        AF.request(url, method: .post, parameters: parameters, headers: headers).responseJSON { (response) in
            switch response.result {
            case let .success(json):
                if let dic = json as? [String: String] {
                    let accessToken = dic["access_token"] ?? ""
                    KeychainSwift().set(accessToken, forKey: "accessToken")
                    print(dic)
                    if let token = dic["access_token"] {
                        self.requestJWT(acccess_token: token) // api 서버에 access token 을 보내고 jwt를 받는 api
                    }
                }
                
            case let .failure(error):
                print(error)
            }
        }
    }
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        if let url = URLContexts.first?.url {
            if url.absoluteString.starts(with: "ralp://") {
                if let code = url.absoluteString.split(separator: "=").last.map({ String($0) }) {
                    LoginManager.shared.requestAccessToken(with: code)
                }
            }
            print(url)
        }
    }

최종적으로 사용자는 JWT 를 받게 되고 이를 헤더에 싣어 보냄으로서 요청에 대한 유효성을 검증 받을 수 있다.


🎃 데일리 스크럼 🎃

Week 1

Week 2

Week 3

🎈 데일리 회고 🎈

Week 1

Week 2

Week 3

💻 주간 개발 진행 💻

Week 1

Week 2

Week 3

🎏 스프린트 계획 회의 🎏

🧑🏻‍🤝‍🧑🏻 피어세션 🧑🏻‍🤝‍🧑🏻

📚 위클리 팀 회고 📚



Clone this wiki locally