Beispiel #1
0
        public async Task <IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
        {
            returnUrl ??= Url.Content("~/");
            if (remoteError != null)
            {
                ErrorMessage = $"Error from external provider: {remoteError}";
                return(RedirectToPage("./Login", new { ReturnUrl = returnUrl }));
            }
            var info = await _signInManager.GetExternalLoginInfoAsync();

            if (info == null)
            {
                ErrorMessage = "Error loading external login information.";
                return(RedirectToPage("./Login", new { ReturnUrl = returnUrl }));
            }

            // Sign in the user with this external login provider if the user already has a login.
            var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent : false, bypassTwoFactor : true);

            if (result.Succeeded)
            {
                _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
                // Get the logged in user from the database
                StreamNightUser loggedInUser = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);

                try
                {
                    bool hasStreamRole = false;
                    bool hasAdminRole  = false;
                    // Get the user's roles from the Discord bot
                    DSharpPlus.Entities.DiscordMember member = await _discordBot.DiscordClient.GetMemberById(loggedInUser.DiscordId);

                    foreach (DSharpPlus.Entities.DiscordRole discordRole in member.Roles)
                    {
                        // If the user has the stream role
                        if (discordRole.Name == _discordBot.DiscordClient.StreamRole)
                        {
                            hasStreamRole = true;
                        }
                        if (discordRole.Name == _discordBot.DiscordClient.AdminRole)
                        {
                            hasAdminRole = true;
                        }
                    }

                    // Check if the user is in the stream role already
                    bool userInStreamRole = await _userManager.IsInRoleAsync(loggedInUser, "StreamController");

                    if (!userInStreamRole && hasStreamRole)
                    {
                        // Add the stream role to the user
                        await _userManager.AddToRoleAsync(loggedInUser, "StreamController");

                        // Refresh the login cookie
                        await _signInManager.RefreshSignInAsync(loggedInUser);
                    }
                    else if (userInStreamRole && !hasStreamRole)
                    {
                        // Remove the stream role from the user
                        await _userManager.RemoveFromRoleAsync(loggedInUser, "StreamController");

                        // Refresh the login cookie
                        await _signInManager.RefreshSignInAsync(loggedInUser);
                    }

                    // Check if the user is in the admin role already
                    bool userInAdmin = await _userManager.IsInRoleAsync(loggedInUser, "Administrator");

                    if (!userInAdmin && hasAdminRole)
                    {
                        // Add the admin role to the user
                        await _userManager.AddToRoleAsync(loggedInUser, "Administrator");

                        // Refresh the login cookie
                        await _signInManager.RefreshSignInAsync(loggedInUser);
                    }
                    else if (userInAdmin && !hasAdminRole)
                    {
                        // Remove the admin role from the user
                        await _userManager.RemoveFromRoleAsync(loggedInUser, "Administrator");

                        // Refresh the login cookie
                        await _signInManager.RefreshSignInAsync(loggedInUser);
                    }
                }
                // The user might not exist, catch the exception and do nothing
                catch (NullReferenceException) { }

                return(LocalRedirect(returnUrl));
            }
            if (result.IsLockedOut)
            {
                return(RedirectToPage("./Lockout"));
            }
            else
            {
                // If the user does not have an account, then ask the user to create an account.
                ReturnUrl     = returnUrl;
                LoginProvider = info.LoginProvider;
                if (info.Principal.HasClaim(c => c.Type == ClaimTypes.NameIdentifier))
                {
                    ulong.TryParse(info.Principal.FindFirstValue(ClaimTypes.NameIdentifier), out ulong dId);
                    Input = new InputModel
                    {
                        DiscordId = dId
                    };
                }
                return(Page());
            }
        }
        public async Task <IActionResult> LoginWithBot([FromQuery] string token)
        {
            string DiscordIdFromLink;
            bool   isValid;

            // Validate the token.
            try
            {
                string decryptedToken = StringCipher.Decrypt(token, _configuration["TokenPassword"]);
                if (Hmac.VerifyMessage(decryptedToken, _configuration["TokenKey"]))
                {
                    isValid           = true;
                    DiscordIdFromLink = Hmac.DecodeMessage(decryptedToken);
                }
                else
                {
                    return(BadRequest());
                }
            }
            catch
            {
                return(BadRequest());
            }

            // Handle login.
            if (isValid)
            {
                StreamNightUser user = await _userManager.FindByNameAsync(DiscordIdFromLink);

                bool signInUser = true;

                if (user == null)
                {
                    signInUser = false;
                    // User doesn't have an account, let's transparently create one and log them in.
                    ulong.TryParse(DiscordIdFromLink, out ulong DiscordId);
                    user = new StreamNightUser {
                        UserName = DiscordId.ToString(), DiscordId = DiscordId
                    };
                    var result = await _userManager.CreateAsync(user);

                    if (result.Succeeded)
                    {
                        signInUser = true;
                        _logger.LogInformation("Created a new user from a Discord link.");
                    }
                }

                if (signInUser)
                {
                    // Check if the user should be in the administrator role
                    try
                    {
                        bool hasStreamRole = false;
                        bool hasAdminRole  = false;
                        // Get the user's roles from the Discord bot
                        DSharpPlus.Entities.DiscordMember member = await _discordBot.DiscordClient.GetMemberById(user.DiscordId);

                        foreach (DSharpPlus.Entities.DiscordRole discordRole in member.Roles)
                        {
                            // If the user has the stream role
                            if (discordRole.Name == _discordBot.DiscordClient.StreamRole)
                            {
                                hasStreamRole = true;
                            }
                            if (discordRole.Name == _discordBot.DiscordClient.AdminRole)
                            {
                                hasAdminRole = true;
                            }
                        }

                        // Check if the user is in the stream role already
                        bool userInStreamRole = await _userManager.IsInRoleAsync(user, "StreamController");

                        if (!userInStreamRole && hasStreamRole)
                        {
                            // Add the stream role to the user
                            await _userManager.AddToRoleAsync(user, "StreamController");
                        }
                        else if (userInStreamRole && !hasStreamRole)
                        {
                            // Remove the stream role from the user
                            await _userManager.RemoveFromRoleAsync(user, "StreamController");
                        }

                        // Check if the user is in the admin role already
                        bool userInAdmin = await _userManager.IsInRoleAsync(user, "Administrator");

                        if (!userInAdmin && hasAdminRole)
                        {
                            // Add the admin role to the user
                            await _userManager.AddToRoleAsync(user, "Administrator");
                        }
                        else if (userInAdmin && !hasAdminRole)
                        {
                            // Remove the admin role from the user
                            await _userManager.RemoveFromRoleAsync(user, "Administrator");
                        }
                    }
                    // The user might not exist, catch the exception and do nothing
                    catch (NullReferenceException) { }

                    await _signInManager.SignInAsync(user, isPersistent : false, authenticationMethod : "DiscordLink");

                    _logger.LogInformation("User logged in using a Discord link.");
                }

                return(LocalRedirect(returnUrl));
            }

            return(BadRequest());
        }
