Authentication

by dpearson26998d90fd121a26No license1.1K starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 2 months ago

Implement iOS authentication flows with AuthenticationServices and LocalAuthentication. Use when building Sign in with Apple, passkey/WebAuthn registration or sign-in with ASAuthorizationPlatformPublicKeyCredentialProvider, ASAuthorizationController credential state and revocation handling, ASWebAuthenticationSession OAuth or third-party login, Password AutoFill, identity-token server validation, or local biometric re-authentication with LAContext.

AI-generated overview

Guides iOS authentication implementation with AuthenticationServices and LocalAuthentication, covering Sign in with Apple, passkeys, OAuth and biometrics.

What it does
Provides instructions and code patterns for implementing iOS authentication flows: Sign in with Apple via ASAuthorizationController, passkey/WebAuthn registration and assertion, ASWebAuthenticationSession OAuth, Password AutoFill, credential state and revocation handling, identity-token server validation, and local biometric re-authentication with LAContext. It also includes common mistakes and a review checklist, plus reference files on passkeys and Keychain/biometric patterns.
When to use it
Use when building or reviewing iOS authentication features such as Sign in with Apple, passkeys, third-party OAuth login, Password AutoFill, or biometric re-authentication. It is aimed at Swift/UIKit and SwiftUI app code that integrates Apple's authentication frameworks.
Requirements
No scripts; instructions and reference documents only. Requires an iOS/Xcode project with the Sign in with Apple capability, Associated Domains for passkeys, and NSFaceIDUsageDescription for biometrics; server-side token validation is described but not provided.

Authentication

Implement authentication flows on iOS using the AuthenticationServices framework, including Sign in with Apple, passkeys, OAuth/third-party web auth, Password AutoFill, and biometric re-authentication.

Contents

Sign in with Apple

Add the "Sign in with Apple" capability in Xcode before using these APIs.

UIKit: ASAuthorizationController Setup

swift
import AuthenticationServices
final class LoginViewController: UIViewController {    func startSignInWithApple() {        let provider = ASAuthorizationAppleIDProvider()        let request = provider.createRequest()        request.requestedScopes = [.fullName, .email]
        let controller = ASAuthorizationController(authorizationRequests: [request])        controller.delegate = self        controller.presentationContextProvider = self        controller.performRequests()    }}
extension LoginViewController: ASAuthorizationControllerPresentationContextProviding {    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {        view.window!    }}

Delegate: Handling Success and Failure

