using System.Security.Claims; using Asp.Versioning; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; namespace InboxIntel.Api.Controllers; [ApiController] [EnableRateLimiting("auth")] // AUDIT H-2: throttle login/challenge attempts per IP [ApiVersion("1.0")] [Route("api/v{version:apiVersion}/[controller]")] public class AuthController : ControllerBase { /// Begins the Google OAuth2 login flow. [HttpGet("login")] [AllowAnonymous] public IActionResult Login([FromQuery] string? returnUrl = "/") { // V-09: only allow local post-login redirects; reject absolute/off-host targets // so the OAuth flow can't be abused as an open redirect for phishing. var safe = !string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl) ? returnUrl : "/app"; return Challenge(new AuthenticationProperties { RedirectUri = safe }, GoogleDefaults.AuthenticationScheme); } [HttpPost("logout")] [Authorize] public async Task Logout() { await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return NoContent(); } /// Returns the currently signed-in user, or 401. [HttpGet("me")] [Authorize] public IActionResult Me() => Ok(new { UserId = User.FindFirstValue("inboxintel:uid"), Email = User.FindFirstValue(ClaimTypes.Email), Name = User.FindFirstValue(ClaimTypes.Name) }); }