Github OAuth Login

Lena·2021년 5월 6일
0

방법1 - URL Scheme

1️⃣ TargetApp - Info - URL Scheme(Authorization callback URL) 설정하기

2️⃣ UIApplication.shared.open(url:)으로 url 열기

let clientID = "a1b2c3d4"
let scope = "repo gist user" 
let urlString = "https://github.com/login/oauth/authorize" 
var components = URLComponents(string: urlString)! 
components.queryItems = [URLQueryItem(name: "client_id", value: self.clientID),
			 URLQueryItem(name: "scope", value: self.scope)] 
UIApplication.shared.open(url)

3️⃣ login 성공 후 redirect, Github으로 부터 리턴받은 code를 가지고 access token 얻기

// SceneDelegate.swift

    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        if let url = URLContexts.first?.url {
            print(url)
            let code = url.absoluteString.components(separatedBy: "code=").last ?? ""
            print(code)
            requestAccessToken(with: code)
        }
    }
    
    func requestAccessToken(with code: String) {
        let url = "https://github.com/login/oauth/access_token"
        let parameters = ["client_id": APIRequestManager.clientID,
                          "client_secret": APIRequestManager.clientSecret,
                          "code": code]
        var request = URLRequest(url: URL(string: url)!)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
        guard let bodyData = try? JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) else { return }
        request.httpBody = bodyData
                
        URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
            guard let data = data else { return }
            guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else { return }
            print(json)
            if let data = json as? [String: Any] {
                // handle data
            }
        }).resume()
    }

방법2 - ASWebAuthenticationSession

  • ASWebAuthenticationSession 객체 생성하기
  • ASWebAuthenticationPresentationContextProviding 프로토콜 채택해서 presentationAnchor 함수 구현하기
class LoginViewController: UIViewController {
    
    var authenticationSession: ASWebAuthenticationSession?
    let authURL = URL(string: "https://github.com/login/oauth/authorize?client_id=\(APIRequestManager.clientID)")
    let callbackUrlScheme = "baseballapp"
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    private func auth() {
        authenticationSession = ASWebAuthenticationSession.init(url: authURL!, callbackURLScheme: callbackUrlScheme, completionHandler: { (callbackURL:URL?, error:Error?) in
                print(callbackURL)
                guard error == nil,
                    let callbackURL = callbackURL,
                    let queryItems = URLComponents(string: callbackURL.absoluteString)?.queryItems,
                    let code = queryItems.first(where: { $0.name == "code" })?.value else {
                    print("An error occurred when attempting to sign in.")
                    return
                }
            self.requestAccessToken(with: code)
        })
        authenticationSession?.presentationContextProvider = self
        authenticationSession?.start()
    }
    
    func requestAccessToken(with code: String) {
        let url = "https://github.com/login/oauth/access_token"
        let parameters = ["client_id": APIRequestManager.clientID,
                          "client_secret": APIRequestManager.clientSecret,
                          "code": code]
        var request = URLRequest(url: URL(string: url)!)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
        guard let bodyData = try? JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) else { return }
        request.httpBody = bodyData
                
        URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
            guard let data = data else { return }
            guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else { return }
            print(json)
            if let data = json as? [String: Any] {
                // handle data
            }
        }).resume()
    }
    
    @IBAction func login() {
        auth()
    }
}

extension LoginViewController: ASWebAuthenticationPresentationContextProviding {
    
    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return self.view.window ?? ASPresentationAnchor()
    }
}

https://d2.naver.com/helloworld/24942
https://medium.com/@jungkim/앱에서-oauth2-연동하기-dadcce91e921
https://www.raywenderlich.com/19364429-implementing-oauth-with-aswebauthenticationsession
https://zeddios.tistory.com/1102
and... https://deptno.github.io/posts/2018/Github-OAuth-404/

1개의 댓글

comment-user-thumbnail
2021년 6월 12일

잘 보고 갑니다 :)

답글 달기