Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Tak783/446b4921cf0894f031eacbd641122928 to your computer and use it in GitHub Desktop.
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
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

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

ast3150 commented Oct 8, 2020

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

@iBolom
Copy link

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

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