記事

Webサービスを通してユーザーを認証する

App内でWebの認証セッションを使用してユーザーを認証します。

概要

Webサイトの中には、安全なユーザー認証メカニズムをサービスとして提供しているものがあります。ユーザーがそのサイトの認証URLに移動すると、認証情報を入力するためのフォームが表示されます。認証情報の検証が行われたのち、ブラウザは認証の結果を示すURLにリダイレクトされます。このとき、カスタムスキームが使用されるのが一般的です。

Web認証セッションの作成

AppでWeb認証サービスを利用するには、その認証vページのURLでASWebAuthenticationSession(英語)のインスタンスを初期化します。認証Webページは、自身が管理するものでも、サードパーティが運用するものでも構いません。初期化の際には、以下のように、認証Webページが認証結果を返すために使用するコールバックスキームを指定します。

// Use the URL and callback scheme specified by the authorization provider.
guard let authURL = URL(string: "https://example.com/auth") else { return }
let scheme = "exampleauth"

// Initialize the session.
let session = ASWebAuthenticationSession(url: authURL, callbackURLScheme: scheme)
{ callbackURL, error in
    // Handle the callback.
}

イニシャライザのトレイリングクロージャを使用して、認証終了後のコールバック処理方法を指定します。詳しくは後述のコールバックの処理を参照してください。

macOSの場合やiOS 13以降をDeployment Targetとする場合、このセッションは認証プロセスが終了するまで自身への強い参照を維持するため、システムによってクロージャが解放されないようになっています。それ以前のiOSをDeployment Targetとする場合は、認証が終了するまでAppがセッションへの強い参照を維持する必要があります。

表示コンテキストの提供

Appは、ASWebAuthenticationPresentationContextProviding(英語)プロトコルに準拠することにより、セッションの表示アンカーとなるウインドウを指定します。以下のように、このプロトコルの必須メソッドであるpresentationAnchor(for:)(英語)メソッドから、アンカーとなるウインドウが返されます。

extension ViewController: ASWebAuthenticationPresentationContextProviding {
    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return view.window!
    }
}

セッションの作成後、適切なコンテキストプロバイダのインスタンスをセッションのpresentationContextProvider(英語)デリゲートとして設定します。

session.presentationContextProvider = viewController

一時的なブラウジングのリクエスト(オプション)

セッションのprefersEphemeralWebBrowserSession(英語)プロパティをtrueに設定し、一時的なブラウジングをリクエストするようセッションを設定することもできます。

session.prefersEphemeralWebBrowserSession = true

この設定を行うと、認証プロセスの際にcookieなどの既存のブラウジングデータを一切使用しないようブラウザに要求することになります。また、認証プロセス中に収集したデータをプロセス終了後も保持しないことや、他のセッションと共有しないことも要求します。一時的なセッションによりセキュリティは強化されますが、前回の認証の結果を再利用できないため、ユーザーが認証情報を再度入力しなければならなくなる可能性があります。したがって一般には、一時的なブラウジングを行うかどうかをユーザーに選択してもらうのが最適な方法です。

Safariは常にこのリクエストに従います。macOSの場合、ユーザーがデフォルトのブラウザを選択できるので、このリクエストに従う場合と従わない場合があります。

認証フローの開始

セッションを設定した後、以下のようにstart()(英語)メソッドを呼び出します。

session.start()

iOSの場合、セッションは初期化で指定した認証Webページを組み込みブラウザのビューにロードします。macOSの場合、セッションは、ユーザーのデフォルトのブラウザが認証セッションに対応している場合はそのブラウザに、そうでない場合はSafariに、ページロード要求を送信します。いずれの場合も、ブラウザに認証ページが表示されます。認証ページは通常、ユーザー名とパスワードの入力フォームです。

Appは、ユーザーが認証を終了する前にセッションのcancel()(英語)メソッドを呼び出せば、認証プロセスをキャンセルすることもできます。

session.cancel()

キャンセルすると、セッションは自動的に対応するブラウザのビューを閉じます。

コールバックの処理

ユーザー認証が完了すると、認証プロバイダはコールバックスキームを使用するURLにブラウザをリダイレクトします。ブラウザはリダイレクトを検出し、自分自身を消去し、完全なURLをAppに渡します。これは、初期化の際に指定したクロージャを呼び出すことで行われます。

Appは、このコールバックを受け取ったら、まずエラーがないかどうかをチェックします。たとえば、ユーザーがブラウザのウインドウを消去して認証フローを中断した場合、canceledLogin(英語)エラーを受け取ります。エラーがnilであれば、コールバックURLを調べて認証結果を確認します。

guard error == nil, let callbackURL = callbackURL else { return }

// The callback URL format depends on the provider. For this example:
//   exampleauth://auth?token=1234
let queryItems = URLComponents(string: callbackURL.absoluteString)?.queryItems
let token = queryItems?.filter({ $0.name == "token" }).first?.value

上記の例では、クエリパラメータに保存されたトークンを探しています。どのような構文解析を行う必要があるかは、認証プロバイダのコールバックURLの構成によります。

関連項目

Webベースログイン

class ASWebAuthenticationSession(英語)

AppがWebサービスを通してユーザーを認証するために使用するセッション。