Beispiel #3
0
        public async Task <IActionResult> OnPostConfirmationAsync(string returnUrl = null)
        {
            returnUrl ??= Url.Content("~/");
            // Get the information about the user from the external login provider
            var info = await _signInManager.GetExternalLoginInfoAsync();

            if (info == null)
            {
                ErrorMessage = "Error loading external login information during confirmation.";
                return(RedirectToPage("./Login", new { ReturnUrl = returnUrl }));
            }

            if (ModelState.IsValid)
            {
                ulong.TryParse(info.Principal.FindFirstValue(ClaimTypes.NameIdentifier), out ulong DiscordId);
                var user = new StreamNightUser {
                    UserName = DiscordId.ToString(), DiscordId = DiscordId
                };
                var result = await _userManager.CreateAsync(user);

                if (result.Succeeded)
                {
                    try
                    {
                        // Get the user's roles from the Discord bot
                        DSharpPlus.Entities.DiscordMember member = await _discordBot.DiscordClient.GetMemberById(user.DiscordId);

                        foreach (DSharpPlus.Entities.DiscordRole discordRole in member.Roles)
                        {
                            // If the user has the stream role
                            if (discordRole.Name == _discordBot.DiscordClient.StreamRole)
                            {
                                await _userManager.AddToRoleAsync(user, "StreamController");
                            }
                            if (discordRole.Name == _discordBot.DiscordClient.AdminRole)
                            {
                                await _userManager.AddToRoleAsync(user, "Administrator");
                            }
                        }
                    }
                    // The user might not exist, catch the exception and do nothing
                    catch (NullReferenceException) { }

                    result = await _userManager.AddLoginAsync(user, info);

                    if (result.Succeeded)
                    {
                        await _signInManager.SignInAsync(user, isPersistent : false);

                        _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
                        return(LocalRedirect(returnUrl));
                    }
                }
                else if (result.Errors.Where(e => e.Code == "DuplicateUserName").Any())
                {
                    var existingUser = await _userManager.FindByNameAsync(DiscordId.ToString());

                    var addLoginResult = await _userManager.AddLoginAsync(existingUser, info);

                    if (addLoginResult.Succeeded)
                    {
                        await _signInManager.SignInAsync(existingUser, isPersistent : false);

                        return(LocalRedirect(returnUrl));
                    }
                }
                else
                {
                    ViewData["ResultMessage"] = "Couldn't sign in with Discord. Try logging in with a DM instead.";
                }

                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }

            LoginProvider = info.LoginProvider;
            ReturnUrl     = returnUrl;
            return(Page());
        }