Authentication layer with user profile
This commit is contained in:
parent
5088f66c26
commit
21fc72ae5f
7 changed files with 168 additions and 11 deletions
|
@ -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;
|
||||
}
|
67
Astral.ApiServer/Controllers/V1/UserApiController.cs
Normal file
67
Astral.ApiServer/Controllers/V1/UserApiController.cs
Normal 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
|
|
38
Astral.ApiServer/Models/UserProfileResultModel.cs
Normal file
38
Astral.ApiServer/Models/UserProfileResultModel.cs
Normal 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; }
|
||||
}
|
|
@ -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();
|
||||
|
|
45
Astral.ApiServer/Providers/IdentityProvider.cs
Normal file
45
Astral.ApiServer/Providers/IdentityProvider.cs
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue