Instagram API로 OAuth 인증 (Swift3 버전)

소개



당사에서 개발한 iOS 앱TABLES에서는 Instagram에 등록된 사용자 정보를 사용하여 로그인하는 기능을 구현했습니다. Instagram에 등록 된 사용자 정보를 얻으려면 Instagram API를 사용해야했지만 Instagram은 API를 사용하기위한 iOS 용 SDK가 배포되지 않았기 때문에 WebView를 사용하여 꾸준히 구현 했습니다.

Instagram 사용자 ID 획득 흐름



아래 단계에 따라 Instagram 사용자 ID를 얻습니다.
1. Authorization API에서 권한 부여 코드 발급
2. 사용자가 승인하면 리디렉션 대상에 권한 코드가 반환됩니다.
3. 인증 코드를 기반으로 사용자 정보를 얻는 API를 두드린다.
4. 사용자 정보의 JSON에서 사용자 ID 얻기

사용자 ID를 얻으려면 2 개의 인증 코드를 반드시 얻어야합니다. TABLES에서는 3과 4는 서버측에서 했으므로, 이번에는 2의 허가 코드를 취득하는 것을 목표로 하고 있습니다.

Authorization API에서 인증 코드 발급



먼저 Instagram에서 인증 코드를 발행하는 Authorization API를 두드리겠습니다. 아래가 URL입니다.
"https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code"

이것을 WebView에 표시합니다. 이번에는 UIWebview 대신 WKWebview를 사용했습니다.
WKWebview는 먼저 표시할 URL을 지정하여 표시할 수 있으므로 다음과 같이 Authorization API를 지정하여 표시합니다.

ViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()

    let instagramAuthUrl = "https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code"

    let instagramWebView = WKWebView()
    let requestURL = NSURL(string: instagramAuthUrl)
    let request = NSURLRequest(url: requestURL! as URL)

    instagramWebView.load(request as URLRequest)
    instagramWebView.navigationDelegate = self
    view = instagramWebView
}

그러면 다음과 같은 화면이 WebView에 표시됩니다.



인증 코드 얻기



그런 다음 권한 코드를 가져옵니다. 위 화면에서 사용자 이름과 비밀번호를 입력하면 다음과 같은 페이지로 전환됩니다.



여기에서 사용자가 Authorize를 탭하면 다음과 같이 인증 코드가 리디렉션 대상으로 매개 변수로 전송됩니다.REDIRECT-URI?code=CODE
따라서 권한 코드를 얻으려면 WebView에서 다음을 구현해야합니다.
  • 표시된 페이지의 URI가 등록 된 리디렉션 URI인지 여부를 결정합니다
  • URI를 구문 분석하여 권한 부여 코드 얻기

  • 이상의 기능을 구현한 소스 코드는 다음과 같습니다.

    ViewController.swift
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        let redirectURL = "[API利用申請時に登録したリダイレクトURL]"
        let URL = navigationAction.request.url.absoluteString!
    
        if Regexp(redirectURL).isMatch(URL ?? "") {
            let comp = NSURLComponents(string: URL)
            let code = comp?.queryItems?[0].value
            // codeが取れているか確認する
            print("---code---")
            print(code ?? "")
        }
    }
    

    정규 표현용의 클래스는 이하가 됩니다.

    Regexp.swift
    import Foundation
    
    class Regexp {
    
        let regexp: NSRegularExpression
        let pattern: String
    
        init(_ pattern: String) {
            self.pattern = pattern
    
            do {
                self.regexp = try NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options.caseInsensitive)
            } catch let error as NSError {
                print(error)
                self.regexp = NSRegularExpression()
            }
        }
    
        func isMatch(_ input: String) -> Bool {
            let matches = internalRegexp.matches( in: input, options: [], range:NSMakeRange(0, input.characters.count) )
            return matches.count > 0
        }
    
    }
    

    1. 표시된 페이지의 URI가 등록된 리디렉션 URI인지 여부를 확인합니다.

    WKWebview의 decidePolicyFor navigationAction라는 대리자 메서드는 액세스하는 URL이 변경되는 시점에서 호출됩니다. navigationAction.request.url에서 리디렉션 대상 URI를 사용할 수 있으므로 리디렉션 대상 URI가 등록한 URI인지 여부를 정규식으로 판단했습니다.

    2. URI를 구문 분석하여 인증 코드를 얻습니다.

    URI의 퍼스는 NSURLComponents라는 객체에 의해 구현되었습니다. NSURLComponents.queryItems 하면 쿼리 매개 변수를 얻을 수 있습니다.

    실행 결과


    ---code---
    3f63e1d6b0356d00976ee5e7d4158ae1
    

    허가 코드가 취해졌습니다 (위의 허가 코드는 적절한 문자열입니다). 인증 코드를 사용하면 사용자 ID를 얻거나 액세스 토큰을 사용하여 게시물을 가져올 수 있습니다.

    좋은 웹페이지 즐겨찾기