Edited at
iOS2Day 12

iOS 11 から追加された SFAuthenticationSession でシングルサインオン

More than 1 year has passed since last update.

下記の @glayash さんによる記事でも書かれていますが、iOS 10 までは Safari と SFSafariViewController の認証情報が共有されていました。

iOS 11 / Android O 時代のアプリ認証 - Qiita

しかし、iOS 11 からはそれぞれ独立した Cookie ストレージを持つように仕様が変更されました。

そこで iOS 11 beta 3 からは Safari の認証情報を共有できる SFAuthenticationSession というクラスが登場するのですが、この記事ではその使い方を説明したいと思います。


実行環境


  • Xcode 9.2


準備

今回は foursquare にログインしてみます。予め Foursquare 開発者サイト からアプリを新規登録し、CLIENT_ID と Redirect URI を取得しておきます。Redirect URI には fsoauthexample://authorized を設定してください。


実装手順

Xcode を起動し、適当なサンプルプロジェクトを作ります。

プロジェクト名は何でもいいです。


URL Schemes の設定

2017.8.8 追記:SFAuthenticationSession 初期化時に引数でスキームを指定する場合、この設定は不要です

fsoauthexample:// でアプリが立ち上がるように設定しておきます。

スクリーンショット 2017-12-11 11.30.09.png


実装

SafariServices をインポートします。

import SafariServices

引数 url に認証用のURLを指定して、SFAuthenticationSession を呼び出します。

let url = URL(string: "https://ja.foursquare.com/oauth2/authenticate?client_id=

(YOUR_CLIENT_ID)&response_type=token&redirect_uri=fsoauthexample://authorized"
)!
self.session = SFAuthenticationSession(url: url, callbackURLScheme: nil) { url, error in
print(url)
// fsoauthexample://authorized#access_token=XXXXXXXXXXXXXX
}
session?.start()

※Xcode 9 beta 3 の時点では引数 callbackURLScheme に何を指定しても挙動が変わりませんでした(詳しい方いましたら教えてください)。

2017.8.8 追記:Xcode 9 beta 5になって、ようやく挙動に変化が現れました。callbackURLScheme にスキームを指定しておけば Info.plist への指定が不要になります。

start() メソッドを実行すると「アプリがSafariの情報を使うけど問題ない?」的なアラートが表示された後、 SFSafariViewController のような画面(本記事では「ログイン画面」と呼ぶことにします)がモーダル表示されます。

Simulator Screen Shot - iPhone SE - 2017-12-11 at 11.33.45.png

すでに Safari で Foursquare にログイン済みの場合は即座に redirect url(fsoauthexample://authorized)にリダイレクトがかかり、そのタイミングで completionHandler が実行されます。

未ログインの場合は、IDとパスワードを入力する通常のログイン画面が表示されます。ログインが成功すると、redirect url にリダイレクトがかかり、そのタイミングで completionHandler が実行されます。

completionHandlerurl にはリダイレクト先の URL がセットされているので、ここから access_token を取り出すことができます。

fsoauthexample://authorized#access_token=XXXXXXXXXXXXXX

completionHandler が実行されるタイミングでログイン画面は自動的に閉じますが、cancel() メソッドを呼ぶことにより、意図したタイミングでログイン画面を閉じることもできます。

これで SFAuthenticationSession によるシングルサインオンが完了しました。


サンプルコード

https://github.com/koogawa/SFAuthenticationSessionSample


リンク