// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Globalization; using System.Net; using System.Text; using System.Threading.Tasks; using Horde.Server.Acls; using Horde.Server.Authentication; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; namespace Horde.Server.Server { /// /// Controller managing account status /// [ApiController] [Route("[controller]")] public class AccountController : Controller { /// /// Style sheet for HTML responses /// const string StyleSheet = "body { font-family: 'Segoe UI', 'Roboto', arial, sans-serif; } " + "p { margin:20px; font-size:13px; } " + "h1 { margin:20px; font-size:32px; font-weight:200; } " + "table { margin:10px 20px; } " + "td { margin:5px; font-size:13px; }"; readonly string _authenticationScheme; readonly IOptionsSnapshot _globalConfig; /// /// Constructor /// public AccountController(IOptionsMonitor serverSettings, IOptionsSnapshot globalConfig) { _authenticationScheme = GetAuthScheme(serverSettings.CurrentValue.AuthMethod); _globalConfig = globalConfig; } /// /// Get auth scheme name for a given auth method /// /// Authentication method /// Name of authentication scheme public static string GetAuthScheme(AuthMethod method) { return method switch { AuthMethod.Anonymous => AnonymousAuthenticationHandler.AuthenticationScheme, AuthMethod.Okta => OktaDefaults.AuthenticationScheme, AuthMethod.OpenIdConnect => OpenIdConnectDefaults.AuthenticationScheme, _ => throw new ArgumentOutOfRangeException(nameof(method), method, null) }; } /// /// Gets the current login status /// /// The current login state [HttpGet] [Route("/account")] public ActionResult State() { StringBuilder content = new StringBuilder(); content.Append($"

Horde Server

"); if (User.Identity?.IsAuthenticated ?? false) { content.Append(CultureInfo.InvariantCulture, $"

User {User.Identity?.Name} is logged in. Log out

"); if (_globalConfig.Value.Authorize(AdminAclAction.AdminWrite, User)) { content.Append("

"); content.Append("Get bearer token
"); content.Append("Get agent registration token
"); content.Append("Get agent software upload token
"); content.Append("Get agent software download token
"); content.Append("Get configuration token
"); content.Append("Get chained job token
"); content.Append("

"); } content.Append(CultureInfo.InvariantCulture, $"

Claims for {User.Identity?.Name}:"); content.Append(""); foreach (System.Security.Claims.Claim claim in User.Claims) { content.Append(CultureInfo.InvariantCulture, $""); } content.Append("
{claim.Type}{claim.Value}
"); content.Append("

"); content.Append(CultureInfo.InvariantCulture, $"

Built from Perforce

"); } else { content.Append("

Login with OAuth2

"); } content.Append(""); return new ContentResult { ContentType = "text/html", StatusCode = (int)HttpStatusCode.OK, Content = content.ToString() }; } /// /// Login to the server /// /// Http result [HttpGet] [Route("/account/login")] public IActionResult Login() { return new ChallengeResult(_authenticationScheme, new AuthenticationProperties { RedirectUri = "/account" }); } /// /// Logout of the current account /// /// Http result [HttpGet] [Route("/account/logout")] public async Task Logout() { await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); try { await HttpContext.SignOutAsync(_authenticationScheme); } catch { } string content = $"

User has been logged out. Returning to login page.

"; return new ContentResult { ContentType = "text/html", StatusCode = (int)HttpStatusCode.OK, Content = content }; } } }