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

70 lines
2.1 KiB
C#
Raw Normal View History

using Foxchat.Core;
using Foxchat.Identity.Database;
using Foxchat.Identity.Database.Models;
2024-05-21 21:21:34 +02:00
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(' ');
2024-05-21 21:21:34 +02:00
if (scopes.Except(appScopes).Any())
{
2024-05-21 21:21:34 +02:00
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:
2024-05-20 20:37:22 +02:00
// 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);
2024-05-20 21:59:30 +02:00
var (token, tokenObj) = Token.Create(null, app, scopes, expiry);
2024-05-21 17:45:35 +02:00
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
);
}