Foxchat.NET/Foxchat.Identity/Controllers/Oauth/TokenController.cs

74 lines
2.1 KiB
C#
Raw Normal View History

using Foxchat.Core;
using Foxchat.Identity.Database;
using Foxchat.Identity.Database.Models;
using Microsoft.AspNetCore.Mvc;
using NodaTime;
namespace Foxchat.Identity.Controllers.Oauth;
[ApiController]
[Route("/_fox/ident/oauth/token")]
public class TokenController(ILogger logger, IdentityContext db, IClock clock) : ControllerBase
{
[HttpPost]
public async Task<IActionResult> PostToken([FromBody] PostTokenRequest req)
{
var app = await db.GetApplicationAsync(req.ClientId, req.ClientSecret);
var scopes = req.Scope.Split(' ');
2024-05-20 19:42:04 +02:00
if (scopes.Except(app.Scopes).Any())
{
throw new ApiError.BadRequest("Invalid or unauthorized scopes");
}
switch (req.GrantType)
{
case "client_credentials":
return await HandleClientCredentialsAsync(app, scopes);
case "authorization_code":
break;
default:
throw new ApiError.BadRequest("Unknown grant_type");
}
throw new NotImplementedException();
}
private async Task<IActionResult> HandleClientCredentialsAsync(Application app, string[] scopes)
{
// TODO: make this configurable
var expiry = clock.GetCurrentInstant() + Duration.FromDays(365);
var (token, hash) = Token.Generate();
var tokenObj = new Token
{
Hash = hash,
Scopes = scopes,
Expires = expiry,
ApplicationId = app.Id
};
await db.AddAsync(tokenObj);
await db.SaveChangesAsync();
logger.Debug("Created token with scopes {Scopes} for application {ApplicationId}", scopes, app.Id);
return Ok(new PostTokenResponse(token, scopes, expiry));
}
public record PostTokenRequest(
string GrantType,
string ClientId,
string ClientSecret,
string Scope,
// Optional parameters
string? Code,
string? RedirectUri
);
public record PostTokenResponse(
string Token,
string[] Scopes,
Instant Expires
);
}