using System.Collections.Generic; using System.IO; using System.Security.Claims; using System.Security.Cryptography; using System.Threading.Tasks; using System.Xml; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using NLog; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; using NzbDrone.Core.Authentication; using NzbDrone.Core.Configuration; namespace Radarr.Http.Authentication { [AllowAnonymous] [ApiController] public class AuthenticationController : Controller { private readonly IAuthenticationService _authService; private readonly IConfigFileProvider _configFileProvider; private readonly IAppFolderInfo _appFolderInfo; private readonly Logger _logger; public AuthenticationController(IAuthenticationService authService, IConfigFileProvider configFileProvider, IAppFolderInfo appFolderInfo, Logger logger) { _authService = authService; _configFileProvider = configFileProvider; _appFolderInfo = appFolderInfo; _logger = logger; } [HttpPost("login")] public async Task Login([FromForm] LoginResource resource, [FromQuery] string returnUrl = null) { var user = _authService.Login(HttpContext.Request, resource.Username, resource.Password); if (user == null) { return Redirect($"~/login?returnUrl={returnUrl}&loginFailed=true"); } var claims = new List { new Claim("user", user.Username), new Claim("identifier", user.Identifier.ToString()), new Claim("AuthType", AuthenticationType.Forms.ToString()) }; var authProperties = new AuthenticationProperties { IsPersistent = resource.RememberMe == "on" }; try { await HttpContext.SignInAsync(AuthenticationType.Forms.ToString(), new ClaimsPrincipal(new ClaimsIdentity(claims, "Cookies", "user", "identifier")), authProperties); } catch (CryptographicException e) { if (e.InnerException is XmlException) { _logger.Error(e, "Failed to authenticate user due to corrupt XML. Please remove all XML files from {0} and restart Radarr", Path.Combine(_appFolderInfo.AppDataFolder, "asp")); } else { _logger.Error(e, "Failed to authenticate user. {0}", e.Message); } return Unauthorized(); } if (returnUrl.IsNullOrWhiteSpace() || !Url.IsLocalUrl(returnUrl)) { return Redirect(_configFileProvider.UrlBase + "/"); } if (_configFileProvider.UrlBase.IsNullOrWhiteSpace() || returnUrl.StartsWith(_configFileProvider.UrlBase)) { return Redirect(returnUrl); } return Redirect(_configFileProvider.UrlBase + returnUrl); } [HttpGet("logout")] public async Task Logout() { _authService.Logout(HttpContext); await HttpContext.SignOutAsync(AuthenticationType.Forms.ToString()); return Redirect(_configFileProvider.UrlBase + "/"); } } }