private string GenerateSecretToken()
 {
     return(TokenService.GenerateAppleToken(Configurations.Apple.AppleSecret, Configurations.Apple.AppleClientId, Configurations.Apple.AppleAppId,
                                            Configurations.Apple.AppleTeamId, "https://appleid.apple.com", DateTime.UtcNow.AddDays(1)));
 }
        public async Task <(bool, UserType)> FindOrCreateUser(string email, string name, string country, string ipAddress, ADUser adUser = null, bool shouldUpdateAdUser = true)
        {
            email = email.ToLower();
            var request = new ListUsersRequest
            {
                UserPoolId = Configurations.Cognito.CognitoPoolId,
                Filter     = $"email = \"{email}\"",
            };

            var usersResponse = await provider.ListUsersAsync(request);

            if (usersResponse.Users.Count > 0)
            {
                var user = usersResponse.Users.First();
                // dont return passcode property to client
                user.Attributes.Remove(user.Attributes.Find(x => x.Name == "custom:authChallenge"));
                return(true, user);
            }
            else
            {
                var adUserExisting = false;
                if (adUser == null)
                {
                    // create AD User if needed
                    var(existing, newAdUser) = await ADUser.FindOrCreate(email, name, country, ipAddress);

                    adUser         = newAdUser;
                    adUserExisting = existing;
                }
                else
                {
                    adUserExisting = true;
                }

                if (adUser == null)
                {
                    throw new Exception($"can not create ad user {email}");
                }

                // update new properties
                if (adUserExisting && shouldUpdateAdUser)
                {
                    var updateParams = new Dictionary <string, dynamic>();
                    if (!string.IsNullOrWhiteSpace(country))
                    {
                        updateParams["country"] = country;
                        adUser.Country          = country;
                    }

                    if (!string.IsNullOrWhiteSpace(ipAddress))
                    {
                        updateParams["streetAddress"] = ipAddress;
                        adUser.IPAddress = ipAddress;
                    }

                    // enable account if needed
                    if (!adUser.AccountEnabled)
                    {
                        updateParams["accountEnabled"] = true;
                        adUser.AccountEnabled          = true;
                    }

                    if (updateParams.Count > 0)
                    {
                        await adUser.Update(updateParams);
                    }
                }

                // then create cognito user
                var attributes = new List <AttributeType>();
                if (!string.IsNullOrWhiteSpace(name))
                {
                    attributes.Add(new AttributeType()
                    {
                        Name = "name", Value = name
                    });
                }

                if (!string.IsNullOrWhiteSpace(country))
                {
                    attributes.Add(new AttributeType()
                    {
                        Name = "custom:country", Value = country
                    });
                }
                else if (!string.IsNullOrWhiteSpace(adUser.Country))
                {
                    attributes.Add(new AttributeType()
                    {
                        Name = "custom:country", Value = adUser.Country
                    });
                }

                if (!string.IsNullOrWhiteSpace(ipAddress))
                {
                    attributes.Add(new AttributeType()
                    {
                        Name = "custom:ipAddress", Value = ipAddress
                    });
                }
                else if (!string.IsNullOrWhiteSpace(adUser.IPAddress))
                {
                    attributes.Add(new AttributeType()
                    {
                        Name = "custom:ipAddress", Value = adUser.IPAddress
                    });
                }

                // set custom user id from b2c
                attributes.Add(new AttributeType()
                {
                    Name = "preferred_username", Value = adUser.ObjectId
                });
                attributes.Add(new AttributeType()
                {
                    Name = "email", Value = email
                });

                // create new user with temp password
                var createRequest = new AdminCreateUserRequest
                {
                    UserPoolId        = Configurations.Cognito.CognitoPoolId,
                    Username          = email,
                    UserAttributes    = attributes,
                    TemporaryPassword = TokenService.GeneratePassword(Guid.NewGuid().ToString()),
                    MessageAction     = MessageActionType.SUPPRESS,
                };

                UserType newUser;
                try
                {
                    var createUserResponse = await provider.AdminCreateUserAsync(createRequest);

                    newUser = createUserResponse.User;
                }
                catch (UsernameExistsException ex)
                {
                    // TODO will remove later (after fixing from client)
                    Logger.Log?.LogError($"user name exist {ex.Message}");
                    // user exist in other request, just get it from cognito after few second
                    Task.Delay(5 * 1000).Wait();
                    usersResponse = await provider.ListUsersAsync(request);

                    newUser = usersResponse.Users.First();
                }

                // then change its password
                var changePasswordRequest = new AdminSetUserPasswordRequest
                {
                    UserPoolId = Configurations.Cognito.CognitoPoolId,
                    Username   = newUser.Username,
                    Password   = TokenService.GeneratePassword(email),
                    Permanent  = true
                };

                await provider.AdminSetUserPasswordAsync(changePasswordRequest);


                if (!adUserExisting)
                {
                    // add cognito user into group new
                    await UpdateUserGroup(newUser.Username, "new");

                    if (shouldUpdateAdUser)
                    {
                        // add ad user into group new
                        var newGroup = await ADGroup.FindByName("new");

                        var addResult = await newGroup.AddUser(adUser.ObjectId);

                        if (!addResult)
                        {
                            throw new Exception($"can not add ad user {email} into new group");
                        }
                    }
                }
                else
                {
                    // add cognito user into group from b2c
                    var groupName = await adUser.GroupName();

                    if (!string.IsNullOrWhiteSpace(groupName))
                    {
                        await UpdateUserGroup(newUser.Username, groupName);
                    }
                    else
                    {
                        Logger.Log?.LogError($"user {email} does not have group");
                    }
                }

                // dont return passcode property to client
                newUser.Attributes.Remove(newUser.Attributes.Find(x => x.Name == "custom:authChallenge"));
                return(false, newUser);
            }
        }