Sign in With Apple email, firstName, lastName returning nil

I have implemented basic Sign in with Apple functionality to my app. When the app is launched, the user will be presented with a Continue with Apple view, where they can authenticate. Once signed in, they will return to a view that reads "Hello, [User's Name]". However, I cannot seem to figure out why the email and name return nil after authentication. For example, when authentication is successful, the HelloView simply reads "Hello, " with no name. I have it setup so that the users name and email are saved to AppStorage variables, and then inserted into a Profile class with SwiftData.

import AuthenticationServices
import SwiftData
import SwiftUI

struct ContentView: View {
    
    @Environment(\.colorScheme) var colorScheme
    @Environment(\.modelContext) var modelContext
    
    @AppStorage("email") var email: String = ""
    @AppStorage("firstName") var firstName: String = ""
    @AppStorage("lastName") var lastName: String = ""
    @AppStorage("userID") var userID: String = ""
    
    @Query var userProfile: [Profile]
    
    private var isSignedIn: Bool {
        !userID.isEmpty
    }
    
    var body: some View {
        VStack {
            if !isSignedIn {
                SignInView()
            } else {
                HomeView()
            }
        }
    }
}

struct SignInView: View {
    
    @Environment(\.colorScheme) var colorScheme
    @Environment(\.modelContext) var modelContext
    
    @AppStorage("email") var email: String = ""
    @AppStorage("firstName") var firstName: String = ""
    @AppStorage("lastName") var lastName: String = ""
    @AppStorage("userID") var userID: String = ""
    
    @Query var userProfile: [Profile]
    
    var body: some View {
        NavigationStack {
            
            Spacer()
            
            SignInWithAppleButton(.continue) { request in
                request.requestedScopes = [.email, .fullName]
            } onCompletion: { result in
                switch result {
                case .success(let auth):
                    
                    switch auth.credential {
                    case let credential as ASAuthorizationAppleIDCredential:
                        
                        // User ID
                        let userID = credential.user
                        
                        // User Info
                        let email = credential.email
                        print(email!)
                        let firstName = credential.fullName?.givenName
                        print(firstName!)
                        let lastName = credential.fullName?.familyName
                        print(lastName!)
                        
                        self.email = email ?? ""
                        self.userID = userID
                        self.firstName = firstName ?? ""
                        self.lastName = lastName ?? ""
                        
                        createProfile()
                                                
                    default:
                        break
                    }
                case .failure(let error):
                    print("Error signing in with Apple: \(error.localizedDescription)")
                }
            }
            .signInWithAppleButtonStyle(colorScheme == .dark ? .white : .black)
            .frame(height: 50)
            .padding()
            .cornerRadius(12)
            .navigationTitle("[App Name]")
        }
    }
    
    func createProfile() {
        let newProfile = Profile(firstName: firstName, lastName: lastName, email: email, userID: userID)
        modelContext.insert(newProfile)
    }
}

This is how I have my HomeView setup:

import SwiftData
import SwiftUI

struct HomeView: View {
    
    @Environment(\.modelContext) var modelContext
    
    @Query var user: [Profile]
    
    var body: some View {
        ForEach(user) { user in
            Text("Hello, \(user.firstName)")
        }
    }
}

#Preview {
    HomeView()
}

And here's the Profile class:

import Foundation
import SwiftData

@Model
class Profile {
    var firstName: String
    var lastName: String
    var email: String
    var userID: String
    
    init(firstName: String, lastName: String, email: String, userID: String) {
        self.firstName = firstName
        self.lastName = lastName
        self.email = email
        self.userID = userID
    }
}
Answered by DTS Engineer in 805246022

Hi @Carter58,

The user's first and last name are not provided to Apple—they are passed directly to the client in the initial authorization response and not included in the identity token in subsequent responses. Please see the documentation below for more information:

Send information to app servers and verify tokens

Ensure that your app relays the credentials and user information to your app servers. The API collects this information and shares it with your app the first time the user logs in using Sign in with Apple. If the user then uses Sign in with Apple on another device, the API doesn’t ask for the user’s name or email again. It collects the information again only if the user stops using Sign in with Apple and later reconnects to your app.

Although Apple provides the user’s email address in the identity token on all subsequent API responses, it doesn’t include other information about the user, such as their name. When you receive user information from the API response, immediately store it locally so your app can access it again in the event of a process or network failure.

Authenticating users with Sign in with Apple https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773

Cheers,

Paris X Pinkney |  WWDR | DTS Engineer

Hi @Carter58,

The user's first and last name are not provided to Apple—they are passed directly to the client in the initial authorization response and not included in the identity token in subsequent responses. Please see the documentation below for more information:

Send information to app servers and verify tokens

Ensure that your app relays the credentials and user information to your app servers. The API collects this information and shares it with your app the first time the user logs in using Sign in with Apple. If the user then uses Sign in with Apple on another device, the API doesn’t ask for the user’s name or email again. It collects the information again only if the user stops using Sign in with Apple and later reconnects to your app.

Although Apple provides the user’s email address in the identity token on all subsequent API responses, it doesn’t include other information about the user, such as their name. When you receive user information from the API response, immediately store it locally so your app can access it again in the event of a process or network failure.

Authenticating users with Sign in with Apple https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773

Cheers,

Paris X Pinkney |  WWDR | DTS Engineer

Sign in With Apple email, firstName, lastName returning nil
 
 
Q