master
D4VID 1 year ago
parent e6e6c73471
commit c48b921c78

@ -1,5 +1,7 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using OAuthServer.Services; using OAuthServer.Services;
@ -7,23 +9,24 @@ namespace OAuthServer.Controllers;
[ApiController] [ApiController]
[Route("oauth")] [Route("oauth")]
public class OAuthController : ControllerBase { public class OAuthController(
private readonly ILogger<OAuthController> _logger; ILogger<OAuthController> logger,
private readonly JwtService _jwt; JwtService jwt,
IDataProtectionProvider dataProtectionProvider
) : ControllerBase {
private readonly Dictionary<string, string> _clients = new() {
{"lmao", "yeet"},
};
public OAuthController(ILogger<OAuthController> logger, JwtService jwt) {
_logger = logger;
_jwt = jwt;
}
[Authorize] [Authorize]
[HttpGet("authorize")] [HttpGet("authorize")]
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
public ActionResult Authorize( public ActionResult Authorize(
[Required, Url] string redirect_uri, [Required, Url] string redirect_uri,
string response_type, string? response_type,
string client_id, string? client_id,
string state string? state
) { ) {
if (string.IsNullOrEmpty(response_type) || string.IsNullOrEmpty(client_id) || string.IsNullOrEmpty(state)) { if (string.IsNullOrEmpty(response_type) || string.IsNullOrEmpty(client_id) || string.IsNullOrEmpty(state)) {
return Redirect($"{redirect_uri}?error=invalid_request"); return Redirect($"{redirect_uri}?error=invalid_request");
@ -33,12 +36,19 @@ public class OAuthController : ControllerBase {
return Redirect($"{redirect_uri}?error=unsupported_response_type&state={state}"); return Redirect($"{redirect_uri}?error=unsupported_response_type&state={state}");
} }
if (client_id != "lmao") { if (!_clients.ContainsKey(client_id)) {
return Redirect($"{redirect_uri}?error=access_denied&error_description=Invalid+client+id&state={state}"); logger.LogInformation("Unknown client id");
return Redirect($"{redirect_uri}?error=unauthorized_client&state={state}");
} }
// TODO: generate code IDataProtector protector = dataProtectionProvider.CreateProtector("oauth");
string code = Guid.NewGuid().ToString(); CodeObject codeObject = new CodeObject(
ClientId: client_id,
RedirectUri: redirect_uri,
Expiry: DateTime.UtcNow.AddMinutes(5)
);
string code = protector.Protect(JsonSerializer.Serialize(codeObject));
return Redirect($"{redirect_uri}?code={code}&state={state}"); return Redirect($"{redirect_uri}?code={code}&state={state}");
} }
@ -54,9 +64,11 @@ public class OAuthController : ControllerBase {
[HttpPost("token")] [HttpPost("token")]
[Consumes("application/x-www-form-urlencoded")] [Consumes("application/x-www-form-urlencoded")]
public ActionResult GenerateToken([FromForm] GenerateTokenRequest request) { public ActionResult GenerateToken([FromForm] GenerateTokenRequest request) {
if (string.IsNullOrEmpty(request.grant_type) || string.IsNullOrEmpty(request.code) || if (string.IsNullOrEmpty(request.grant_type) ||
string.IsNullOrEmpty(request.code) ||
string.IsNullOrEmpty(request.redirect_uri) || string.IsNullOrEmpty(request.redirect_uri) ||
string.IsNullOrEmpty(request.client_id)) { string.IsNullOrEmpty(request.client_id) ||
string.IsNullOrEmpty(request.client_secret)) {
return BadRequest(new {error = "invalid_request"}); return BadRequest(new {error = "invalid_request"});
} }
@ -64,15 +76,44 @@ public class OAuthController : ControllerBase {
return BadRequest(new {error = "unsupported_grant_type"}); return BadRequest(new {error = "unsupported_grant_type"});
} }
if (request.client_id != "lmao") { if (!_clients.TryGetValue(request.client_id, out string? clientSecret)) {
return BadRequest(new {error = "invalid_client"}); logger.LogInformation("Unknown client id");
return BadRequest(new {error = "unauthorized_client"});
}
if (request.client_secret != clientSecret) {
logger.LogInformation("Invalid client secret");
return BadRequest(new {error = "unauthorized_client"});
}
IDataProtector protector = dataProtectionProvider.CreateProtector("oauth");
CodeObject? codeObject;
try {
codeObject = JsonSerializer.Deserialize<CodeObject>(protector.Unprotect(request.code));
} catch (Exception) {
return BadRequest(new {error = "invalid_request"});
}
if (codeObject == null) {
return BadRequest(new {error = "invalid_request"});
} }
string token = _jwt.GenerateToken(); if (codeObject.ClientId != request.client_id || codeObject.RedirectUri != request.redirect_uri) {
return BadRequest(new {error = "invalid_request"});
}
if (DateTime.UtcNow > codeObject.Expiry) {
logger.LogInformation("Expired token");
return BadRequest(new {error = "invalid_grant"});
}
string token = jwt.GenerateToken();
Response.Headers.Append("Cache-Control", "no-store"); Response.Headers.Append("Cache-Control", "no-store");
Response.Headers.Append("Pragma", "no-cache"); Response.Headers.Append("Pragma", "no-cache");
return Ok(new {access_token = token, token_type = "bearer"}); return Ok(new {access_token = token, token_type = "bearer"});
} }
private record CodeObject(string ClientId, string RedirectUri, DateTime Expiry);
} }
Loading…
Cancel
Save