はじめに
弊社で開発しているiOSアプリTABLESでは、Instagramに登録されているユーザ情報を用いてログインする機能を実装しました。Instagramに登録されているユーザ情報を取得するためには、Instagram APIを用いる必要がありましたが、InstagramはAPIを使うためのiOS用のSDKが配布されていなかったため、WebViewを用いて地道に実装しました。
InstagramのユーザID取得の流れ
以下の手順に沿ってInstagramのユーザIDを取得します
- Authorization APIで認可コードを発行する
- ユーザが承認した場合、リダイレクト先に認可コードが返ってくる
- 認可コードをもとに、ユーザ情報を取得するAPIを叩く
- ユーザ情報の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を指定して表示します。
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をパースして認可コードを取得する
以上の機能を実装したソースコードが次のようになります。
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 ?? "")
}
}
正規表現用のクラスは以下になります。
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を取得したり、アクセストークンを用いて投稿を取得したりすることができます。