public async Task <AuthenticationTicket?> OnSignInAsync(
            ulong userId,
            string username,
            string discriminator,
            string avatarHash,
            Func <CancellationToken, Task <IEnumerable <ulong> > > getGuildIdsDelegate,
            CancellationToken cancellationToken = default)
        {
            AuthenticationLogMessages.UserSigningIn(_logger, userId, username, discriminator);

            // Don't bother tracking or retrieving permissions for users we don't care about.
            var isAdmin = _authorizationConfiguration.AdminUserIds.Contains(userId);

            if (!isAdmin && !(await IsMemberAsync(userId, getGuildIdsDelegate, cancellationToken)))
            {
                AuthenticationLogMessages.UserIgnored(_logger, userId, username, discriminator);
                return(null);
            }

            await _usersService.TrackUserAsync(
                userId,
                username,
                discriminator,
                avatarHash,
                cancellationToken);

            AuthenticationLogMessages.UserTracked(_logger, userId);

            AuthenticationLogMessages.AuthenticationTicketActiveIdFetching(_logger, userId);
            var ticketId = await GetActiveTicketIdAsync(userId, cancellationToken);

            AuthenticationLogMessages.AuthenticationTicketActiveIdFetched(_logger, ticketId);

            AuthenticationLogMessages.GrantedPermissionsFetching(_logger, userId);
            var grantedPermissions = (await _usersService.GetGrantedPermissionsAsync(
                                          userId,
                                          cancellationToken))
                                     .Value
                                     .ToDictionary(x => x.Id, x => x.Name);

            AuthenticationLogMessages.GrantedPermissionsFetched(_logger, grantedPermissions);

            var ticket = new AuthenticationTicket(
                ticketId,
                userId,
                username,
                discriminator,
                avatarHash,
                grantedPermissions);

            AuthenticationLogMessages.UserSignedIn(_logger, ticketId, userId, username, discriminator);
            return(ticket);
        }
        public async Task <AuthenticationTicket> OnAuthenticatedAsync(
            long ticketId,
            ulong userId,
            string username,
            string discriminator,
            string avatarHash,
            IReadOnlyDictionary <int, string> grantedPermissions,
            CancellationToken cancellationToken)
        {
            AuthenticationLogMessages.AuthenticationPerforming(_logger, ticketId, userId, username, discriminator, avatarHash, grantedPermissions);

            AuthenticationLogMessages.AuthenticationTicketActiveIdFetching(_logger, userId);
            var activeTicketId = await GetActiveTicketIdAsync(userId, cancellationToken);

            AuthenticationLogMessages.AuthenticationTicketActiveIdFetched(_logger, activeTicketId);

            if (activeTicketId != ticketId)
            {
                AuthenticationLogMessages.GrantedPermissionsFetching(_logger, userId);
                grantedPermissions = (await _usersService.GetGrantedPermissionsAsync(
                                          userId,
                                          cancellationToken))
                                     .Value
                                     .ToDictionary(x => x.Id, x => x.Name);
                AuthenticationLogMessages.GrantedPermissionsFetched(_logger, grantedPermissions);
            }

            _currentTicket = new AuthenticationTicket(
                activeTicketId,
                userId,
                username,
                discriminator,
                avatarHash,
                grantedPermissions);
            AuthenticationLogMessages.AuthenticationPerformed(_logger, activeTicketId);

            return(_currentTicket);
        }