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

69 lines
2.1 KiB
C#

using Foxchat.Core;
using Foxchat.Identity.Database;
using Foxchat.Identity.Database.Models;
using Foxchat.Identity.Utils;
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 appScopes = app.Scopes.ExpandScopes();
var scopes = req.Scope.Split(' ');
if (scopes.Except(appScopes).Any())
{
throw new ApiError.Forbidden("Invalid or unauthorized scopes", scopes.Except(appScopes));
}
switch (req.GrantType)
{
case OauthUtils.ClientCredentials:
return await HandleClientCredentialsAsync(app, scopes);
case OauthUtils.AuthorizationCode:
// TODO
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, tokenObj) = Token.Create(null, app, scopes, expiry);
db.Add(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
);
}