The last piece of the puzzle is implementing the logic for completing the Sign in with Apple flow.
In the Vapor app, open WebiteController.swift and add a new request handler, appleAuthRedirectHandler(_:) that returns a Response:
func appleAuthRedirectHandler(_ req: Request) async throws -> Response {
}
First, decode the request body to SIWARedirectData - this matches the data sent in the form in the previous video:
let data = try req.content.decode(SIWARedirectData.self)
Next, get the application identifier from the environment variables that you set up when you configured the website in the Apple Developer Portal. Note that this is different to the app identifier used for the iOS app:
guard let appIdentifier = Environment.get("WEBSITE_APPLICATION_IDENTIFIER") else {
throw Abort(.internalServerError)
}
Then, verify the token provided to ensure it’s a valid JWT:
let siwaToken = try await req.jwt.apple.verify(data.token, applicationIdentifier: appIdentifier)
Once you’ve passed this point you have a JWT you know came from Apple with a valid and authenticated user.
Next, see if an user exists with the Sign in with Apple identifier:
let user: User
if let userFound = try await User.query(on: req.db).filter(\.$siwaIdentifier == siwaToken.subject.value).first() {
user = userFound
} else {
}
If the user doesn’t exist, search for them with their email to see if they are an existing user or not:
guard let email = data.email, let firstName = data.firstName, let lastName = data.lastName else {
throw Abort(.badRequest)
}
if let existingUser = try await User.query(on: req.db).filter(\.$username == email).first() {
} else {
}
If the user already exists, update their Sign in with Apple identifier and save the user:
user = existingUser
user.siwaIdentifier = siwaToken.subject.value
try await user.save(on: req.db)
If the user is a new user, create the user and save them in the database:
let newUser = User(name: "\(firstName) \(lastName)", username: email, password: UUID().uuidString, siwaIdentifier: siwaToken.subject.value)
try await newUser.save(on: req.db)
user = newUser
Finally, log them in and redirect to the homepage:
req.auth.login(user)
return req.redirect(to: "/")
Register the route as a POST request to /login/siwa/handle in boot(_:):
authSessionsRoutes.post("login", "siwa", "handle", use: appleAuthRedirectHandler)
Build and run the app and then go to the URL from Ngrok in your browser. Make sure it matches the URL set in the developer portal and the environment variables.
Click Create an Acronym and you’ll be taken to the log in page. Click Sign in with Apple and complete the flow to log in. Click again on Create an Acronym and you’ll be taken to the create page now that you’re logged in. Congratulations! You’ve signed in with Apple on a website!