public async Task <AuthenticationResult> RegisterAsync(string email, string password)
        {
            var newUser = await userManager.FindByEmailAsync(email);

            if (newUser != null) // If user exist
            {
                return(AuthenticationResult.FailResult("User alredy exist"));
            }

            var newUserId = Guid.NewGuid().ToString();

            newUser = new IdentityUser()
            {
                Id = newUserId, Email = email, UserName = email
            };
            var creationResult = await userManager.CreateAsync
                                     (user : newUser,
                                     password : password);

            // Add this claim into the database
            await userManager.AddClaimAsync(newUser, new Claim("tags.view", "true"));

            if (!creationResult.Succeeded)
            {
                return(AuthenticationResult.FailResult(creationResult.Errors.Select(r => r.Description)));
            }

            return(await GenerateAuthenticationResultForUser(newUser));
        }
        public async Task <AuthenticationResult> RegisterAsync(string email, string password)
        {
            // if user doesnt exists, create a new user
            var newUser = new AppUser()
            {
                Email = email, UserName = email
            };


#if TESTINGIDENTITY
            //
            // Email Confirmation
            //

            string cToken = await userManager.GenerateEmailConfirmationTokenAsync(newUser);

            string b64token = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(cToken));

            var callbackUrl = new Url($"Callback/url/{b64token}");

            // Email Service that send email
            // email_service.SendEmailAsync(callbackUrl);


            if (userManager.Options.SignIn.RequireConfirmedEmail)
            {
                // return to some page to wait until he confirm his email



                // just testing Identity
                if (newUser.Email.EndsWith("benzeine.com"))
                {
                    newUser.AccessFailedCount = 100;
                    newUser.EmailConfirmed    = true;
                    newUser.LockoutEnabled    = false;

                    //newUser.LockoutEnd = DateTime.Today.AddDays(30);
                }
            }
#endif

            var identityResult = await userManager.CreateAsync(newUser, password);


            if (!identityResult.Succeeded)
            {
                return(AuthenticationResult.FailResult(identityResult.Errors.Select(e => e.Description)));
            }

            await userManager.AddToRoleAsync(newUser, "User");

            return(await GenerateAuthenticationResultAsync(newUser));
        }
        // LOGIN
        public async Task <AuthenticationResult> LoginAsync(string email, string password)
        {
            var user = await userManager.FindByEmailAsync(email);

            if (user == null)
            {
                return(AuthenticationResult.FailResult("User doesnt exist"));
            }

            bool isPasswordValid = await userManager.CheckPasswordAsync(user, password);

            if (!isPasswordValid)
            {
                return(AuthenticationResult.FailResult("User/Password combination is wrong"));
            }

            return(await GenerateAuthenticationResultForUser(user));
        }
        public async Task <AuthenticationResult> LoginAsync(string email, string password)
        {
            var user = await userManager.FindByEmailAsync(email);

            if (user == null)
            {
                return(AuthenticationResult.FailResult("Sorry, user doesn't exist. Don't do that again"));
            }

            // if passwords are mattched we generate JWT
            if (await userManager.CheckPasswordAsync(user, password))
            {
                return(await GenerateAuthenticationResultAsync(user));
            }
            else
            {
                return(AuthenticationResult.FailResult("Sorry, Passwords don't match, please dry your fingers"));
            }
        }
        public async Task <AuthenticationResult> RefreshTokenAsync(string token, string refreshToken)
        {
            ClaimsPrincipal principal = GetPrincipalFromToken(token);

            if (principal == null)
            {
                return(AuthenticationResult.FailResult("Invalid Token"));
            }

            var unix_expiration_dateOfToken = long.Parse(principal.Claims.Single
                                                             (x => x.Type == JwtRegisteredClaimNames.Exp).Value);

            var utc_expiration_date = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
                                      .AddSeconds(unix_expiration_dateOfToken)
                                      .Subtract(jwtOptions.TokenLifeTime);

            if (utc_expiration_date > DateTime.UtcNow)
            {
                return(AuthenticationResult.FailResult("This token hasn't expired yet"));
            }

            var jti = principal.Claims.Single
                          (x => x.Type == JwtRegisteredClaimNames.Jti).Value;

            RefreshToken stored_refresh_token = await
                                                context.RefreshTokens.SingleOrDefaultAsync(x => x.Token == refreshToken);

            if (stored_refresh_token == null)
            {
                return(AuthenticationResult.FailResult("Hey, Refresh Token doesnt exixst"));
            }

            // if refresh token expired
            if (DateTime.UtcNow > stored_refresh_token.ExpirationDate)
            {
                return(AuthenticationResult.FailResult("This refresh token has expired"));
            }

            if (stored_refresh_token.Invalidated)
            {
                return(AuthenticationResult.FailResult("This refresh token has been invalidated"));
            }

            if (stored_refresh_token.IsUsed)
            {
                return(AuthenticationResult.FailResult("This refresh token has been used"));
            }

            if (stored_refresh_token.JwtId != jti)
            {
                return(AuthenticationResult.FailResult("This refresh token doesn't match JTI"));
            }

            stored_refresh_token.IsUsed = true;
            context.RefreshTokens.Update(stored_refresh_token);
            await context.SaveChangesAsync();

            var user = await
                       userManager.FindByIdAsync(principal.Claims.Single(x => x.Type == "id").Value);

            return(await GenerateAuthenticationResultForUser(user));


            #region Local Methods

            // local methods
            ClaimsPrincipal GetPrincipalFromToken(string _token)
            {
                var jwtHandler = new JwtSecurityTokenHandler();

                try
                {
                    ClaimsPrincipal _principal =
                        jwtHandler.ValidateToken(_token, tokenValidationParameters, out SecurityToken validatedToken);

                    if (!IsJwtWithValidSecurityAlgorithm(validatedToken))
                    {
                        return(null);
                    }

                    return(_principal);
                }
                catch (Exception)
                {
                    return(null);
                }

                // local methods
                bool IsJwtWithValidSecurityAlgorithm(SecurityToken validatedToken)
                {
                    return((validatedToken is JwtSecurityToken jwt) &&
                           jwt.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCulture));
                }
            }

            #endregion
        }