WKWebViewで認証されたページにアクセスしたいときは、確認証方法に合わせた処理が必要です。この記事ではHTTPのBasic認証に対応する方法を解説します。
全体的な流れ
WKWebViewでBasic認証に対応するには、次のような流れを実装します。
- 認証エラーになったら、認証方式を判定する。
- アカウント情報を持っていたら、アカウント情報をヘッダに追加してアクセスする。
- アカウント情報を持っていなかったら、認証画面を表示する。
- アカウント情報が入力されたら、アカウント情報をヘッダに追加してアクセスする。
認証が必要なページにアクセスするとどうなる?
認証に対応するために必要な処理を何も実装せずに、認証が必要なページにアクセスすると、エラーページが表示されます。SafariやChromeのような認証ダイアログは自動的には表示されません。
これらの処理はアプリ側で実装する必要があります。

まずは、次の2つを実装します。
- 認証エラーになったことを判定する。
- 認証方式がBasic認証かどうかを判定する。
認証エラーになったことの判定
認証エラーになり、認証が必要になると、WKNavigationDelegateの次のメソッドが呼ばれます。
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)WKNavigationDelegateプロトコルに適合したクラスで実装し、WKWebViewクラスのnavigationDelegateプロトコルにセットします。
必要な処理を実行して、最後にcompletionHandlerを実行します。
認証方式の判定
認証方式を判定するには、URLAuthenticationChallengeのprotectionSpaceプロパティを取得して、URLProtectionSpaceのauthenticationMethodプロパティをチェックします。
次のコードは、Basic認証かどうかを判定しています。
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
var isBasicAuthentication = false
let method = challenge.protectionSpace.authenticationMethod
if method.compare(NSURLAuthenticationMethodHTTPBasic) == .orderedSame {
isBasicAuthentication = true
}
completionHandler(.performDefaultHandling, nil)
}Basic認証の場合は、authenticationMethodの値はNSURLAuthenticationMethodHTTPBasicになっています。
認証画面の表示
Basic認証だったら、認証画面を表示し、それ以外だったらデフォルトの処理を行うように実装します。
認証画面でログイン、または、キャンセルボタンが押されたら、webView(_:didReceive:completionHandler:)で取得したcompletionHandlerを実行します。
次のコードは、UIAlertControllerでログイン画面を作っているサンプルコードです。とりあえず、表示するというコードなので、ボタンの処理は特に行っていません。
func showBasicAuthAlert(completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let alert = UIAlertController(title: "Authentication",
message: "Enter your account",
preferredStyle: .alert)
// ユーザー名のテキストフィールドを作成する
alert.addTextField { (textField) in
textField.placeholder = "User Name"
textField.keyboardType = .asciiCapable
}
// パスワードのテキストフィールドを作成する
alert.addTextField { (textField) in
textField.placeholder = "Password"
textField.keyboardType = .asciiCapable
textField.isSecureTextEntry = true
}
// ログインボタンを作成する
alert.addAction(UIAlertAction(title: "Login", style: .default, handler: { (action) in
completionHandler(.performDefaultHandling, nil)
}))
// キャンセルボタンを作成する
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) in
completionHandler(.performDefaultHandling, nil)
}))
// アラートを表示する
self.present(alert, animated: true, completion: nil)
}

キャンセルボタンの処理
キャンセルボタンが押されたときの処理を実装します。とはいっても、既に実装済みのコードです。
completionHandlerの引数に.performDefaultHandlingを指定して実行します。cancelAuthenticationChallengeも定義されていて、そちらを使った方が良いと最初は思ったのですが、試してみると、cancelAuthenticationChallenageは処理の中断でした。
SafariやChromeの動作を見てみると、Basic認証でエラーになったときは、エラーページを表示するようになっています。しかし、cancelAuthenticationChallengeを指定してしまうと、エラーページの表示処理も行わずに中止してしまいました。
.performDefaultHandlingを指定すると、エラーページの表示に遷移するので、WKWebViewと組み合わせるときは、.performDefaultHandlingの方が良いと思います。
但し、エラーになったら、WKWebView自体を非表示にして、別の画面に遷移するような仕様のときは、cancelAuthenticationChallengeの方が良いでしょう。
ログイン処理
ログイン処理は、次の処理を実装します。
- 入力されたユーザー名とパスワードを取得する
- 取得したユーザー名とパスワードから認証情報を作成する
- 作成した認証情報を使って認証を行う
コードにすると次のようになります。
// ログインボタンを作成する
alert.addAction(UIAlertAction(title: "Login", style: .default, handler: { (action) in
var userName = ""
var password = ""
// 入力された文字列を取得する
if let textFields = alert.textFields {
if let str = textFields[0].text {
userName = str
}
if let str = textFields[1].text {
password = str
}
}
// このセッション専用の認証情報を作成する
let credential = URLCredential(user: userName, password: password, persistence: .forSession)
// 作成した認証情報で認証を行う
completionHandler(.useCredential, credential)
}))認証情報は、URLCredentialのインスタンスです。イニシャライザでユーザー名とパスワードを指定できます。最後のpersistenceは認証情報をどのように保持するかを指定します。
次の値が定義されています。
- none : 保持しない
- forSession : セッション中だけ保持する
- permanent : キーチェインに保存する
- synchronizable : キーチェインに保存し、Apple IDに紐付けて同期可能にする(iCloud経由で同期可能という意味だと思います)
認証情報を作成したら、useCredentialを指定して completionHandlerを実行します。
認証に成功すると、ページにアクセスできます。












