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)
});
}