Web Authentication with iOS AuthenticationServices
07 Jun 2018 by AJ
Last week I started looking into doing OAuth for an iOS application to enable a simple GitHub authentication flow. After my quick research, I discovered there are more than a couple ways to do this authentication, but the newest and easiest way in Swift was the SFAuthenticationSession
that was just introduced in iOS 11.
SFAuthenticationSession
offers an easy API to launch a Safari View Controller to a given sign-in url where the user can authenticate through the web. When the OAuth service returns with the auth token, a simple completion handler is called to handle the response. It’s simple, secure, and really fast to implement.
Here’s my func to authenticate with my GitHub app OctoNotes in Swift:
//...
var authSession: SFAuthenticationSession?
//...
func getAuthToken() {
//OAuth Provider URL
let authURL = URL(string: "https://github.com/login/oauth/authorize?client_id=<client_id>")
let callbackUrlScheme = "octonotes://auth"
//Initialize auth session
self.authSession = SFAuthenticationSession.init(url: authURL!, callbackURLScheme: callbackUrlScheme,
completionHandler: { (callBack:URL?, error:Error?) in
// handle auth response
guard error == nil, let successURL = callBack else {
return
}
let oauthToken = NSURLComponents(string: (successURL.absoluteString))?.queryItems?.filter({$0.name == "code"}).first
// Do what you now that you've got the token, or use the callBack URL
print(oauthToken ?? "No OAuth Token")
})
//Kick it off
self.authSession?.start()
}
Easy enough! An alert gets displayed to the user prompting them to auth, Safari handles it with their input/with the data it already has, then returns you an authenticated token.
But you’ll probably guess if you looked at that link to the SFAuthenticationSession
docs that this isn’t the end of the story.
ASWebAuthenticationSession
On Tuesday at WWDC, in the “Automatic Strong Passwords and Security Code AutoFill” session, Apple announced a new API for authenticating through the web in your iOS apps, and deprecated SFAuthenticationSession
. Short life for this handy API.
Not to fear! The replacement for SFAuthenticationSession
is ASWebAuthenticationSession
, and the new API is very familiar.
Instead of importing SafariServices
, start by importing the new AuthenticationServices
import AuthenticationServices
Then follow the same exact pattern to start a ASWebAuthenticationSession
and handle the callback to retrive your OAuth Token.
//...
var webAuthSession: ASWebAuthenticationSession?
//...
@available(iOS 12.0, *)
func getAuthTokenWithWebLogin() {
let authURL = URL(string: "https://github.com/login/oauth/authorize?client_id=<client_id>")
let callbackUrlScheme = "octonotes://auth"
self.webAuthSession = ASWebAuthenticationSession.init(url: authURL!, callbackURLScheme: callbackUrlScheme, completionHandler: { (callBack:URL?, error:Error?) in
// handle auth response
guard error == nil, let successURL = callBack else {
return
}
let oauthToken = NSURLComponents(string: (successURL.absoluteString))?.queryItems?.filter({$0.name == "code"}).first
// Do what you now that you've got the token, or use the callBack URL
print(oauthToken ?? "No OAuth Token")
})
// Kick it off
self.webAuthSession?.start()
}
Familiar, eh? The new ASWebAuthenticationSession
should enable you to securely authenticate on the web and future-proof your app for any security features involved in web-based login. So while we weep for year-long API’s, at least Apple is making the conversion a breeze.