xcodecocoawkwebviewciscowebex

Custom redirect URI to macOS app not working


Purpose of the redirect

I am working on an application that integrates with Cisco's Webex Teams Api. Unfortunately, for macOS they don't have an SDK (they only do have one for iOS), so I am trying to authenticate with their Api kind of "manually".

So, I am using a custom URL that has a client id backed in to retrieve a code. When calling this URL, Cisco's regular login procedure starts, asking the user to log in with her / his username an password. Upon successful login, Cisco's server provide you with a URL that includes a code that is then needed to proceed.

What I got so far

Custom url

My prototype currently just consists of a button that calls a custom URL to authenticate. To get this URL, I needed to register my integration with Cisco here: https://developer.webex.com/my-apps

So far, when I click on my button, a WKWebView instance takes over with my custom URL:

https://api.ciscospark.com/v1/authorize?client_id=<**personalClientId**>&response_type=code&redirect_uri=<**BundleIdentifier**>3A%2F%2Fredirect&scope=spark%3Aall%20spark%3Akms&state=set_state_here

Redirect URI

So, my redirect uri currently is ch.appfros.webexoauthwokflowprototype://redirect; this redirect uri is registered with Cisco in my integration registration form.

I am aware that I have to put this redirect uri into my app, so I did that resulting in the corresponding info.plist section looking like this:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>response</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>ch.appfros.webexoauthwokflowprototype://</string>
        </array>
    </dict>
</array>

Preparing the AppDelegate

As I far as I currently have found out, it seems that I need to also have an additional function in my AppDelegate, that handles the callback. For cocoa, this seems to be the func application(_ application: NSApplication, open urls: [URL]) method.

As far as I understand it, i would have to handle all redirects there. My AppDelegate currently looks like this:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {



    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application)
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

    func application(_ application: NSApplication, open urls: [URL]) {
        print("got answer")
    }

}

The issue I am having

My problem is, fulfilling the login procedure results in the message There is no application set to open the URL ch.appfros.webexoauthwokflowprototype://redirect?code=&state=loggedIn.

So, the authentication process on Cisco's end is successful and it provides my system with the URL -- which my computer does not know how to handle... I can even see the code I need to retreive an access in the URL that is coming back, I just don't have them within my application to proceed...

What am I missing?

It's quite obvious that I am missing something crucial here -- I just don't know what it is and researching online wouldn't help me. I could find bits and pieces here and there, but I am still to find a concise instruction on what to do in my case for my macOS app.

Environment

Edit: changes to AppDelegate

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {



    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application)
         NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleAppleEvent(event:replyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

    func application(_ application: NSApplication, open urls: [URL]) {
        print("got answer")
    }

    @objc
    func handleAppleEvent(event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
        print("got answer in event handler")
    }

}

Edit 2: update to AppDelegate (to reflect hints and tips by NoHalfBits)

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {



    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application)

    }

    func applicationWillFinishLaunching(_ notification: Notification) {
        NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleAppleEvent(event:replyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

    func application(_ application: NSApplication, open urls: [URL]) {
        print("got answer")
    }

    @objc
    func handleAppleEvent(event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
        print("got answer in event handler")
    }

}

Solution

  • Turns out that sandboxing really was the problem. After disabling Sandboxing -- this is going to be a small in house helper at my comanpy, nothing fancy and for sure nothing for any store -- it worked right away.

    If need be I will have to take a look into how NSAppTransportSecurity would be needed to get implemented -- thanks to @NoHalfBits for pushing me into the right direction.

    So now I have

    Thanks for your help; hope this might help anybody else (or my future self) down the road :-)