login method

Future<AuthSuccess> login(
  1. Session session, {
  2. required String code,
  3. required String codeVerifier,
  4. required String redirectUri,
  5. Transaction? transaction,
})

Validates a GitHub authorization code and either logs in the associated user or creates a new user account if the GitHub account ID is not yet known.

This method exchanges the authorization code for an access token using PKCE, then authenticates the user.

If a new user is created an associated UserProfile is also created.

Implementation

Future<AuthSuccess> login(
  final Session session, {
  required final String code,
  required final String codeVerifier,
  required final String redirectUri,
  final Transaction? transaction,
}) async {
  return await DatabaseUtil.runInTransactionOrSavepoint(
    session.db,
    transaction,
    (final transaction) async {
      final accessToken = await utils.exchangeCodeForToken(
        session,
        code: code,
        codeVerifier: codeVerifier,
        redirectUri: redirectUri,
      );

      final account = await utils.authenticate(
        session,
        accessToken: accessToken,
        transaction: transaction,
      );

      final image = account.details.image;
      if (account.newAccount) {
        try {
          await _userProfiles.createUserProfile(
            session,
            account.authUserId,
            UserProfileData(
              fullName: account.details.name?.trim(),
              email: account.details.email,
            ),
            transaction: transaction,
            imageSource: image != null ? UserImageFromUrl(image) : null,
          );
        } catch (e, stackTrace) {
          session.log(
            'Failed to create user profile for new GitHub user.',
            level: LogLevel.error,
            exception: e,
            stackTrace: stackTrace,
          );
        }
      } else if (image != null) {
        try {
          final user = await UserProfile.db.findFirstRow(
            session,
            where: (final t) => t.authUserId.equals(account.authUserId),
            transaction: transaction,
          );
          if (user != null && user.image == null) {
            await _userProfiles.setUserImageFromUrl(
              session,
              account.authUserId,
              image,
              transaction: transaction,
            );
          }
        } catch (e, stackTrace) {
          session.log(
            'Failed to update user profile image for existing GitHub user.',
            level: LogLevel.error,
            exception: e,
            stackTrace: stackTrace,
          );
        }
      }

      return _tokenIssuer.issueToken(
        session,
        authUserId: account.authUserId,
        transaction: transaction,
        method: method,
        scopes: account.scopes,
      );
    },
  );
}