// 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, $"| {claim.Type} | {claim.Value} |
");
}
content.Append("
");
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 };
}
}
}