F.Ko-Jiの「一秒後は未来」

Swift: GitHubのOAuthログインをiOSアプリからやってみた

iOS アプリから GitHub のアカウントで OAuth ログインするというのをやってみた。環境は Xcode 6 beta 4 と Swift。

参考にしたサイトはこちら。

» iOSアプリでGithubにOAuthする – yaakaito.org

それから公式ドキュメント。

» OAuth | GitHub API

最初に GitHub の Applications にてアプリケーション登録をして Client ID と Client Secret を取得。Authorization callback URL にはカスタムURLスキームを設定する必要がある。

ちなみにカスタムURLスキームのスキーム部分にピリオドが入っているとエラーになるので、 com.fkoji.someapp:// のような Bundle ID を元にしたURLスキームは使えない。someapp:// のような形式にしておくこと。

ios-oauth-github-01.jpg

↑ Authorization callback URL の設定例。

次に OAuth ログインの実装。Twitter や Facebook と違って iOS 標準の SDK がないので まずは Safari ないしは UIWebView でログイン画面を開いてログインしてもらい、callback URL でアプリへ戻ってくるという流れになる。

let clientId = "your client id"
let url = NSString(
    format: "https://github.com/login/oauth/authorize?client_id=%@",
    clientId
)

// Safari が開く場合
UIApplication.sharedApplication().openURL(NSURL.URLWithString(url))

GitHub にログインしアプリケーションの連携を許可すると、指定したカスタムURLスキームに「?code=hogehoge」がついて戻ってくる。カスタムURLスキームは UIApplicationDelegate の application:openURL:sourceApplication:annotation: 内で解析。以下 AppDelegate.swift から抜粋。

func application(application: UIApplication!, openURL url: NSURL!, sourceApplication: String!, annotation: AnyObject!) -> Bool {

    // callback URL に someapp://oauth/github と指定した場合、
    // someapp://oauth/github?code=hogehoge のようなURLで戻ってくる
    if url.scheme == "someapp" {
        if url.host == "oauth" && url.lastPathComponent == "github" {
            let kv = url.query.componentsSeparatedByString("=")
            if kv[0] != "code" {
                return false
            }

            let code = kv[1]

            // サインイン (独自のクラスで定義)
            let github = MyGitHubLogin()
            github.getAccessToken(code)

            return true
        }
        return false
    }

    return true
}

サインイン部分は独自のクラスに実装してみた。書き方は色々。ここでは AFNetworking を使ってアクセストークンの取得をおこなっている。

class MyGitHubLogin {
    var code: String!
    var clientId: String!
    var clientSecret: String!
    var accessToken: String!

    init() {
        // 上記の宣言時に let でセットしててもよい
        self.clientId = "your client id"
        self.clientSecret = "your client secret"
    }

    func getAccessToken(code: String!) {
        self.code = code

        let manager: AFHTTPRequestOperationManager = AFHTTPRequestOperationManager()

        // GitHub の OAuth で JSON フォーマットのレスポンスを受け取るには Accept ヘッダーが必要
        let requestSerializer = AFHTTPRequestSerializer()
        requestSerializer.setValue("application/json", forHTTPHeaderField: "Accept")
        manager.requestSerializer = requestSerializer

        manager.POST(
            "https://github.com/login/oauth/access_token",
            parameters: [
                "client_id": self.clientId,
                "client_secret": self.clientSecret,
                "code": self.code
            ],
            success: { (operation, responseObject) in
                if let response = responseObject as NSDictionary! {
                    self.accessToken = response["access_token"] as String!

                    // あとはお好みで…
                }
            },
            failure: { (operation, error) in
                // エラー時のアラート処理などはここに
            }
        )
    }
}

アクセストークンが取得できれば、さらにそれを元に「https://api.github.com/user?access_token=…」をリクエストすることでプロフィール情報を取得できる。今回は取得したアクセストークンをサーバーサイドに投げてそっちでログイン処理をおこなう必要があったのでここでは割愛。

(修正履歴: 2014-08-15) MyGitHubLogin の login を getAccessToken に変更

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

著者について

fkoji

F.Ko-Ji

Webエンジニアやってます。最近は ドットインストール の開発がお仕事です。その傍ら、個人で Meity電車遅延なう梅酒.in#グラドル自画撮り部 の部室といったネットサービスを開発・運営してます。梅酒と草野球とリアル脱出ゲームが好きです。

» 詳しいプロフィールや運営サービスの一覧など