public async Task <AuthorizeResult> GenerateTokenForIdentityId(Guid identityId, CancellationToken cancellationToken = default(CancellationToken))
        {
            var identityResult = await this.IdentityTable.GetItemAsync(Constants.PartitionNames.IdentityPrimary, identityId.ToString(), cancellationToken).ConfigureAwait(false);

            var identityEntity = JsonConvert.DeserializeObject <AWSIdentityEntity>(identityResult.ToJson());

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

            var tokenDocument     = Document.FromJson(JsonConvert.SerializeObject(tokenEntity));
            var tokenInsertResult = await this.TokenTable.PutItemAsync(tokenDocument, cancellationToken).ConfigureAwait(false);

            return(new AuthorizeResult
            {
                Success = true,
                Token = token,
                IdentityId = identityId
            });
        }
        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 AWSIdentityEntity()
                {
                    IdentityId     = Guid.NewGuid(),
                    EmailAddress   = emailAddress,
                    PerUserSalt    = perUserSalt,
                    HashedPassword = hashedPassword
                };

                var identityDocument       = Document.FromJson(JsonConvert.SerializeObject(identityEntity));
                var insertIdentityResponse = await this.IdentityTable.PutItemAsync(identityDocument, 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 AWSTokenEntity
                {
                    IdentityId = identityEntity.IdentityId,
                    Token      = token
                };


                var tokenDocument       = Document.FromJson(JsonConvert.SerializeObject(tokenEntity));
                var insertTokenResponse = await this.TokenTable.PutItemAsync(tokenDocument, cancellationToken).ConfigureAwait(false);

                return(new CreateIdentityResult
                {
                    Success = true,
                    IdentityId = identityEntity.IdentityId,
                    Token = tokenEntity.Token
                });
            }
            catch (Exception)
            {
                return(new CreateIdentityResult
                {
                    Success = false
                });
            }
        }
        public async Task <AuthorizeResult> Authorize(string emailAddress, string password, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                // Check to see if email exists
                emailAddress = emailAddress?.ToLowerInvariant();
                var queryResponse = await QueryEmailSecondaryIndex(emailAddress, cancellationToken).ConfigureAwait(false);

                if (queryResponse.Count != 1)
                {
                    return(new AuthorizeResult
                    {
                        Success = false
                    });
                }

                var identitySecondaryResult = queryResponse.Items.First();
                var identityId = identitySecondaryResult[nameof(AWSIdentityEntity.IdentityId)].S;

                // Retrieve IdentityEntity
                var identityResult = await this.IdentityTable.GetItemAsync(Constants.PartitionNames.IdentityPrimary, identityId, cancellationToken).ConfigureAwait(false);

                var identityEntity = JsonConvert.DeserializeObject <AWSIdentityEntity>(identityResult.ToJson());

                // Check if provided password is valid
                var passwordMatches = Security.PasswordMatches(identityEntity.PerUserSalt, password, identityEntity.HashedPassword);
                if (!passwordMatches)
                {
                    return(new AuthorizeResult
                    {
                        Success = false
                    });
                }

                // Email verification check
                if (this.EmailProvider != null && !identityEntity.EmailVerified && !this.AllowUnverifiedIdentities)
                {
                    return(new AuthorizeResult
                    {
                        Success = false,
                        IdentityId = identityEntity.IdentityId,
                        Message = "Identity has not been verified by email yet"
                    });
                }

                // Generate, store and return token
                var token       = Security.GenerateToken();
                var tokenEntity = new AWSTokenEntity
                {
                    IdentityId = identityEntity.IdentityId,
                    Token      = token
                };

                var tokenDocument = Document.FromJson(JsonConvert.SerializeObject(tokenEntity));
                var putResponse   = await this.TokenTable.PutItemAsync(tokenDocument, cancellationToken).ConfigureAwait(false);

                return(new AuthorizeResult
                {
                    Success = true,
                    IdentityId = identityEntity.IdentityId,
                    Token = token
                });
            }
            catch (Exception)
            {
                return(new AuthorizeResult
                {
                    Success = false
                });
            }
        }