57
59

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[iOS]OAuth認証を極める(GitHubAPIで学ぶOAuth認証のフロー)

Last updated at Posted at 2018-05-07

アプリでGitHubAPIを使用する

<対象>
・OAuth認証のフローを知りたい
・GitHubAPIをつかいたい

GitHubでは、検索やリポジトリの読み書き、プルリクエストの生成・更新・削除などいろいろなAPIが提供されています。
GitHubAPI

これらは
アクセストークンなしでAPIを使用することもできるのですが、その場合はAPIでできることが一部制限されてしまいます。例えば、SearchAPIには以下のような注釈があります。

Note: You must authenticate to search for code across all public repositories.
パブリックなリポジトリを対象に検索を実行するには認証が必要です

というわけで、APIの全機能を使うためにはGitHub認証が必要になるわけです。

本記事ではiOSアプリでGitHub認証しアクセストークンを取得するまで(OAuth認証の流れとアプリ側の実装)をまとめました!

OAuth認証のフロー

・事前準備
ここからGitHubのアプリを新規に作成します。
必要事項を記入し、完了するとClient IDClient Secretが発行されます。

でここからがアプリ内での処理です。

① 認可リクエスト
GithubのAPIを使ったアプリのサービスを受けたいので、「認可リクエスト」を行う
→ WebViewなどで認証画面を表示する
→ ユーザーはGithubにログインし、アプリに代理アクセスすることを許可する(連携認証の許可)
→ GitHubからコールバック
→ GitHubから認証コードをレスポンスとしてもらう

② アクセストークン取得
もらったコードを使ってアプリはGithubの「アクセストークン交換場所 (Token Endpoint)」にアクセスします。
その際、認証コードを「アクセストークン」に変換する為に、アプリは事前の登録で取得したクレデンシャル(Client IDClient Secret)で認証を受けます。 (クライアント認証)
正しく認証されると、コードと引き換えにアクセストークンをもらいます。

以上の流れは「コードフロー」と呼ばれ、基本的なOAuthのフローです。

図にすると以下のような感じです。
スクリーンショット 2018-05-05 4.31.04.png

アプリで実装してみる

流れがわかったので、実装に落とし込んでみます。

(以下ではライブラリとして、Alamofire, Swiftyjsonを利用しています)

① 認可リクエスト

.swift

let gitOuthUrl = URL(string: "https://github.com/login/oauth/authorize?client_id={ 
取得したクライアントID }&scope=public_repo")
let gitOuthRequest = URLRequest(url: gitOuthUrl!)
webView.load(gitOuthRequest)

上記ではwebViewで認可リクエストを送っています。
scope=public_repoはパブリックなリポジトリに対する読み書き権限を要求していることを示します。なくてもOKです。参考
で、以下のように連携認証のためにログインが求められます。

Simulator Screen Shot - iPhone X - 2018-05-06 at 00.04.24.png

ここでログインを実行するとコールバックURLが実行され、認証コードを取得できるので、それを取得する処理を書きます。

.swift

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { 

        // 設定しているコールバックURLのスキーム、ホスト名で分岐処理       
        if navigationAction.request.url?.scheme == "yyokii", navigationAction.request.url?.host == "GithubSearchApp"{
            dismiss(animated: true, completion: nil)

            // 認証コード取得
            let code = getQueryStringParameter(url: (navigationAction.request.url?.absoluteString)!, param: "code")
            

            // ② アクセストークン取得処理
            let githubAPIManager = GithubAPIManager.sharedManager
            githubAPIManager.getAccessToken(code: code, completion: nil)

            decisionHandler(WKNavigationActionPolicy.allow);
}


static func getQueryStringParameter(url: String, param: String) -> String? {
        guard let url = URLComponents(string: url) else { return nil }
        return url.queryItems?.first(where: { $0.name == param })?.value
    }

ここで使用されるコールバックURLはGithHubでアプリ登録したときに設定したURLとなります。
コールバックURLが叩かれたときにクエリパラメーターに付与されている認証コードを取得しています。

② アクセストークン取得処理

.swift

    /// アクセストークンを取得
    ///
    /// - Parameter code: このコードとアクセストークンを交換
    func getAccessToken(code: String!, completion: @escaping () -> Void) {
        self.code = code
        let url = "https://github.com/login/oauth/access_token"
        
        // 受信可能なレスポンスデータのメディアタイプを指定
        let headers = [
            "ACCEPT": "application/json"
        ]
        
        // 認証に必要な値を設定
        let parameters: Parameters = [
            "client_id": self.clientId,
            "client_secret": self.clientSecret,
            "code": self.code
            ]
        
        Alamofire.request(url, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON{ response in
            
            switch response.result {
            case .success:
                let json = JSON(response.result.value!)

                // アクセストークンを取得
                let accessToken = json["access_token"].string
                UserDefaults.standard.set(accessToken!, forKey: ACCESS_TOKEN)
                completion()
            case .failure(let error):
                print(error)
            }
        }
    }

ヘッダー、リクエストパラメーターを設定し、"https://github.com/login/oauth/access_token"をPOST通信で叩きます。でそのレスポンスからアクセストークンを取得しています。

このアクセストークンを使用してAPIを叩くには、ヘッダーに
"Authorization": "token " + {取得したアクセストークン}をつければOKです!!

おわり!!!

57
59
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
59

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?