public async Task DeleteIdentity(Guid identityId, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Retrieve identity entity
            var retrieveOperation = TableOperation.Retrieve <AzureIdentityEntity>(Constants.PartitionNames.IdentityPrimary, identityId.ToString());
            var retrievedResult   = await this.IdentityTable.ExecuteAsync(retrieveOperation, null, null, cancellationToken).ConfigureAwait(false);

            var retrievedEntity = (AzureIdentityEntity)retrievedResult?.Result;

            // Delete both foreign key as well as identity record
            var deleteIdentityEntity = new AzureIdentityEntity
            {
                PartitionKey = Constants.PartitionNames.IdentityPrimary,
                RowKey       = identityId.ToString(),
                ETag         = "*"
            };

            var deleteForeignKeyEntity = new AzureIdentityForeignKeyEntity
            {
                PartitionKey = Constants.PartitionNames.EmailAddressToIdentityForeignKey,
                RowKey       = retrievedEntity.EmailAddress,
                ETag         = "*"
            };

            // Delete all authentication tokens associated with the Identity
            var query = new TableQuery <AzureTokenEntity>();

            query.Where(TableQuery.CombineFilters(
                            TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, Constants.PartitionNames.TokenPrimary),
                            TableOperators.And,
                            TableQuery.GenerateFilterConditionForGuid("IdentityId", QueryComparisons.Equal, identityId)
                            )
                        );

            TableContinuationToken continuationToken = null;

            do
            {
                var segmentResult = await this.TokenTable.ExecuteQuerySegmentedAsync(query, continuationToken, null, null, cancellationToken);

                var batchOption = new TableBatchOperation();
                foreach (var entity in segmentResult.Results)
                {
                    batchOption.Delete(entity);
                }

                if (batchOption.Count > 0)
                {
                    await this.TokenTable.ExecuteBatchAsync(batchOption, null, null, cancellationToken).ConfigureAwait(false);
                }

                continuationToken = segmentResult.ContinuationToken;
            } while (continuationToken != null);

            // Delete identity and identity foreign key
            var deleteEntityOperation     = TableOperation.Delete(deleteIdentityEntity);
            var deleteForeignKeyOperation = TableOperation.Delete(deleteForeignKeyEntity);

            var entityDeleteResult = await this.IdentityTable.ExecuteAsync(deleteEntityOperation, null, null, cancellationToken).ConfigureAwait(false);

            var foreignKeyDeleteResult = await this.IdentityTable.ExecuteAsync(deleteForeignKeyOperation, null, null, cancellationToken).ConfigureAwait(false);
        }
        public async Task <CreateIdentityResult> CreateIdentity(string emailAddress, string password, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                emailAddress = emailAddress?.ToLowerInvariant();

                var identityExistsCheck = await CheckIdentityExists(emailAddress, cancellationToken).ConfigureAwait(false);

                if (identityExistsCheck)
                {
                    return(new CreateIdentityResult
                    {
                        Success = false
                    });
                }

                // Identity generation
                var perUserSalt    = Security.GeneratePerUserSalt();
                var hashedPassword = Security.GeneratePasswordHash(password, perUserSalt);
                var identityEntity = new AzureIdentityEntity()
                {
                    IdentityId     = Guid.NewGuid(),
                    EmailAddress   = emailAddress,
                    PerUserSalt    = perUserSalt,
                    HashedPassword = hashedPassword
                };

                var createIdentityOperation = TableOperation.Insert(identityEntity);

                // Identity foreign key generation
                var foreignKey = new AzureIdentityForeignKeyEntity
                {
                    IdentityId   = identityEntity.IdentityId,
                    EmailAddress = emailAddress,
                };

                var createForeignKeyOperation = TableOperation.Insert(foreignKey);

                // Insert identity information
                await this.IdentityTable.ExecuteAsync(createForeignKeyOperation, null, null, cancellationToken).ConfigureAwait(false);                 // This insert first to ensure there isn't a key conflict

                await this.IdentityTable.ExecuteAsync(createIdentityOperation, null, null, cancellationToken).ConfigureAwait(false);

                // Create verification token if email provider is set up
                if (this.EmailProvider != null)
                {
                    await this.EmailProvider.SendVerificationEmail(identityEntity.IdentityId, this.EmailProvider.VerificationEmailSubject, cancellationToken).ConfigureAwait(false);

                    // Do not create token until identity is verified
                    return(new CreateIdentityResult
                    {
                        Success = true,
                        IdentityId = identityEntity.IdentityId
                    });
                }

                // Token generation
                var token       = Security.GenerateToken();
                var tokenEntity = new AzureTokenEntity
                {
                    IdentityId = identityEntity.IdentityId,
                    Token      = token
                };

                var createTokenOperation = TableOperation.Insert(tokenEntity);
                await this.TokenTable.ExecuteAsync(createTokenOperation, null, null, cancellationToken).ConfigureAwait(false);

                return(new CreateIdentityResult
                {
                    Success = true,
                    IdentityId = identityEntity.IdentityId,
                    Token = tokenEntity.Token
                });
            }
            catch (StorageException)
            {
                return(new CreateIdentityResult
                {
                    Success = false
                });
            }
        }