Sign in to websites in your SwiftUI app


Sign in to websites in your SwiftUI app

Many Swift apps require access to an online account. A person using your app must sign into a website to give your app access to the account. How do you let the person sign in from your app?

Apple provides a class, ASWebAuthenticationSession, to simplify signing into a website from an iOS or Mac app. When you create and start an instance of ASWebAuthenticationSession, a private browser window opens for someone to sign into a website. After signing in, ASWebAuthenticationSession takes you back to your app.

You must perform the following tasks to use ASWebAuthenticationSession in a SwiftUI app:

  • Add a custom URL type for your app.
  • Create a class for your login session.
  • Add a presentation anchor.
  • Create an ASWebAuthenticationSession instance.
  • Create a SwiftUI view to handle the sign in.

Create a custom URL type

When someone finishes logging in to the website, they should go back to your app. You must add a URL type to your app to go back to the app.

Select your app target from the project editor and click the Info button at the top of the project editor to add a URL type to the app.

Give your URL type a name in the Identifier text field. Enter the URL type in the URL Schemes text field. The URL type should take the following form:

appname://

Create a class for your login session

To use ASWebAuthenticationSession you must add a class to hold the login session.

import AuthenticationServices
class LoginSession: NSObject, 
  ObservableObject, 
  ASWebAuthenticationPresentationContextProviding {
  var webAuthSession: ASWebAuthenticationSession?
}

The ASWebAuthenticationSession class is part of the Authentication Services framework so you must import that framework.

The class must conform to the ASWebAuthenticationPresentationContextProviding protocol. Inheriting from NSObject is the easiest way to conform to the protocol.

Conforming to ObservableObject lets you pass the session to another SwiftUI view.

The class needs a property of type ASWebAuthenticationSession to run the login session.

Add a presentation anchor

The login session requires a presentation anchor, which is a window to show the login session so people can sign in. Add the following function to your login session class:

func presentationAnchor(for session: 
  ASWebAuthenticationSession) -> ASPresentationAnchor {
  return ASPresentationAnchor()
}

ASPresentationAnchor is an instance of UIWindow on iOS and an instance of NSWindow on Mac.

Create an ASWebAuthenticationSession instance

Now you can create an instance of ASWebAuthenticationSession. You must supply the following arguments:

  • The URL of the website to log in.
  • The callback URL, the URL to go when the login session finishes.
  • A completion handler closure (function) that runs when the session finishes successfully.

The callback URL is the custom URL type you created for the app, minus the ://.

appname

The following code creates the session:

webAuthSession = ASWebAuthenticationSession.init(
  url: websiteURL, 
  callbackURLScheme: callbackURL, 
  completionHandler: { (callback:URL?, error:Error?) in
  // Do what you need to after someone logs in.
})
// Run the session
webAuthSession?.presentationContextProvider = self
webAuthSession?.prefersEphemeralWebBrowserSession = true
webAuthSession?.start()

Add a login function to the LoginSession class and add this code to the function. You will have to add code for the websiteURL and callbackURL variables, as these depend on the website where you want to sign in and your app's custom URL.

You should use ephemeral web browser sessions. If you set prefersEphemeralWebBrowserSession to false, information from previous sessions will be available in the session.

If you need to make any async calls in the completion handler, wrap them in a Task block. ASWebAuthenticationSession does not support Swift’s async await concurrency features.

Task {
  // Put async calls here
}

Create a login view

After creating the class to handle the login session, you can create a SwiftUI view for people to sign in. The following code shows an example of a simple login view:

struct LoginView: View {
  @StateObject var session = LoginSession()
  @Environment(\.presentationMode) var presentationMode
	 
  var body: some View {
    VStack {
      Image(systemName: "person.circle")
        .resizable()
        .frame(width: 64, height: 64)
        .padding()
      Text("You need to sign in.")
        .padding()
      Button {
        login()
      } label: {
        Text("Sign In")
      }
    }
    .frame(width: 256, height: 256, alignment: .topLeading)
  }    
}
extension LoginView {
  func login() {
    session.login()
    presentationMode.wrappedValue.dismiss()
  }    
}

The view code uses the @StateObject property wrapper to store the login session because the session is a class that conforms to ObservableObject. The view has a Sign In button. When the person taps or clicks that button, the login session starts, and the person can sign in to the website.

Additional reading

The following articles provide more information:

Swift Dev Journal

Subscribe and get exclusive articles on Swift development, a free guide on moving from tutorials to making your first app, notices of sales on books, and anything I decide to add in the future.

Read more from Swift Dev Journal

If you find your app becomes unresponsive at times, it can be frustrating to find the cause. Instruments includes a Hangs instrument that reports hangs to help you find and fix hangs. This article shows you how to use the Hangs and Time Profiler instruments to find hangs and find the code causing the hangs. Profiling Your App In Xcode press Cmd-I to build and profile your app with Instruments. When Instruments launches, it will ask you to choose a template for profiling. Select the Time...

Saving App Data in Property List Files Your app needs to save data. There's too much data to use User Defaults. Using SwiftData or Core Data would be overkill. One solution is to save the data in property list files. This article shows you how to save your app's data in property list files. Use the PropertyListEncoder Class if you can If the data you want to save conforms to the Codable protocol, use the PropertyListEncoder class to save the data. Encoding data with PropertyListEncoder...

Working with Lists in Multiplatform SwiftUI Apps One of SwiftUI's best features is you can use it to make apps that run on both iOS and Mac. Almost every SwiftUI article you find online is about iOS development, but most of the material also applies to Mac as well. Lists are one area of SwiftUI where there are large differences between iOS and Mac. If you read an article about lists and try to use the code in a Mac app, you'll run into problems. This article provides guidance on writing list...