0

Dev environment: MacbookPro, Ventura 13.0.1 XCode 14.1

I’m implementing a feature for an existing MacOS application, which will allow users to launch Zoom (and eventually, other 3rd party services) from the application. I'm trying to implement OAuth2 via ASWebAuthenticationSession and Universal Links, and using an https-based redirect URI. It isn't quite working as expected and doesn't work when Chrome is the default browser.

In the app delegate, I’ve implemented the Universal Links handler:

//Objective C
- (BOOL)application:(NSApplication *)application
 continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray<id<NSUserActivityRestoring>> *restorableObjects))restorationHandler
{
  if ([userActivity.activityType isEqualToString: NSUserActivityTypeBrowsingWeb]) {
    NSURL *url = userActivity.webpageURL;
    if ([url.path containsString:[NSString stringWithStdString:Zoom::kFragment]])
    {
      std::string urlStr((url.absoluteString).stdString); //DBG
      DialogFactory::GetInstance()->Message("Universal links handler - AppDelegate: Handling response: " + urlStr); //DBG
      return YES;
    }
  }
  return NO;
}

And here’s the code for the view controller extension which conforms to ASWebAuthenticationPresentationContextProviding:

//Swift
@objc extension ViewController : ASWebAuthenticationPresentationContextProviding {
     
  @objc public func userLogin(){
    guard let oauthMgr : ZoomOAuthMgr = self.oauthDelegate else {
      return
    }
     
    guard let authURL = oauthMgr.getAuthURL() else {
      return
    }
     
    guard let scheme = oauthMgr.getScheme() else {
      return
    }
     
    let session = ASWebAuthenticationSession(url: authURL, callbackURLScheme: scheme) { callbackURL, error in
      /* TODO: guard */
      self.handleOAuthResponse(callbackUrl: callbackURL, err: error)
    }
     
    session.presentationContextProvider = self
    session.prefersEphemeralWebBrowserSession = true
    session.start()
  }
   
  func handleOAuthResponse(callbackUrl: URL?, err: Error?) {
    guard callbackUrl != nil else {return}
    guard err == nil else {
      /* TODO: err handling */
      return
    }
     
    guard let url : URLComponents = URLComponents(string: callbackUrl!.absoluteString) else
{return}
    guard let authCode = url.queryItems?.first(where: { $0.name == "code" })?.value else {return}
    /* TODO: request access token */
  }
   
  public func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
    return self.view.window ?? ASPresentationAnchor()
  }
}

Expected behaviour: Starting a new session should launch the user’s default browser and present a login page. After the user is authenticated, the auth server’s response should be redirected to the app, where the session handler passed to ASWebAuthenticationSession handles the response.

Actual behaviour: When Chrome is the default browser, starting a session launches a Chrome window, which closes immediately. So no login page is presented. My session handler receives a copy of authURL that was sent to Chrome. No error is received by the handler or reported in XCode. No crash logs are generated. System logs don’t seem to offer any clues. And I see no evidence of network traffic suggesting the auth request was ever sent to the auth server.

When Safari is the default browser, starting a session launches Safari with the login page. After logging in, instead of redirecting back to the application and invoking my session handler, a 404 page is displayed. Also displayed is a banner near the top of the window, containing an button with instructions: “Open in the MyApp app”. Clicking the button redirects back to the app, and the response, which should populate callbackURL is instead received by the Universal Links handler AppDelegate::application:continueUserActivity:restorationHandler:. The response contains a valid auth code and no error. My session handler never receives the response nor an error. No errors are reported in XCode.

When Firefox is the default browser, Safari is launched instead, and the behaviour is the same as above.

Sanity checks: I've confirmed that

  • universal links are correctly configured and working as expected
  • the scheme argument passed to ASWebAuthenticationSession is simply the string "https". It doesn't contain any special characters and matches authURL’s scheme.
  • my system, including Chrome, is up to date I’ve tried:
  • clearing all cache & cookies, and disabling all extensions on Chrome
  • an alternate https-based redirect
  • implementing ASWebAuthenticationSession in Objective C (same results)

Possible clue: I’ve tried encoding authURL before handing it to ASWebAuthenticationSession, using various character sets, with no success. But if I encode authURL using the following character set:  [urlStr stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLHostAllowedCharacterSet]  - Chrome doesn't crash. Instead it displays a popup with the message “Your connection to this site is not secure”. Screenshot of Chrome's error popup

I’d really appreciate any help getting this working as expected. Or any suggested alternatives for implementing OAuth with https-based redirects for a MacOS app.

Thanks!

Yeine
  • 1

0 Answers0