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.
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")
}
}
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...
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.
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")
}
}
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")
}
}
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
func application(_ application: NSApplication, open urls: [URL])
implemented in my AppDelegate (turns out this really is enough as @Aaron Raimist was sayingThanks for your help; hope this might help anybody else (or my future self) down the road :-)