authenticate method
Authenticates a user using an identityToken and authorizationCode.
If the external user ID is not yet known in the system, a new AuthUser
is created for it.
Implementation
Future<AppleAuthSuccess> authenticate(
final Session session, {
required final String identityToken,
required final String authorizationCode,
/// Whether the sign-in was triggered from a native Apple platform app.
///
/// Pass `false` for web sign-ins or 3rd party platforms like Android.
required final bool isNativeApplePlatformSignIn,
final String? firstName,
final String? lastName,
required final Transaction? transaction,
}) async {
final verifiedIdentityToken = await _signInWithApple.verifyIdentityToken(
identityToken,
useBundleIdentifier: isNativeApplePlatformSignIn,
nonce: null,
);
// TODO(https://github.com/serverpod/serverpod/issues/4105):
// Handle the edge-case where we already know the user, but they
// disconnected and now "registered" again, in which case we need to
// receive and store the new refresh token.
var appleAccount = await AppleAccount.db.findFirstRow(
session,
where: (final t) => t.userIdentifier.equals(
verifiedIdentityToken.userId,
),
transaction: transaction,
);
final createNewAccount = appleAccount == null;
final AuthUserModel authUser = switch (createNewAccount) {
true => await _authUsers.create(
session,
transaction: transaction,
),
false => await _authUsers.get(
session,
authUserId: appleAccount!.authUserId,
),
};
if (createNewAccount) {
final refreshToken = await _signInWithApple.exchangeAuthorizationCode(
authorizationCode,
useBundleIdentifier: isNativeApplePlatformSignIn,
);
appleAccount = await AppleAccount.db.insertRow(
session,
AppleAccount(
userIdentifier: verifiedIdentityToken.userId,
refreshToken: refreshToken.refreshToken,
refreshTokenRequestedWithBundleIdentifier:
isNativeApplePlatformSignIn,
email: verifiedIdentityToken.email?.toLowerCase(),
isEmailVerified: verifiedIdentityToken.emailVerified,
isPrivateEmail: verifiedIdentityToken.isPrivateEmail,
authUserId: authUser.id,
firstName: firstName,
lastName: lastName,
),
transaction: transaction,
);
}
final AppleAccountDetails details = (
userIdentifier: appleAccount.userIdentifier,
email: appleAccount.email,
isVerifiedEmail: appleAccount.isEmailVerified,
isPrivateEmail: appleAccount.isPrivateEmail,
firstName: appleAccount.firstName,
lastName: appleAccount.lastName,
);
return (
appleAccountId: appleAccount.id!,
authUserId: appleAccount.authUserId,
details: details,
newAccount: createNewAccount,
scopes: authUser.scopes,
);
}