69 lines
2.1 KiB
C#
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
|
|
);
|
|
}
|