swift
extension LoginViewController: ASAuthorizationControllerDelegate {    func authorizationController(        controller: ASAuthorizationController,        didCompleteWithAuthorization authorization: ASAuthorization    ) {        guard let credential = authorization.credential            as? ASAuthorizationAppleIDCredential else { return }
        let userID = credential.user  // Stable, unique, per-team identifier        let email = credential.email  // nil after first authorization        let fullName = credential.fullName  // nil after first authorization        let identityToken = credential.identityToken  // JWT for server validation        let authCode = credential.authorizationCode  // Short-lived code for server exchange
        // Save userID to Keychain for credential state checks        // See references/keychain-biometric.md for Keychain patterns        saveUserID(userID)
        // Send identityToken and authCode to your server        authenticateWithServer(identityToken: identityToken, authCode: authCode)    }
    func authorizationController(        controller: ASAuthorizationController,        didCompleteWithError error: any Error    ) {        switch (error as? ASAuthorizationError)?.code {        case .canceled, .notInteractive:            break        case .failed:            showError("Authorization failed")        default:            showError("Authorization failed: \(error.localizedDescription)")        }    }}

Credential Handling

Credential dataRequired handling
userPersist this stable, per-team identifier for credential-state checks.
email, fullNameThese optional values arrive only on first authorization; cache them immediately.
identityToken, authorizationCodeSend them to the server for validation or exchange; never trust them as client-side proof.

Treat realUserStatus only as a fraud-prevention signal, not authentication proof.

Credential State Checking

Check credential state on every app launch. The user may revoke access at any time via Settings > Apple Account > Sign-In & Security.

swift
func checkCredentialState() {    let provider = ASAuthorizationAppleIDProvider()    guard let userID = loadSavedUserID() else {        showLoginScreen()        return    }
    provider.getCredentialState(forUserID: userID) { state, _ in        DispatchQueue.main.async {            switch state {            case .authorized:                proceedToMainApp()            case .revoked:                // User revoked -- sign out and clear local data                signOut()                showLoginScreen()            case .notFound:                showLoginScreen()            case .transferred:                // App transferred to new team -- migrate user identifier                migrateUser()            @unknown default:                showLoginScreen()            }        }    }}

Credential Revocation Notification

swift
NotificationCenter.default.addObserver(    forName: ASAuthorizationAppleIDProvider.credentialRevokedNotification,    object: nil,    queue: .main) { _ in    // Sign out immediately    AuthManager.shared.signOut()}

Token Validation

The identityToken is a JWT. Send it to your server for validation -- never trust it client-side alone.

Server-side, validate the JWT against Apple's public keys at https://appleid.apple.com/auth/keys (JWKS). Verify: iss is https://appleid.apple.com, aud matches your bundle ID, and exp has not passed. Exchange the short-lived authorization code on the server and store the resulting app session token in Keychain.

Existing Account Setup Flows

On launch, silently check for existing Sign in with Apple and password credentials before showing a login screen:

swift
func performExistingAccountSetupFlows() {    let appleIDRequest = ASAuthorizationAppleIDProvider().createRequest()    let passwordRequest = ASAuthorizationPasswordProvider().createRequest()
    let controller = ASAuthorizationController(        authorizationRequests: [appleIDRequest, passwordRequest]    )    controller.delegate = self    controller.presentationContextProvider = self    controller.performRequests(        options: .preferImmediatelyAvailableCredentials    )}

Call this in viewDidAppear or on app launch. If no existing credentials are found, the delegate receives a .notInteractive error -- handle it silently and show your normal login UI.

Passkeys

Use passkeys only for a relying-party domain configured with a webcredentials: Associated Domain and AASA entry. Registration and assertion each require a fresh server challenge, an ASAuthorizationPlatformPublicKeyCredentialProvider, an authorization controller with an active presentation anchor, and server-side verification before issuing a session.

Load references/passkeys.md [blocked] for the canonical registration, assertion, result handling, AutoFill-assisted, and physical security-key flows.

ASWebAuthenticationSession (OAuth)

Use ASWebAuthenticationSession for OAuth and third-party authentication (Google, GitHub, etc.). Never use WKWebView for auth flows.

swift
import AuthenticationServices
final class OAuthController: NSObject, ASWebAuthenticationPresentationContextProviding {    private weak var presentationAnchor: ASPresentationAnchor?
    init(presentationAnchor: ASPresentationAnchor) {        self.presentationAnchor = presentationAnchor    }
    func startOAuthFlow() {        let authURL = URL(string:            "https://provider.com/oauth/authorize?client_id=YOUR_ID&redirect_uri=myapp://callback&response_type=code"        )!        let session = ASWebAuthenticationSession(            url: authURL, callback: .customScheme("myapp")        ) { callbackURL, error in            guard let callbackURL, error == nil,                  let code = URLComponents(url: callbackURL, resolvingAgainstBaseURL: false)?                      .queryItems?.first(where: { $0.name == "code" })?.value else { return }            Task { await self.exchangeCodeForTokens(code) }        }        session.presentationContextProvider = self        session.prefersEphemeralWebBrowserSession = true  // No shared cookies        session.start()    }
    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {        guard let presentationAnchor else {            fatalError("ASWebAuthenticationSession needs the active window")        }        return presentationAnchor    }}

In SwiftUI, use @Environment(\.webAuthenticationSession) and call authenticate(using:callback:preferredBrowserSession:additionalHeaderFields:) with .customScheme("myapp") or .https(host:path:); prefer .ephemeral only when the provider flow should avoid shared browser cookies.

Password AutoFill Credentials

Offer ASAuthorizationPasswordProvider alongside Sign in with Apple using the single controller in Existing Account Setup Flows. Handle ASPasswordCredential in that controller's delegate.

Set textContentType on text fields for AutoFill to work:

swift
usernameField.textContentType = .usernamepasswordField.textContentType = .password

Biometric Authentication

Use LAContext from LocalAuthentication for local re-authentication before showing account settings or starting sensitive actions. Do not treat a returned Bool as proof to unlock a stored secret; protect secrets with Keychain access control instead. See references/keychain-biometric.md [blocked] for the canonical LAContext, fallback, SecAccessControl, and .biometryCurrentSet patterns.

Required: Add NSFaceIDUsageDescription to Info.plist. Missing this key crashes on Face ID devices.

Security Boundaries

This skill owns user-facing account authentication: Sign in with Apple, passkeys, Password AutoFill, ASAuthorizationController, OAuth session presentation, credential state, and local biometric re-authentication. Route deep security work to swift-security: Keychain architecture/migration, CryptoKit, Secure Enclave, certificate pinning/trust, keychain sharing, storage hardening, and OWASP MASVS/MASTG. Keep only the storage minimum here: tokens and secrets belong in Keychain; LAContext.evaluatePolicy alone must not release protected secrets.

SwiftUI SignInWithAppleButton

Use SignInWithAppleButton in SwiftUI views when the login surface is SwiftUI. Request .fullName and .email, downcast a successful result to ASAuthorizationAppleIDCredential, and pass it to the shared Token Validation flow. Style with .signInWithAppleButtonStyle(...).

Common Mistakes

  • Assuming a saved local session means the Apple ID credential is still valid. Check credential state at launch and handle revocation notifications.
  • Showing a full login screen before trying existing account setup flows. Treat .notInteractive as the normal "no local credential" path.
  • Force-unwrapping email or fullName. Cache them on first authorization and handle nil later.
  • Creating an ASAuthorizationController without a presentation context provider. Authorization UI needs the active presentation anchor.
  • Storing identity tokens, authorization codes, access tokens, passwords, or passkey server state in UserDefaults, files, or Core Data. Store secrets in Keychain and keep relying-party passkey verification server-side.
  • Adding passkey requests without webcredentials: Associated Domains for the relying-party domain, or trying to use app-native passkeys for unrelated websites.
  • Expanding authentication work into CryptoKit, Secure Enclave, certificate pinning, or OWASP MASVS. Route those to swift-security.

Review Checklist

  • "Sign in with Apple" capability added in Xcode project
  • ASAuthorizationControllerPresentationContextProviding implemented
  • Credential state checked on every app launch (getCredentialState(forUserID:completion:))
  • credentialRevokedNotification observer registered; sign-out handled
  • email and fullName cached on first authorization (not assumed available later)
  • identityToken sent to server for validation, not trusted client-side only
  • Tokens stored in Keychain, not UserDefaults or files
  • performExistingAccountSetupFlows called before showing login UI
  • Error cases handled: .canceled, .failed, .notInteractive
  • NSFaceIDUsageDescription in Info.plist for biometric auth
  • ASWebAuthenticationSession used for OAuth (not WKWebView)
  • prefersEphemeralWebBrowserSession set for OAuth when appropriate
  • textContentType set on username/password fields for AutoFill
  • Passkey relying party has webcredentials: Associated Domains configured
  • Passkey registration/assertion challenges come from the server and are verified server-side
  • Deep Keychain, CryptoKit, Secure Enclave, certificate pinning, and MASVS work routed to swift-security

References

Source and attribution

Source:dpearson2699/swift-ios-skillsinskills/authenticationat commit8d90fd1

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal

More from dpearson2699/swift-ios-skills

Widgetkit

dpearson2699

Guides implementing, reviewing, and improving WidgetKit widgets and controls for iOS, iPadOS, watchOS, and CarPlay.

Software Development1.1Kupdated 2 months ago

Weatherkit

dpearson2699

Guides iOS developers in fetching WeatherKit forecasts, alerts, and attribution using WeatherService.

Software Development1.1Kupdated 2 months ago

Vision Framework

dpearson2699

Implement computer vision features including text recognition (OCR), face detection, barcode scanning, image segmentation, object tracking, and document scanning in iOS apps. Covers both the modern Swift-native Vision API (iOS 18+) and legacy VNRequest patterns, VisionKit DataScannerViewController for live camera scanning, and CoreMLRequest/VNCoreMLRequest for custom model inference. Use when adding OCR, barcode scanning, face detection, or custom Core ML model inference with Vision.

Awaiting classification1.1Kupdated 2 months ago

Tipkit

dpearson2699

Implement and review Apple TipKit feature-discovery UI for iOS 17+ apps. Use when adding or auditing in-app tips, contextual help, coach marks, Tip, TipView, popoverTip, rules, events, actions, display frequency, testing overrides, reusable tip identifiers, or iOS 18+ TipGroup and CloudKit tip sync; avoid for generic SwiftUI navigation or layout outside tip presentation.

Awaiting classification1.1Kupdated 2 months ago

Tabletopkit

dpearson2699

Guides building multiplayer spatial board games on visionOS with Apple's TabletopKit and RealityKit.

Software Development1.1Kupdated 2 months ago

Swiftui Webkit

dpearson2699

Guides embedding and controlling web content in SwiftUI apps with WebKit for SwiftUI on iOS 26 and later.

Software Development1.1Kupdated 2 months ago
Authentication Agent Skill | SourceWeft