Add Steam OpenID authentication
Deploy Promiscuity Auth API / deploy (push) Failing after 20s
Deploy Promiscuity Character API / deploy (push) Failing after 19s
Deploy Promiscuity Crafting API / deploy (push) Failing after 20s
Deploy Promiscuity Inventory API / deploy (push) Failing after 19s
Deploy Promiscuity Locations API / deploy (push) Failing after 19s
Deploy Promiscuity Mail API / deploy (push) Failing after 20s
Deploy Promiscuity World API / deploy (push) Failing after 20s
k8s smoke test / test (push) Failing after 20s

This commit is contained in:
2026-07-20 00:30:06 -05:00
parent 18c3d6fc5d
commit cde0e28e44
16 changed files with 564 additions and 29 deletions
@@ -2,13 +2,11 @@ using AuthApi.Models;
using AuthApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using MongoDB.Driver;
using MongoDB.Bson;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Mail;
using System.Security.Claims;
using System.Text;
using System.Text.RegularExpressions;
using System.Net.Http.Json;
@@ -22,10 +20,12 @@ public class AuthController : ControllerBase
private readonly IConfiguration _cfg;
private readonly BlacklistService _blacklist;
private readonly IHttpClientFactory _httpClients;
private readonly JwtTokenService _tokens;
public AuthController(UserService users, IConfiguration cfg, BlacklistService blacklist, IHttpClientFactory httpClients)
public AuthController(UserService users, IConfiguration cfg, BlacklistService blacklist,
IHttpClientFactory httpClients, JwtTokenService tokens)
{
_users = users; _cfg = cfg; _blacklist = blacklist; _httpClients = httpClients;
_users = users; _cfg = cfg; _blacklist = blacklist; _httpClients = httpClients; _tokens = tokens;
}
[HttpPost("register")]
@@ -62,11 +62,12 @@ public class AuthController : ControllerBase
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginRequest req)
{
var user = await _users.GetByUsernameAsync(req.Username);
if (user == null || !BCrypt.Net.BCrypt.Verify(req.Password, user.PasswordHash))
var candidates = await _users.GetByLoginCandidatesAsync(req.Username);
var user = candidates.FirstOrDefault(candidate => BCrypt.Net.BCrypt.Verify(req.Password, candidate.PasswordHash));
if (user == null)
return Unauthorized();
var (accessToken, jti, expUtc) = GenerateJwtToken(user);
var (accessToken, jti, expUtc) = _tokens.Generate(user);
user.RefreshToken = Guid.NewGuid().ToString("N");
user.RefreshTokenExpiry = DateTime.UtcNow.AddDays(7);
await _users.UpdateAsync(user);
@@ -81,7 +82,7 @@ public class AuthController : ControllerBase
if (user == null || user.RefreshToken != req.RefreshToken || user.RefreshTokenExpiry < DateTime.UtcNow)
return Unauthorized("Invalid or expired refresh token");
var (accessToken, _, expUtc) = GenerateJwtToken(user);
var (accessToken, _, expUtc) = _tokens.Generate(user);
return Ok(new { accessToken, exp = expUtc });
}
@@ -186,27 +187,6 @@ public class AuthController : ControllerBase
[Authorize(Roles = "SUPER")]
public async Task<IActionResult> GetAllUsers() => Ok(await _users.GetAllAsync());
private (string token, string jti, DateTime expUtc) GenerateJwtToken(User user)
{
var key = Encoding.UTF8.GetBytes(_cfg["Jwt:Key"]!);
var issuer = _cfg["Jwt:Issuer"] ?? "GameAuthApi";
var audience = _cfg["Jwt:Audience"] ?? issuer;
var creds = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256);
var jti = Guid.NewGuid().ToString("N");
var claims = new[]
{
new Claim(ClaimTypes.Name, user.Username),
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Role, user.Role),
new Claim(JwtRegisteredClaimNames.Jti, jti)
};
var exp = DateTime.UtcNow.AddMinutes(15);
var token = new JwtSecurityToken(issuer, audience, claims, expires: exp, signingCredentials: creds);
return (new JwtSecurityTokenHandler().WriteToken(token), jti, exp);
}
private async Task<User?> CurrentUserAsync()
{
var id = User.FindFirstValue(ClaimTypes.NameIdentifier);