public virtual async Task DeleteTenantAsync(Tenant tenant)
        {
            ThrowIfDisposed();
            Guard.ArgumentNotNull(tenant, nameof(tenant));

            _dbContext.Remove(tenant);
            await _dbContext
                .SaveChangesAsync(_cancellationToken)
                .ConfigureAwait(false);
        }
        public virtual async Task UpdateTenantAsync(Tenant tenant)
        {
            ThrowIfDisposed();
            Guard.ArgumentNotNull(tenant, nameof(tenant));

            _dbContext.Attach(tenant);
            tenant.ConcurrencyStamp = Guid.NewGuid().ToString();
            _dbContext.Update(tenant);
            await _dbContext
                .SaveChangesAsync(_cancellationToken)
                .ConfigureAwait(false);
        }
        private async Task<Tenant> SignUpTenantAsync(BaseControlContext context, TenantManager tenantManager)
        {
            Guard.ArgumentNotNull(context, nameof(context));
            Guard.ArgumentNotNull(tenantManager, nameof(tenantManager));

            var principal = context.Ticket.Principal;
            var issuerValue = principal.GetIssuerValue();
            var tenant = new Tenant
            {
                IssuerValue = issuerValue,
                Created = DateTimeOffset.UtcNow
            };

            try
            {
                await tenantManager.CreateAsync(tenant)
                    .ConfigureAwait(false);
            }
            catch(Exception ex)
            {
                _logger.SignUpTenantFailed(principal.GetObjectIdentifierValue(), issuerValue, ex);
                throw;
            }

            return tenant;
        }
        private async Task CreateOrUpdateUserAsync(AuthenticationTicket authenticationTicket, UserManager userManager, Tenant tenant)
        {
            Guard.ArgumentNotNull(authenticationTicket, nameof(authenticationTicket));
            Guard.ArgumentNotNull(userManager, nameof(userManager));
            Guard.ArgumentNotNull(tenant, nameof(tenant));

            var principal = authenticationTicket.Principal;
            string objectIdentifier = principal.GetObjectIdentifierValue();
            string displayName = principal.GetDisplayNameValue();
            string email = principal.GetEmailValue();

            var user = await userManager.FindByObjectIdentifier(objectIdentifier)
                .ConfigureAwait(false);
            if (user == null)
            {
                // The user isn't in our database, so add them.
                user = new User
                {
                    Created = DateTimeOffset.UtcNow,
                    ObjectId = objectIdentifier,
                    TenantId = tenant.Id,
                    DisplayName = displayName,
                    Email = email
                };

                await userManager.CreateAsync(user)
                    .ConfigureAwait(false);
            }
            else
            {
                // Since we aren't the system of record, we need to attempt to keep our display values in sync with the user store.
                // We'll do a simple form of it here.
                bool shouldSaveUser = false;
                if (!user.DisplayName.Equals(displayName, StringComparison.OrdinalIgnoreCase))
                {
                    user.DisplayName = displayName;
                    shouldSaveUser = true;
                }

                // Do a case insensitive comparison for email matching
                if (!user.Email.Equals(email, StringComparison.OrdinalIgnoreCase))
                {
                    user.Email = email;
                    shouldSaveUser = true;
                }

                if (shouldSaveUser)
                {
                    await userManager
                        .UpdateAsync(user)
                        .ConfigureAwait(false);
                }
            }

            // Add in the survey user id claim.
            principal.Identities.First().AddClaim(new Claim(SurveyClaimTypes.SurveyUserIdClaimType, user.Id.ToString()));
            // Add in the user's tenant id claim.
            principal.Identities.First().AddClaim(new Claim(SurveyClaimTypes.SurveyTenantIdClaimType, user.TenantId.ToString()));
        }