|
// ViewController.swift |
|
|
|
// . . . |
|
|
|
// MARK: Delegate for the web view navigation events. |
|
extension ViewController: WKNavigationDelegate { |
|
// . . . |
|
|
|
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { |
|
print("Navigation—action URL: ", navigationAction.request.url?.absoluteString ?? "") |
|
|
|
/** |
|
Handling the redirect from the authorization endpoint. |
|
|
|
Alternatively, for a custom URI scheme, one could use WKURLSchemeHandler; for example: |
|
let configuration = WKWebViewConfiguration() |
|
configuration.setURLSchemeHandler(your-class-adopting-the-WKURLSchemeHandler-protocol, forURLScheme: redirectionUriScheme) |
|
webView = WKWebView(frame: webViewFrame, configuration: configuration) |
|
*/ |
|
if navigationAction.request.url?.absoluteString.starts(with: redirectionUri) ?? false { |
|
print("Redirection URI: ", navigationAction.request.url?.absoluteString ?? "") |
|
|
|
/** |
|
Redirection URI query parameters. |
|
*/ |
|
var parameters: [String : String] = [:] |
|
|
|
if let urlComponents = URLComponents(url: navigationAction.request.url!, resolvingAgainstBaseURL: false) { |
|
let queryItems: [URLQueryItem]? = urlComponents.queryItems |
|
|
|
if let queryItems = queryItems { |
|
parameters = queryItems.reduce(into: parameters) {result, queryItem in |
|
result[queryItem.name] = queryItem.value |
|
} |
|
} |
|
} |
|
|
|
// Checking if the web view is associated with an OIDAuthorizationRequest. |
|
if let oidAuthorizationRequest = oidAuthorizationRequest { |
|
// Creating an OIDAuthorizationResponse to initiate token exchange request with. |
|
let oidAuthorizationResponse = OIDAuthorizationResponse(request: oidAuthorizationRequest, parameters: parameters as [String : NSCopying & NSObjectProtocol]) |
|
|
|
// Verifying that the state in the response matches the state in the request. |
|
if oidAuthorizationRequest.state == oidAuthorizationResponse.state, let _ = oidAuthorizationResponse.authorizationCode { |
|
// Saving the response in the authentication state object. |
|
let authState = OIDAuthState(authorizationResponse: oidAuthorizationResponse) |
|
|
|
// Saving the authorization state. |
|
setAuthState(authState) |
|
|
|
// Performing the token exchange and providing the callback on completion. |
|
makeTokenRequest() { |
|
authState, error in |
|
|
|
self.authorizationCompletion?(authState, error) |
|
} |
|
} else { |
|
setAuthState(nil) |
|
} |
|
|
|
decisionHandler(.cancel) |
|
|
|
view.viewWithTag(webViewTag)?.removeFromSuperview() |
|
|
|
webViewController = nil |
|
|
|
return |
|
} |
|
} |
|
|
|
// Allowing navigation to and saving cookies from the issuer site. |
|
if navigationAction.request.url?.host == (URL(string: issuerUrl))?.host { |
|
decisionHandler(.allow) |
|
|
|
// Capturing (authentication) cookies when they are present—after signing in at the authentication endpoint. |
|
WKWebsiteDataStore.default().httpCookieStore.getAllCookies() { |
|
cookies in |
|
|
|
let cookies = cookies.filter { |
|
self.appGroupCookies.contains($0.name) |
|
} |
|
|
|
guard cookies.count > 0 else { |
|
return |
|
} |
|
|
|
self.webViewController.saveCookies(cookies) |
|
} |
|
|
|
return |
|
} |
|
|
|
print("Cancelling navigation to: ", navigationAction.request.url?.absoluteString ?? "") |
|
|
|
decisionHandler(.cancel) |
|
} |
|
|
|
// . . . |
|
} |