Authentication layer with user profile

This commit is contained in:
Mike 2024-12-14 17:48:03 +00:00
parent 5088f66c26
commit 21fc72ae5f
7 changed files with 168 additions and 11 deletions

View file

@ -1,4 +1,4 @@
// <copyright file="OAuthController.cs" company="alveus.dev">
// <copyright file="OAuthApiController.cs" company="alveus.dev">
// Copyright (c) alveus.dev. All rights reserved. Licensed under the MIT License.
// </copyright>
@ -16,15 +16,15 @@ namespace Astral.ApiServer.Controllers;
/// OAuth authentication controller.
/// </summary>
[Route("oauth")]
public class OAuthController : BaseApiController
public class OAuthApiController : BaseApiController
{
private readonly IAuthenticationService _authenticationService;
/// <summary>
/// Initializes a new instance of the <see cref="OAuthController"/> class.
/// Initializes a new instance of the <see cref="OAuthApiController"/> class.
/// </summary>
/// <param name="authenticationService">Instance of <see cref="IAuthenticationService"/>.</param>
public OAuthController(IAuthenticationService authenticationService)
public OAuthApiController(IAuthenticationService authenticationService)
{
_authenticationService = authenticationService;
}

View file

@ -0,0 +1,67 @@
// <copyright file="UserApiController.cs" company="alveus.dev">
// Copyright (c) alveus.dev. All rights reserved. Licensed under the MIT License.
// </copyright>
using Astral.ApiServer.Models;
using Astral.Services.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Astral.ApiServer.Controllers.V1;
/// <summary>
/// User api controller.
/// </summary>
[Route("api/v1/user")]
[Authorize]
public class UserApiController : BaseApiController
{
private readonly IIdentityProvider _identityProvider;
/// <summary>
/// Initializes a new instance of the <see cref="UserApiController"/> class.
/// </summary>
/// <param name="identityProvider">Instance of <see cref="IIdentityProvider"/>.</param>
public UserApiController(IIdentityProvider identityProvider)
{
_identityProvider = identityProvider;
}
/// <summary>
/// Get the user's profile.
/// </summary>
[HttpGet("profile")]
public IActionResult GetUserProfile()
{
var userId = _identityProvider.GetUserId();
var userName = _identityProvider.GetUserName();
return new JsonResult(new UserProfileResultModel()
{
Success = true,
AccountId = userId,
Username = userName,
XmppPassword = string.Empty,
DiscourseApiKey = string.Empty
});
}
/// <summary>
/// Does nothing for now since I believe the locker feature is deprecated.
/// </summary>
[HttpPost("locker")]
public IActionResult PostLocker()
{
return SuccessResult();
}
/// <summary>
/// Does nothing for now since I believe the locker feature is deprecated.
/// </summary>
[HttpGet("locker")]
public IActionResult GetLocker()
{
return SuccessResult();
}
}

View file

@ -33,7 +33,7 @@ public class TokenGrantResultModel : ResultModel
ExpiresIn = sessionDto.AccessTokenExpires.Ticks;
RefreshToken = sessionDto.RefreshToken;
Scope = sessionDto.Scope.ToString().ToLowerInvariant();
AccountId = sessionDto.UserId.ToString();
AccountId = sessionDto.UserId;
AccountName = sessionDto.UserName;
TokenType = "Bearer";
AccountRoles = sessionDto.Role.GetAccessibleRoles().Select(role => role.ToString().ToLowerInvariant()).ToList();
@ -79,7 +79,7 @@ public class TokenGrantResultModel : ResultModel
/// The user's id.
/// </summary>
[JsonPropertyName("account_id")]
public string AccountId { get; set; }
public Guid AccountId { get; set; }
/// <summary>
/// The user's name.

View file

@ -0,0 +1,38 @@
// <copyright file="UserProfileResultModel.cs" company="alveus.dev">
// Copyright (c) alveus.dev. All rights reserved. Licensed under the MIT License.
// </copyright>
using System.Text.Json.Serialization;
using Astral.ApiServer.Models.Common;
namespace Astral.ApiServer.Models;
/// <summary>
/// User profile request result.
/// </summary>
public class UserProfileResultModel : ResultModel
{
/// <summary>
/// Account id (Even used?).
/// </summary>
[JsonPropertyName("accountId")]
public Guid AccountId { get; set; }
/// <summary>
/// Username.
/// </summary>
[JsonPropertyName("username")]
public string Username { get; set; }
/// <summary>
/// Discourse api key (Even used?).
/// </summary>
[JsonPropertyName("discourse_api_key")]
public string DiscourseApiKey { get; set; }
/// <summary>
/// XMPP Password (Even used?).
/// </summary>
[JsonPropertyName("xmpp_password")]
public string XmppPassword { get; set; }
}

View file

@ -36,6 +36,7 @@ builder.Services.AddHttpUserAgentMemoryCachedParser(opt =>
builder.Services.AddHostedService<StartupService>();
builder.Services.AddAstralApiServer();
builder.Services.AddAstralCore();
builder.Services.AddAstralServices();
builder.Services.AddAstralDAL();
@ -105,4 +106,4 @@ if (app.Environment.IsDevelopment())
app.UseAuthorization();
app.MapControllers();
await app.RunAsync();
await app.RunAsync();

View file

@ -0,0 +1,45 @@
// <copyright file="IdentityProvider.cs" company="alveus.dev">
// Copyright (c) alveus.dev. All rights reserved. Licensed under the MIT License.
// </copyright>
using System.Security.Claims;
using Astral.Services.Constants;
using Astral.Services.Interfaces;
using Injectio.Attributes;
namespace Astral.ApiServer.Providers;
/// <inheritdoc />
[RegisterScoped]
public class IdentityProvider : IIdentityProvider
{
/// <summary>
/// Initializes a new instance of the <see cref="IdentityProvider"/> class.
/// </summary>
/// <param name="httpContextAccessor">Instance of <see cref="IHttpContextAccessor"/>.</param>
public IdentityProvider(IHttpContextAccessor httpContextAccessor)
{
var claims = httpContextAccessor.HttpContext?.User.Claims;
if (claims is not null)
{
Claims = claims;
}
}
/// <summary>
/// Session claims.
/// </summary>
private IEnumerable<Claim> Claims { get; set; }
/// <inheritdoc />
public Guid GetUserId()
{
return Guid.TryParse(Claims.FirstOrDefault(c => c.Type == ClaimIds.UserId)?.Value, out var guid) ? guid : Guid.Empty;
}
/// <inheritdoc />
public string GetUserName()
{
return Claims.FirstOrDefault(c => c.Type == ClaimIds.UserName)?.Value;
}
}

View file

@ -5,13 +5,19 @@
namespace Astral.Services.Interfaces;
/// <summary>
/// Identify who the requesting user is.
/// Identify who the requesting user is.
/// </summary>
public interface IIdentityProvider
{
/// <summary>
/// Get the user id of the requester.
/// Get the user id of the authorised agent.
/// </summary>
/// <returns>String representing the user id, or null if none.</returns>
string GetRequestingUserId();
/// <returns>Guid representing the user id, or empty guid if none.</returns>
Guid GetUserId();
/// <summary>
/// Get the username of the authorised agent.
/// </summary>
/// <returns>Username, or null if none.</returns>
string GetUserName();
}