using Microsoft.AspNetCore.Mvc; using Auth.Services.DatabaseService; using System.Web.Http; using Auth.Entities; using System.Text; using System.Security.Cryptography; using Microsoft.IdentityModel.Tokens; namespace Auth.Controllers { [ApiController] [Route("api/oauth/")] public class OAuthController : MistoxControllerBase { public OAuthController(DatabaseService db) : base(db) { } /* private string GenerateCodeChallenge(string codeVerifier) { using var sha256 = SHA256.Create(); var bytes = sha256.ComputeHash(Encoding.ASCII.GetBytes(codeVerifier)); return Base64UrlEncode(bytes); } private string Base64UrlEncode(byte[] input) { return Convert.ToBase64String(input) .TrimEnd('=') .Replace('+', '-') .Replace('/', '_'); } [HttpGet("authorize")] public async Task Authorize([FromQuery] AuthorizationRequest request) { try { if (request.ResponseType != "code") { return BadRequest("unsupported_code_type"); } string RequestingApp = request.ClientId; // Verify login // create guid // set guid to account // save account to database return NotFound("User is not logged in"); } catch (Exception ex) { Console.WriteLine("Delete Error: " + ex.Message); return NotFound("An internal server error has occured"); } } [HttpPost("token")] public async Task Token([FromForm] TokenRequest request) { try { // Validate Grant Code if (request.GrantType != "authorization_code") { return BadRequest(new { error = "unsupported_grant_type" }); } // Validate Required Parameters if (string.IsNullOrEmpty(request.Code) || string.IsNullOrEmpty(request.RedirectUri) || string.IsNullOrEmpty(request.CodeVerifier)) { return BadRequest(new { error = "invalid_request" }); } // Check if LoginToken is expired var authCode = AuthorizationCodeStore.Get(request.Code); if (authCode == null || authCode.IsExpired) { return BadRequest(new { error = "invalid_grant" }); } // Verify redirect_uri matches if (!string.Equals(authCode.RedirectUri, request.RedirectUri, StringComparison.Ordinal)) { return BadRequest(new { error = "invalid_grant" }); } // 5. Verify code_verifier (PKCE check) var expectedChallenge = GenerateCodeChallenge(request.CodeVerifier); if (authCode.CodeChallenge != expectedChallenge) { return BadRequest(new { error = "invalid_grant", error_description = "PKCE verification failed" }); } // 6. Optionally verify client_id/client_secret (for confidential clients) // ... // 7. Issue access token (and refresh token if needed) var accessToken = TokenService.GenerateAccessToken(authCode.UserId, authCode.ClientId, authCode.Scope); var refreshToken = TokenService.GenerateRefreshToken(authCode.UserId, authCode.ClientId); // 8. Invalidate used authorization code (one-time use) AuthorizationCodeStore.Remove(request.Code); // 9. Return token response return Ok(new { access_token = accessToken, token_type = "Bearer", expires_in = 3600, refresh_token = refreshToken }); } catch (Exception ex) { Console.WriteLine("Delete Error: " + ex.Message); return NotFound("An internal server error has occured"); } } [HttpGet("/userinfo")] public async Task UserInfo() { Account user = await getLoggedInUser(); if (user == null) { return Unauthorized(); } var claims = new { sub = user.ID, preferred_username = user.UserName, email = user.Email, email_verified = user.EmailVerified }; return Ok(claims); } [HttpGet("/.well-known/openid-configuration")] public IActionResult OpenIdConfiguration() { var issuer = "https://your-auth-server.com"; var config = new { issuer = issuer, authorization_endpoint = $"{issuer}/authorize", token_endpoint = $"{issuer}/token", userinfo_endpoint = $"{issuer}/userinfo", jwks_uri = $"{issuer}/.well-known/jwks.json", response_types_supported = new[] { "code", "token", "id_token", "code id_token" }, subject_types_supported = new[] { "public" }, id_token_signing_alg_values_supported = new[] { "RS256" }, scopes_supported = new[] { "openid", "profile", "email" }, token_endpoint_auth_methods_supported = new[] { "client_secret_basic", "private_key_jwt" }, claims_supported = new[] { "sub", "name", "preferred_username", "email", "email_verified" } }; return Ok(config); } [HttpGet("/.well-known/jwks.json")] public IActionResult GetJwks() { var key = new RsaSecurityKey(rsa) { KeyId = "my-key-id-123" // a unique key ID, important for clients }; var parameters = key.Rsa.ExportParameters(false); // export public key only var jwk = new JsonWebKey { Kid = key.KeyId, Kty = "RSA", Use = "sig", // signing Alg = SecurityAlgorithms.RsaSha256, N = Base64UrlEncoder.Encode(parameters.Modulus), E = Base64UrlEncoder.Encode(parameters.Exponent) }; var jwks = new { keys = new[] { jwk } }; return Ok(jwks); } */ } }