Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Tak783/446b4921cf0894f031eacbd641122928 to your computer and use it in GitHub Desktop.

Select an option

Save Tak783/446b4921cf0894f031eacbd641122928 to your computer and use it in GitHub Desktop.
import UIKit
import SafariServices
import AuthenticationServices
import AppAuth
import Reachability
class OIDExternalUserAgentASWebAuthenticationSession: NSObject, OIDExternalUserAgent {
private let presentingViewController: UIViewController
private var externalUserAgentFlowInProgress: Bool = false
private var authenticationViewController: ASWebAuthenticationSession?
private weak var session: OIDExternalUserAgentSession?
init(with presentingViewController: UIViewController) {
self.presentingViewController = presentingViewController
super.init()
}
func present(_ request: OIDExternalUserAgentRequest, session: OIDExternalUserAgentSession) -> Bool {
if externalUserAgentFlowInProgress {
return false
}
guard let requestURL = request.externalUserAgentRequestURL() else {
return false
}
self.externalUserAgentFlowInProgress = true
self.session = session
var openedUserAgent = false
// ASWebAuthenticationSession doesn't work with guided access (Search web for "rdar://40809553")
// Make sure that the device is not in Guided Access mode "(Settings -> General -> Accessibility -> Enable Guided Access)"
if UIAccessibility.isGuidedAccessEnabled == false {
let redirectScheme = request.redirectScheme()
let authenticationViewController = ASWebAuthenticationSession(url: requestURL, callbackURLScheme: redirectScheme) { (callbackURL, error) in
self.authenticationViewController = nil
if let url = callbackURL {
self.session?.resumeExternalUserAgentFlow(with: url)
} else {
let webAuthenticationError = OIDErrorUtilities.error(with: OIDErrorCode.userCanceledAuthorizationFlow,
underlyingError: error,
description: nil)
self.session?.failExternalUserAgentFlowWithError(webAuthenticationError)
}
}
authenticationViewController.presentationContextProvider = self
/// ** Key Line of code -> `.prefersEphemeralWebBrowserSession`** allows for private browsing
authenticationViewController.prefersEphemeralWebBrowserSession = true
self.authenticationViewController = authenticationViewController
openedUserAgent = authenticationViewController.start()
} else {
let webAuthenticationError = OIDErrorUtilities.error(with: OIDErrorCode.safariOpenError,
underlyingError: AuthenticationManager.AuthenticationError.appInGuidedAccessMode,
description: nil)
self.session?.failExternalUserAgentFlowWithError(webAuthenticationError)
}
return openedUserAgent
}
func dismiss(animated: Bool, completion: @escaping () -> Void) {
// Ignore this call if there is no authorization flow in progress.
if externalUserAgentFlowInProgress == false {
completion()
}
cleanUp()
if authenticationViewController != nil {
authenticationViewController?.cancel()
completion()
} else {
completion()
}
return
}
}
extension OIDExternalUserAgentASWebAuthenticationSession {
/// Sets class variables to nil. Note 'weak references i.e. session are set to nil to avoid accidentally using them while not in an authorization flow.
func cleanUp() {
session = nil
authenticationViewController = nil
externalUserAgentFlowInProgress = false
}
}
extension OIDExternalUserAgentASWebAuthenticationSession: ASWebAuthenticationPresentationContextProviding {
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
return presentingViewController.view.window!
}
}
@Tak783
Copy link
Copy Markdown
Author

Tak783 commented May 16, 2020

Call Like this
let sceneDelegate = viewController.view.window?.windowScene?.delegate as? SceneDelegate
let externalAgent = OIDExternalUserAgentASWebAuthSession(with: viewController)
sceneDelegate?.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, externalUserAgent: externalAgent, callback: { authState, error in
handleAuthState(authState, error, completion)
})

@iBolom
Copy link
Copy Markdown

iBolom commented Sep 21, 2020

"prefersEphemeralWebBrowserSession" is only available on iOS 13 and later. Is there any other solution so it works on lower iOS versions?

@ast3150
Copy link
Copy Markdown

ast3150 commented Oct 8, 2020

Just add if #available(iOS 13, *) {...} around the line setting prefersEphemeralWebBrowserSession.

@iBolom
Copy link
Copy Markdown

iBolom commented Oct 8, 2020

i mean is there any solution to make permission dialog not appearing on lower versions than iOS 13.

@ast3150
Copy link
Copy Markdown

ast3150 commented Oct 8, 2020

Depending on the scenario you could use SFSafariViewController as an external user agent, check the discussion here: openid/AppAuth-iOS#402

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment