Compare commits

..

No commits in common. "development" and "main" have entirely different histories.

56 changed files with 612 additions and 926 deletions

View File

@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.10.34928.147 VisualStudioVersion = 17.10.34928.147
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Thalos.BuildingBlocks", "Core.Thalos.BuildingBlocks\Core.Thalos.BuildingBlocks.csproj", "{C902AB37-E6D1-4CE7-B271-0E3969C989F3}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Cerberos.Adapters", "Core.Cerberos.Adapters\Core.Cerberos.Adapters.csproj", "{C902AB37-E6D1-4CE7-B271-0E3969C989F3}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -1,6 +1,11 @@
using System.Text.Json; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters
{ {
public class BaseAdapterResponse public class BaseAdapterResponse
{ {

View File

@ -1,22 +1,30 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="ModuleAdapter.cs"> // <copyright file="ModuleAdapter.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using Core.Blueprint.Mongo; using Core.Cerberos.Adapters.Common.Enums;
using MongoDB.Bson; using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters
{ {
/// <summary> /// <summary>
/// Adapter for representing a module. /// Adapter for representing a module.
/// </summary> /// </summary>
[CollectionAttributeName("Modules")] public class ModuleAdapter
public class ModuleAdapter : Document
{ {
/// <summary>
/// Gets or sets the ID of the module.
/// </summary>
[BsonId]
[BsonElement("_id")]
[BsonRepresentation(BsonType.ObjectId)]
[JsonPropertyName("id")]
public string Id { get; set; } = null!;
/// <summary> /// <summary>
/// Gets or sets the name of the module. /// Gets or sets the name of the module.
/// </summary> /// </summary>
@ -65,5 +73,46 @@ namespace Core.Thalos.BuildingBlocks
[JsonPropertyName("application")] [JsonPropertyName("application")]
[JsonConverter(typeof(JsonStringEnumConverter))] [JsonConverter(typeof(JsonStringEnumConverter))]
public ApplicationsEnum? Application { get; set; } = null!; public ApplicationsEnum? Application { get; set; } = null!;
/// <summary>
/// Gets or sets the date and time when the module was created.
/// </summary>
[BsonElement("createdAt")]
[BsonRepresentation(BsonType.DateTime)]
[JsonPropertyName("createdAt")]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// Gets or sets the user who created the module.
/// </summary>
[BsonElement("createdBy")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("createdBy")]
public string? CreatedBy { get; set; }
/// <summary>
/// Gets or sets the date and time when the module was last updated.
/// </summary>
[BsonElement("updatedAt")]
[BsonRepresentation(BsonType.DateTime)]
[JsonPropertyName("updatedAt")]
public DateTime? UpdatedAt { get; set; } = null;
/// <summary>
/// Gets or sets the user who last updated the module.
/// </summary>
[BsonElement("updatedBy")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("updatedBy")]
public string? UpdatedBy { get; set; } = null;
/// <summary>
/// Gets or sets the status of the module.
/// </summary>
[BsonElement("status")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("status")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public StatusEnum Status { get; set; } = StatusEnum.Active;
} }
} }

View File

@ -0,0 +1,95 @@
// ***********************************************************************
// <copyright file="PermissionAdapter.cs">
// Heath
// </copyright>
// ***********************************************************************
using Core.Cerberos.Adapters.Common.Constants;
using Core.Cerberos.Adapters.Common.Enums;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization;
namespace Core.Cerberos.Adapters
{
/// <summary>
/// Adapter for representing a permission.
/// </summary>
public class PermissionAdapter
{
/// <summary>
/// Gets or sets the ID of the entity.
/// </summary>
[BsonId]
[BsonElement("_id")]
[BsonRepresentation(BsonType.ObjectId)]
[JsonPropertyName("id")]
public string Id { get; set; } = null!;
/// <summary>
/// Gets or sets the name of the entity.
/// </summary>
[BsonElement("name")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("name")]
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the description of the entity.
/// </summary>
[BsonElement("description")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("description")]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the status of the entity object.
/// </summary>
[BsonElement("accessLevel")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("accessLevel")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public AccessLevelEnum? AccessLevel { get; set; } = null!;
/// <summary>
/// Gets or sets the date and time when the entity was created.
/// </summary>
[BsonElement("createdAt")]
[BsonRepresentation(BsonType.DateTime)]
[JsonPropertyName("createdAt")]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// Gets or sets the user who created the entity.
/// </summary>
[BsonElement("createdBy")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("createdBy")]
public string? CreatedBy { get; set; }
/// <summary>
/// Gets or sets the date and time when the entity was last updated.
/// </summary>
[BsonElement("updatedAt")]
[BsonRepresentation(BsonType.DateTime)]
[JsonPropertyName("updatedAt")]
public DateTime? UpdatedAt { get; set; } = null;
/// <summary>
/// Gets or sets the user who last updated the entity.
/// </summary>
[BsonElement("updatedBy")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("updatedBy")]
public string? UpdatedBy { get; set; } = null;
/// <summary>
/// Gets or sets the status of the entity.
/// </summary>
[BsonElement("status")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("status")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public StatusEnum Status { get; set; } = StatusEnum.Active;
}
}

View File

@ -0,0 +1,107 @@
// ***********************************************************************
// <copyright file="RoleAdapter.cs">
// Heath
// </copyright>
// ***********************************************************************
using Core.Cerberos.Adapters.Common.Enums;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization;
namespace Core.Cerberos.Adapters
{
/// <summary>
/// Adapter representing a role.
/// </summary>
public class RoleAdapter
{
/// <summary>
/// Gets or sets the unique identifier of the role.
/// </summary>
[BsonId]
[BsonElement("_id")]
[BsonRepresentation(BsonType.ObjectId)]
[JsonPropertyName("id")]
public string Id { get; set; } = null!;
/// <summary>
/// Gets or sets the name of the role.
/// </summary>
[BsonElement("name")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("name")]
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the description of the role.
/// </summary>
[BsonElement("description")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("description")]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the status of the entity.
/// </summary>
[BsonElement("applications")]
[JsonPropertyName("applications")]
[JsonConverter(typeof(EnumArrayJsonConverter<ApplicationsEnum>))]
public ApplicationsEnum[]? Applications { get; set; }
/// <summary>
/// Gets or sets the modules of the role.
/// </summary>
[BsonElement("modules")]
[JsonPropertyName("modules")]
public string[] Modules { get; set; } = null!;
/// <summary>
/// Gets or sets the permissions of the role.
/// </summary>
[BsonElement("permissions")]
[JsonPropertyName("permissions")]
public string[] Permissions { get; set; } = null!;
/// <summary>
/// Gets or sets the date and time when the entity was created.
/// </summary>
[BsonElement("createdAt")]
[BsonRepresentation(BsonType.DateTime)]
[JsonPropertyName("createdAt")]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// Gets or sets the user who created the entity.
/// </summary>
[BsonElement("createdBy")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("createdBy")]
public string? CreatedBy { get; set; }
/// <summary>
/// Gets or sets the date and time when the entity was last updated.
/// </summary>
[BsonElement("updatedAt")]
[BsonRepresentation(BsonType.DateTime)]
[JsonPropertyName("updatedAt")]
public DateTime? UpdatedAt { get; set; } = null;
/// <summary>
/// Gets or sets the user who last updated the entity.
/// </summary>
[BsonElement("updatedBy")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("updatedBy")]
public string? UpdatedBy { get; set; } = null;
/// <summary>
/// Gets or sets the status of the entity.
/// </summary>
[BsonElement("status")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("status")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public StatusEnum Status { get; set; } = StatusEnum.Active;
}
}

View File

@ -1,19 +1,18 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="TokenAdapter.cs"> // <copyright file="TokenAdapter.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters
{ {
public class TokenAdapter public class TokenAdapter
{ {
public UserAdapter? User { get; set; } public UserAdapter? User { get; set; }
public RoleAdapter? Role { get; set; } public RoleAdapter? Role { get; set; }
public TenantAdapter? Tenant { get; set; }
public IEnumerable<PermissionAdapter>? Permissions { get; set; } public IEnumerable<PermissionAdapter>? Permissions { get; set; }
public IEnumerable<ModuleAdapter> Modules { get; set; } = null!; public IEnumerable<ModuleAdapter>? Modules { get; set; }
} }
} }

View File

@ -1,21 +1,37 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="UserAdapter.cs"> // <copyright file="UserAdapter.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using Core.Blueprint.Mongo; using Core.Cerberos.Adapters.Common.Enums;
using MongoDB.Bson; using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters
{ {
/// <summary> /// <summary>
/// Adapter representing a user. /// Adapter representing a user.
/// </summary> /// </summary>
[CollectionAttributeName("Users")] public class UserAdapter : BaseAdapterResponse
public class UserAdapter : Document
{ {
/// <summary>
/// Gets or sets the unique identifier of the user.
/// </summary>
[BsonId]
[BsonElement("_id")]
[BsonRepresentation(BsonType.ObjectId)]
[JsonPropertyName("id")]
public string Id { get; set; } = null!;
/// <summary>
/// Gets or sets the guid of the user.
/// </summary>
[BsonElement("guid")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("guid")]
public string? Guid { get; set; }
/// <summary> /// <summary>
/// Gets or sets the email address of the user. /// Gets or sets the email address of the user.
/// </summary> /// </summary>
@ -56,14 +72,6 @@ namespace Core.Thalos.BuildingBlocks
[JsonPropertyName("displayName")] [JsonPropertyName("displayName")]
public string? DisplayName { get; set; } public string? DisplayName { get; set; }
/// <summary>
/// Gets or sets the Tenand ID of the user.
/// </summary>
[BsonElement("tenantId")]
[BsonRepresentation(BsonType.ObjectId)]
[JsonPropertyName("tenantId")]
public string TenantId { get; set; } = null!;
/// <summary> /// <summary>
/// Gets or sets the role ID of the user. /// Gets or sets the role ID of the user.
/// </summary> /// </summary>
@ -72,6 +80,28 @@ namespace Core.Thalos.BuildingBlocks
[JsonPropertyName("roleId")] [JsonPropertyName("roleId")]
public string RoleId { get; set; } = null!; public string RoleId { get; set; } = null!;
/// <summary>
/// Gets or sets the array of companies associated with the user.
/// </summary>
[BsonElement("companies")]
[JsonPropertyName("companies")]
public string[] Companies { get; set; } = null!;
/// <summary>
/// Gets or sets the array of projects associated with the user.
/// </summary>
[BsonElement("projects")]
[JsonPropertyName("projects")]
public string[]? Projects { get; set; }
/// <summary>
/// Gets or sets the boolean of the consent form accepted by the user.
/// </summary>
[BsonElement("consentFormAccepted")]
[JsonPropertyName("consentFormAccepted")]
[BsonIgnoreIfNull]
public bool ConsentFormAccepted { get; set; }
/// <summary> /// <summary>
/// Gets or sets the timestamp of the last login of the user. /// Gets or sets the timestamp of the last login of the user.
/// </summary> /// </summary>
@ -96,5 +126,46 @@ namespace Core.Thalos.BuildingBlocks
[BsonRepresentation(BsonType.String)] [BsonRepresentation(BsonType.String)]
[JsonPropertyName("token")] [JsonPropertyName("token")]
public string? Token { get; set; } = null; public string? Token { get; set; } = null;
/// <summary>
/// Gets or sets the date and time when the entity was created.
/// </summary>
[BsonElement("createdAt")]
[BsonRepresentation(BsonType.DateTime)]
[JsonPropertyName("createdAt")]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// Gets or sets the user who created the entity.
/// </summary>
[BsonElement("createdBy")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("createdBy")]
public string? CreatedBy { get; set; }
/// <summary>
/// Gets or sets the date and time when the entity was last updated.
/// </summary>
[BsonElement("updatedAt")]
[BsonRepresentation(BsonType.DateTime)]
[JsonPropertyName("updatedAt")]
public DateTime? UpdatedAt { get; set; } = null;
/// <summary>
/// Gets or sets the user who last updated the entity.
/// </summary>
[BsonElement("updatedBy")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("updatedBy")]
public string? UpdatedBy { get; set; } = null;
/// <summary>
/// Gets or sets the status of the entity.
/// </summary>
[BsonElement("status")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("status")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public StatusEnum Status { get; set; } = StatusEnum.Active;
} }
} }

View File

@ -1,4 +1,4 @@
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters
{ {
public class Permission public class Permission
{ {

View File

@ -2,7 +2,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Attributes
{ {
/// <summary> /// <summary>
/// Custom authorization attribute that checks if the user has any of the required permissions. /// Custom authorization attribute that checks if the user has any of the required permissions.

View File

@ -1,12 +1,12 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="AccessLevelEnum.cs"> // <copyright file="AccessLevelEnum.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
/// <summary> /// <summary>
/// Specifies different access level for a permission. /// Specifies different access level for a permission.

View File

@ -1,9 +1,9 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="AzureAd.cs"> // <copyright file="AzureAd.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
/// <summary> /// <summary>
/// Constants for Azure Active Directory. /// Constants for Azure Active Directory.

View File

@ -1,9 +1,9 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="Claims.cs"> // <copyright file="Claims.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
/// <summary> /// <summary>
/// Constants for claims used in JWT tokens. /// Constants for claims used in JWT tokens.
@ -23,20 +23,10 @@ namespace Core.Thalos.BuildingBlocks
/// <summary> /// <summary>
/// Claim name for user's ID. /// Claim name for user's ID.
/// </summary> /// </summary>
public const string Id = "_id"; public const string Id = "id";
/// <summary> /// <summary>
/// Claim name for user's tenant name. /// Claim name for user's role ID.
/// </summary>
public const string Tenant = "tenant";
/// <summary>
/// Claim name for user's tenant identifier.
/// </summary>
public const string TenantId = "tenantId";
/// <summary>
/// Claim name for user's role name.
/// </summary> /// </summary>
public const string Role = "role"; public const string Role = "role";

View File

@ -1,4 +1,4 @@
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
public static class CollectionNames public static class CollectionNames
{ {

View File

@ -1,10 +1,10 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="EnvironmentVariables.cs"> // <copyright file="EnvironmentVariables.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
/// <summary> /// <summary>
/// Constants of the environment variables for this service. /// Constants of the environment variables for this service.

View File

@ -1,9 +1,9 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="KeyVaultConfiguration.cs"> // <copyright file="KeyVaultConfiguration.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
/// <summary> /// <summary>
/// Constants for Key Vault configuration. /// Constants for Key Vault configuration.

View File

@ -6,7 +6,7 @@
using System.Globalization; using System.Globalization;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
/// <summary> /// <summary>
/// Constants for the mime types. /// Constants for the mime types.

View File

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
namespace Core.Thalos.BuildingBlocks.Common.Constants
{
/// <summary>
/// Constants for policy.
/// </summary>
public class Policies
{
/// <summary>
/// Defines the access policy for reading mobile-related data.
/// This policy grants read-only permissions for retrieving mobile device information,
/// user mobile settings, or related data as per the application's authorization scope.
/// </summary>
public const string Read = "Read";
/// <summary>
/// Defines the access policy for writing mobile-related data.
/// This policy grants permissions to modify, update, or store mobile device information,
/// user mobile settings, or related data as per the application's authorization scope.
/// </summary>
public const string Write = "Write";
}
}

View File

@ -1,15 +0,0 @@
namespace Core.Thalos.BuildingBlocks.Common.Constants
{
public class Roles
{
/// <summary>
/// The role for Guest.
/// </summary>
public const string Guest = "684909c4826cd093b4f61c11";
/// <summary>
/// The role for Admin.
/// </summary>
public const string Admin = "68407642ec46a0e6fe1e8ec9";
}
}

View File

@ -1,10 +1,10 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="Routes.cs"> // <copyright file="Routes.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
/// <summary> /// <summary>
/// Constants of the routes of this service. /// Constants of the routes of this service.
@ -24,7 +24,7 @@ namespace Core.Thalos.BuildingBlocks
/// <summary> /// <summary>
/// The identifier route. /// The identifier route.
/// </summary> /// </summary>
public const string Id = "{_id}"; public const string Id = "{id}";
/// <summary> /// <summary>
/// The Authentication route. /// The Authentication route.
@ -74,7 +74,7 @@ namespace Core.Thalos.BuildingBlocks
/// <summary> /// <summary>
/// The ChangeStatus route. /// The ChangeStatus route.
/// </summary> /// </summary>
public const string ChangeStatus = "{_id}/{newStatus}/ChangeStatus"; public const string ChangeStatus = "{id}/{newStatus}/ChangeStatus";
/// <summary> /// <summary>
/// The AddCompany route. /// The AddCompany route.

View File

@ -1,4 +1,4 @@
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
/// <summary> /// <summary>
/// Constants for schemes. /// Constants for schemes.
@ -6,18 +6,13 @@
public class Schemes public class Schemes
{ {
/// <summary> /// <summary>
/// The default scheme. /// The heath scheme.
/// </summary> /// </summary>
public const string DefaultScheme = "DefaultScheme"; public const string HeathScheme = "HeathScheme";
/// <summary> /// <summary>
/// The azure scheme. /// The azure scheme.
/// </summary> /// </summary>
public const string AzureScheme = "AzureScheme"; public const string AzureScheme = "AzureScheme";
/// <summary>
/// The google scheme.
/// </summary>
public const string GoogleScheme = "GoogleScheme";
} }
} }

View File

@ -1,9 +1,9 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="AppSettings.cs"> // <copyright file="AppSettings.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Constants
{ {
/// <summary> /// <summary>
/// Constants for secrets in azure key vault. /// Constants for secrets in azure key vault.
@ -23,12 +23,12 @@ namespace Core.Thalos.BuildingBlocks
/// <summary> /// <summary>
/// The Issuer parameter for JWT settings. /// The Issuer parameter for JWT settings.
/// </summary> /// </summary>
public const string Issuer = "JWTIssuer"; public const string Issuer = "Issuer";
/// <summary> /// <summary>
/// The Audience parameter for JWT settings. /// The Audience parameter for JWT settings.
/// </summary> /// </summary>
public const string Audience = "JWTAudience"; public const string Audience = "Audience";
/// <summary> /// <summary>
/// The TokenExpirationInMinutes parameter for JWT settings. /// The TokenExpirationInMinutes parameter for JWT settings.
@ -49,15 +49,11 @@ namespace Core.Thalos.BuildingBlocks
public const string AzureADTenantId = "B2C:TenantId"; public const string AzureADTenantId = "B2C:TenantId";
public const string AzureADClientId = "B2C:ClientId"; public const string AzureADClientId = "B2C:ClientId";
public const string AzureADClientSecret = "B2C:ClientSecret"; public const string AzureADClientSecret = "B2C:ClientSecret";
public const string ThalosAppAuthorizationUrl = "Swagger:AuthorizationUri"; public const string HeathCerberosAppAuthorizationUrl = "Swagger:AuthorizationUri";
public const string ThalosAppTokenUrl = "Swagger:TokenUri"; public const string HeathCerberosAppTokenUrl = "Swagger:TokenUri";
public const string ThalosAppClientId = "Swagger:ClientId"; public const string HeathCerberosAppClientId = "Swagger:ClientId";
public const string ThalosAppScope = "Swagger:Scope"; public const string HeathCerberosAppScope = "Swagger:Scope";
public const string PrivateKey = "JwtTokenPrivateKey"; public const string PrivateKey = "B2C:JwtIssuerOptions:TokenPrivateKey";
public const string PublicKey = "JwtTokenPublicKey"; public const string PublicKey = "B2C:JwtIssuerOptions:TokenPublicKey";
public const string GoogleClientId = "GoogleClientId";
public const string GoogleClientSecret = "GoogleClientSecret";
public const string GoogleRedirectUri = "GoogleRedirectUri";
public const string GoogleLocalRedirectUri = "GoogleLocalRedirectUri";
} }
} }

View File

@ -1,12 +1,12 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="ApplicationsEnum.cs"> // <copyright file="ApplicationsEnum.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Enums
{ {
/// <summary> /// <summary>
/// Defines the applications associated with the role. /// Defines the applications associated with the role.
@ -15,13 +15,28 @@ namespace Core.Thalos.BuildingBlocks
public enum ApplicationsEnum public enum ApplicationsEnum
{ {
/// <summary> /// <summary>
/// Thalos application. /// LSA Web Portal application.
/// </summary> /// </summary>
Thalos = 0, LSAWebPortal = 0,
/// <summary> /// <summary>
/// DreamViewer application. /// Customer DashBoard application.
/// </summary> /// </summary>
DreamViewer = 1, CustomerDashboard = 1,
/// <summary>
/// Discover application.
/// </summary>
Discover = 2,
/// <summary>
/// LSA Mobile application.
/// </summary>
LSAMobile = 3,
/// <summary>
/// BluePrint application.
/// </summary>
BluePrint = 4,
} }
} }

View File

@ -1,12 +1,12 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="StatusEnum.cs"> // <copyright file="StatusEnum.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Common.Enums
{ {
/// <summary> /// <summary>
/// Defines the status of an entity. /// Defines the status of an entity.

View File

@ -1,6 +1,6 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="EnumSchemaFilter.cs"> // <copyright file="EnumSchemaFilter.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************

View File

@ -1,10 +1,10 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="ITokenProvider.cs"> // <copyright file="ITokenProvider.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Contracts
{ {
/// <summary> /// <summary>
/// Interface for token provider. /// Interface for token provider.

View File

@ -1,13 +1,13 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="ITokenService.cs"> // <copyright file="ITokenService.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Contracts
{ {
/// <summary> /// <summary>
/// Interface for authenticacion service. /// Interface for authenticacion service.
@ -17,7 +17,7 @@ namespace Core.Thalos.BuildingBlocks
/// <summary> /// <summary>
/// Refreshes the access token. /// Refreshes the access token.
/// </summary> /// </summary>
(string, IEnumerable<ModuleAdapter>) GenerateAccessToken(TokenAdapter adapter); string GenerateAccessToken(TokenAdapter adapter);
/// <summary> /// <summary>
/// Refreshes the access token. /// Refreshes the access token.

View File

@ -8,35 +8,23 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<VersionPrefix>1.0.5</VersionPrefix>
<VersionSuffix>$(Date:yyyyMMddHHmm)</VersionSuffix>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" /> <PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageReference Include="Core.Blueprint.KeyVault" Version="1.0.3" />
<PackageReference Include="Core.Blueprint.Mongo" Version="1.0.0" />
<PackageReference Include="Google.Apis.Auth" Version="1.70.0" />
<PackageReference Include="Google.Apis.Oauth2.v2" Version="1.68.0.1869" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="8.0.18" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="8.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.7" /> <PackageReference Include="Microsoft.Identity.Web" Version="3.2.2" />
<PackageReference Include="Microsoft.Identity.Web" Version="3.9.1" /> <PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="3.2.2" />
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="3.9.1" /> <PackageReference Include="MongoDB.Bson" Version="3.0.0" />
<PackageReference Include="MongoDB.Bson" Version="3.4.0" /> <PackageReference Include="OpenTelemetry" Version="1.9.0" />
<PackageReference Include="OpenTelemetry" Version="1.12.0" /> <PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.12.0" /> <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" /> <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" /> <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" /> <PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.9.0" />
<PackageReference Include="System.Text.Json" Version="9.0.5" /> <PackageReference Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>
<ItemGroup>
<Folder Include="Handlers\Adapters\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,10 +1,14 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="AuthExtension.cs"> // <copyright file="AuthExtension.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using Microsoft.AspNetCore.Authentication; using Core.Cerberos.Adapters.Common.Constants;
using Core.Cerberos.Adapters.Contracts;
using Core.Cerberos.Adapters.Handlers;
using Core.Cerberos.Adapters.Options;
using Core.Cerberos.Adapters.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
@ -13,7 +17,7 @@ using Microsoft.Identity.Web;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography; using System.Security.Cryptography;
namespace Core.Thalos.BuildingBlocks.Configuration namespace Core.Cerberos.Adapters.Extensions
{ {
/// <summary> /// <summary>
/// Extension methods for configuring authentication with various Azure AD setups. /// Extension methods for configuring authentication with various Azure AD setups.
@ -29,44 +33,42 @@ namespace Core.Thalos.BuildingBlocks.Configuration
{ {
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty;
var identityProviders = new IdentityProviders(); var azureAdInMemorySettings = new Dictionary<string, string?>
configuration.GetSection("IdentityProviders").Bind(identityProviders); {
{ "AzureAdB2C:Instance", authSettings.AzureADInstance ?? string.Empty },
{ "AzureAdB2C:TenantId", authSettings.AzureADTenantId ?? string.Empty },
{ "AzureAdB2C:ClientId", authSettings.AzureADClientId ?? string.Empty },
{ "AzureAdB2C:ClientSecret", authSettings.AzureADClientSecret ?? string.Empty }
};
AddCustomAuthentication(services, authSettings.Token); var configurationBuilder = new ConfigurationBuilder()
.AddConfiguration(configuration)
.AddInMemoryCollection(azureAdInMemorySettings);
if (identityProviders.Azure) var combinedConfiguration = configurationBuilder.Build();
AddAzureAuthentication(authSettings, configuration, services);
if (identityProviders.Google) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
AddGoogleAuthentication(services, authSettings.Google); .AddMicrosoftIdentityWebApi(combinedConfiguration.GetSection("AzureAdB2C"), Schemes.AzureScheme)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(configuration.GetSection("MicrosoftGraph"))
.AddInMemoryTokenCaches();
services.AddAuthorization();
services.AddTransient<IAuthorizationHandler, PermissionsAuthorizationHandler>();
services.AddTransient<ITokenService, TokenService>();
}
public static void AddCustomAuthentication(IServiceCollection services, TokenAuthSettings tokenAuthSettings)
{
var rsa = RSA.Create(); var rsa = RSA.Create();
rsa.ImportFromPem(tokenAuthSettings.PrivateKey?.ToCharArray()); rsa.ImportFromPem(authSettings.PrivateKey?.ToCharArray());
var rsaPrivateKey = new RsaSecurityKey(rsa); var rsaPrivateKey = new RsaSecurityKey(rsa);
var rsaPublic = RSA.Create(); var rsaPublic = RSA.Create();
rsaPublic.ImportFromPem(tokenAuthSettings.PublicKey?.ToCharArray()); rsaPublic.ImportFromPem(authSettings.PublicKey?.ToCharArray());
var rsaPublicKey = new RsaSecurityKey(rsaPublic); var rsaPublicKey = new RsaSecurityKey(rsaPublic);
var jwtAppSettingOptions = configuration.GetSection("B2C:JwtIssuerOptions");
var jwtIssuerOptions = new JwtIssuerOptions var jwtIssuerOptions = jwtAppSettingOptions.Get<JwtIssuerOptions>();
{
Audience = tokenAuthSettings.Audience,
Issuer = tokenAuthSettings.Issuer,
};
if (string.IsNullOrEmpty(jwtIssuerOptions?.Issuer) || string.IsNullOrEmpty(jwtIssuerOptions.Audience)) if (string.IsNullOrEmpty(jwtIssuerOptions?.Issuer) || string.IsNullOrEmpty(jwtIssuerOptions.Audience))
throw new InvalidOperationException("JwtIssuerOptions are not configured correctly."); throw new InvalidOperationException("JwtIssuerOptions are not configured correctly.");
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(Schemes.DefaultScheme, x => .AddJwtBearer(Schemes.HeathScheme, x =>
{ {
x.TokenValidationParameters = new TokenValidationParameters x.TokenValidationParameters = new TokenValidationParameters
{ {
@ -86,52 +88,10 @@ namespace Core.Thalos.BuildingBlocks.Configuration
options.Audience = jwtIssuerOptions?.Audience; options.Audience = jwtIssuerOptions?.Audience;
options.SigningCredentials = new SigningCredentials(rsaPrivateKey, SecurityAlgorithms.RsaSha256); options.SigningCredentials = new SigningCredentials(rsaPrivateKey, SecurityAlgorithms.RsaSha256);
}); });
}
public static void AddAzureAuthentication(AuthSettings authSettings, IConfiguration configuration, IServiceCollection services) services.AddSingleton(jwtAppSettingOptions);
{ services.AddTransient<IAuthorizationHandler, PermissionsAuthorizationHandler>();
var azureAdInMemorySettings = new Dictionary<string, string?> services.AddTransient<ITokenService, TokenService>();
{
{ "AzureAdB2C:Instance", authSettings.Azure.Instance ?? string.Empty },
{ "AzureAdB2C:TenantId", authSettings.Azure.TenantId ?? string.Empty },
{ "AzureAdB2C:ClientId", authSettings.Azure.ClientId ?? string.Empty },
{ "AzureAdB2C:ClientSecret", authSettings.Azure.ClientSecret ?? string.Empty }
};
var configurationBuilder = new ConfigurationBuilder()
.AddConfiguration(configuration)
.AddInMemoryCollection(azureAdInMemorySettings);
var combinedConfiguration = configurationBuilder.Build();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(combinedConfiguration.GetSection("AzureAdB2C"), Schemes.AzureScheme)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(configuration.GetSection("MicrosoftGraph"))
.AddInMemoryTokenCaches();
}
public static void AddGoogleAuthentication(IServiceCollection services, GoogleAuthSettings googleAuthSettings)
{
services.AddSingleton<GoogleAuthSettings>(googleAuthSettings);
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = Schemes.GoogleScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddScheme<AuthenticationSchemeOptions,
GoogleAccessTokenAuthenticationHandler>(Schemes.GoogleScheme, null)
.AddGoogle(options =>
{
options.ClientId = googleAuthSettings.ClientId!;
options.ClientSecret = googleAuthSettings.ClientSecret!;
//options.SaveTokens = true;
options.CallbackPath = $"/{googleAuthSettings.RedirectUri}";
});
services.AddScoped<IGoogleAuthHelper, GoogleAuthHelper>();
services.AddScoped<IGoogleAuthorization, GoogleAuthorization>();
} }
} }
} }

View File

@ -1,21 +1,22 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="SwaggerExtensions.cs"> // <copyright file="SwaggerExtensions.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using Asp.Versioning.ApiExplorer; using Asp.Versioning.ApiExplorer;
using Core.Cerberos.Adapters.Common.Constants;
using Core.Cerberos.Adapters.Extensions;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI; using Swashbuckle.AspNetCore.SwaggerUI;
namespace Core.Thalos.BuildingBlocks.Configuration namespace Core.Cerberos.Adapters.Extensions
{ {
/// <summary> /// <summary>
/// Extension methods for configuring Swagger documentation and UI. /// Extension methods for configuring Swagger documentation and UI.
@ -39,121 +40,71 @@ namespace Core.Thalos.BuildingBlocks.Configuration
/// </summary> /// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param> /// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
/// <param name="configuration">The <see cref="IConfiguration"/> containing Swagger and OAuth2 configuration settings.</param> /// <param name="configuration">The <see cref="IConfiguration"/> containing Swagger and OAuth2 configuration settings.</param>
public static void AddSwaggerGen( public static void AddSwaggerGen(this IServiceCollection services, IConfiguration configuration, string DocumentationFile, AuthSettings authSettings)
this IServiceCollection services,
IConfiguration configuration,
string documentationFile,
AuthSettings authSettings)
{ {
var identityProviders = new IdentityProviders();
configuration.GetSection("IdentityProviders").Bind(identityProviders);
services.AddSwaggerGen(c => services.AddSwaggerGen(c =>
{
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{ {
Description = "JWT Authorization header using the Bearer scheme", c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{ {
Type = ReferenceType.SecurityScheme, Description = "OAuth2.0 Authorization Code flow",
Id = "Bearer" Name = "oauth2.0",
}
},
Array.Empty<string>()
}
});
if (identityProviders.Azure)
{
const string azureScheme = "oauth2-Azure";
c.AddSecurityDefinition(azureScheme, new OpenApiSecurityScheme
{
Description = "Azure OAuth2 Authorization Code flow",
Type = SecuritySchemeType.OAuth2, Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows Flows = new OpenApiOAuthFlows
{ {
AuthorizationCode = new OpenApiOAuthFlow AuthorizationCode = new OpenApiOAuthFlow
{ {
AuthorizationUrl = new Uri(authSettings.Azure?.ThalosAppAuthorizationUrl ?? AuthorizationUrl = new Uri(authSettings.HeathCerberosAppAuthorizationUrl ?? string.Empty),
"https://login.microsoftonline.com/common/oauth2/v2.0/authorize"), TokenUrl = new Uri(authSettings.HeathCerberosAppTokenUrl ?? string.Empty),
TokenUrl = new Uri(authSettings.Azure?.ThalosAppTokenUrl ??
"https://login.microsoftonline.com/common/oauth2/v2.0/token"),
Scopes = new Dictionary<string, string> Scopes = new Dictionary<string, string>
{ {
{ authSettings.Azure?.ThalosAppScope ?? "access_as_user", "Access API as User" } { authSettings.HeathCerberosAppScope ?? string.Empty, "Access API as User" }
} }
} }
} }
}); });
c.AddSecurityRequirement(new OpenApiSecurityRequirement c.AddSecurityRequirement(new OpenApiSecurityRequirement
{ {
[new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = azureScheme }
}] = new[] { authSettings.Azure?.ThalosAppScope ?? "access_as_user" }
});
}
if (identityProviders.Google)
{
const string googleScheme = "oauth2-Google";
c.AddSecurityDefinition(googleScheme, new OpenApiSecurityScheme
{ {
Type = SecuritySchemeType.OAuth2, new OpenApiSecurityScheme
Extensions = new Dictionary<string, IOpenApiExtension>
{ {
["x-tokenName"] = new OpenApiString("id_token") Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
}, },
new[] { authSettings.HeathCerberosAppScope }
}
});
Flows = new OpenApiOAuthFlows c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{ {
AuthorizationCode = new OpenApiOAuthFlow Description = "JWT Authorization header using the Bearer scheme",
{ Name = "Authorization",
AuthorizationUrl = new Uri("https://accounts.google.com/o/oauth2/v2/auth"), In = ParameterLocation.Header,
TokenUrl = new Uri("https://oauth2.googleapis.com/token"), Type = SecuritySchemeType.Http,
Scopes = new Dictionary<string, string> Scheme = "bearer",
{ BearerFormat = "JWT"
{ "openid", "OpenID Connect" },
{ "email", "Access email" },
{ "profile", "Access profile" }
}
}
}
}); });
c.AddSecurityRequirement(new OpenApiSecurityRequirement c.AddSecurityRequirement(new OpenApiSecurityRequirement
{ {
[new OpenApiSecurityScheme {
new OpenApiSecurityScheme
{ {
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = googleScheme } Reference = new OpenApiReference
}] = new[] { "openid", "email", "profile" } {
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
}); });
}
// ✅ XML Comments var filePath = Path.Combine(AppContext.BaseDirectory, DocumentationFile);
var filePath = Path.Combine(AppContext.BaseDirectory, documentationFile); c.IncludeXmlComments(filePath);
c.IncludeXmlComments(filePath); c.SchemaFilter<EnumSchemaFilter>();
c.SchemaFilter<EnumSchemaFilter>(); });
});
} }
/// <summary> /// <summary>
/// Configures Swagger and Swagger UI for the application. /// Configures Swagger and Swagger UI for the application.
/// </summary> /// </summary>
@ -178,36 +129,15 @@ namespace Core.Thalos.BuildingBlocks.Configuration
/// </summary> /// </summary>
/// <param name="app">The <see cref="WebApplication"/> instance.</param> /// <param name="app">The <see cref="WebApplication"/> instance.</param>
/// <param name="configuration">The <see cref="IConfiguration"/> containing Swagger UI and OAuth2 configuration settings.</param> /// <param name="configuration">The <see cref="IConfiguration"/> containing Swagger UI and OAuth2 configuration settings.</param>
public static void UseSwaggerUI( public static void UseSwaggerUI(this WebApplication app, IConfiguration configuration, AuthSettings authSettings)
this WebApplication app,
IConfiguration configuration,
AuthSettings authSettings)
{ {
var identityProviders = new IdentityProviders(); app.UseSwaggerUI(options =>
configuration.GetSection("IdentityProviders").Bind(identityProviders);
app.UseSwagger();
if (identityProviders.Google)
{ {
app.UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/v1/swagger.json", "Custom Auth API with Azure AD v1");
{ options.OAuthClientId(authSettings.HeathCerberosAppClientId);
options.OAuthUsePkce(); options.OAuthUsePkce();
options.OAuthScopeSeparator(" "); options.OAuthScopeSeparator(" ");
options.OAuthClientId(authSettings.Google?.ClientId); });
options.OAuthClientSecret(authSettings.Google?.ClientSecret);
});
}
if (identityProviders.Azure)
{
app.UseSwaggerUI(options =>
{
options.OAuthUsePkce();
options.OAuthScopeSeparator(" ");
options.OAuthClientId(authSettings.Azure?.ThalosAppClientId);
});
}
} }
/// <summary> /// <summary>

View File

@ -4,15 +4,15 @@ using OpenTelemetry.Metrics;
using OpenTelemetry.Resources; using OpenTelemetry.Resources;
using OpenTelemetry.Trace; using OpenTelemetry.Trace;
namespace Core.Thalos.BuildingBlocks.Configuration namespace Core.Cerberos.Adapters.Extensions
{ {
public static class TelemetryExtensions public static class TelemetryExtensions
{ {
public static void AddTelemetry(this IServiceCollection services, string apiName) public static void AddTelemetry(this IServiceCollection services)
{ {
// Add OpenTelemetry Tracing // Add OpenTelemetry Tracing
services.AddOpenTelemetry() services.AddOpenTelemetry()
.ConfigureResource(resource => resource.AddService($"{apiName}")) .ConfigureResource(resource => resource.AddService("lsa.dashboard.bff.api"))
.WithTracing(tracing => tracing.AddAspNetCoreInstrumentation().AddConsoleExporter()) .WithTracing(tracing => tracing.AddAspNetCoreInstrumentation().AddConsoleExporter())
.WithMetrics(metrics => metrics.AddAspNetCoreInstrumentation().AddConsoleExporter()). .WithMetrics(metrics => metrics.AddAspNetCoreInstrumentation().AddConsoleExporter()).
WithLogging(logs => logs.AddConsoleExporter()); WithLogging(logs => logs.AddConsoleExporter());

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace Core.Thalos.BuildingBlocks.Extensions namespace Core.Cerberos.Adapters.Extensions
{ {
public sealed class TrackingMechanismExtension : DelegatingHandler public sealed class TrackingMechanismExtension : DelegatingHandler
{ {

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Handlers.Adapters
{ {
public class PermissionsAuthorizationAdapter : IAuthorizationRequirement public class PermissionsAuthorizationAdapter : IAuthorizationRequirement
{ {

View File

@ -1,11 +1,12 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="AuthenticatedHttpClientHandler.cs"> // <copyright file="AuthenticatedHttpClientHandler.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using Core.Cerberos.Adapters.Contracts;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Handlers
{ {
/// <summary> /// <summary>
/// Class to inject the token in all requests. /// Class to inject the token in all requests.

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Authorization; using Core.Cerberos.Adapters.Handlers.Adapters;
using Microsoft.AspNetCore.Authorization;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Handlers
{ {
public class PermissionsAuthorizationHandler : AuthorizationHandler<PermissionsAuthorizationAdapter> public class PermissionsAuthorizationHandler : AuthorizationHandler<PermissionsAuthorizationAdapter>
{ {

View File

@ -0,0 +1,52 @@
using Azure.Identity;
using Core.Cerberos.Adapters.Common.Constants;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
using Microsoft.Extensions.Logging;
namespace Core.Cerberos.Adapters.Helpers
{
public static class AuthHelper
{
private static readonly ILogger logger = LoggerFactory.Create(builder =>
{
builder.AddConsole();
}).CreateLogger("AuthHelper");
public static AuthSettings GetAuthSettings(WebApplicationBuilder builder, string appConfigLabel)
{
builder.Configuration.AddAzureAppConfiguration(options =>
{
var endpoint = builder.Configuration.GetSection("Endpoints:AppConfigurationURI").Value;
if (string.IsNullOrEmpty(endpoint))
throw new ArgumentException("The app configuration is missing");
options.Connect(new Uri(endpoint), new DefaultAzureCredential())
.Select(KeyFilter.Any, "cerberos_common")
.Select(KeyFilter.Any, appConfigLabel);
options.ConfigureKeyVault(keyVaultOptions =>
{
keyVaultOptions.SetCredential(new DefaultAzureCredential());
});
});
return new AuthSettings
{
AzureADInstance = builder.Configuration.GetSection(Secrets.AzureADInstance).Value,
AzureADTenantId = builder.Configuration.GetSection(Secrets.AzureADTenantId).Value,
AzureADClientId = builder.Configuration.GetSection(Secrets.AzureADClientId).Value,
AzureADClientSecret = builder.Configuration.GetSection(Secrets.AzureADClientSecret).Value,
HeathCerberosAppAuthorizationUrl = builder.Configuration.GetSection(Secrets.HeathCerberosAppAuthorizationUrl).Value,
HeathCerberosAppTokenUrl = builder.Configuration.GetSection(Secrets.HeathCerberosAppTokenUrl).Value,
HeathCerberosAppClientId = builder.Configuration.GetSection(Secrets.HeathCerberosAppClientId).Value,
HeathCerberosAppScope = builder.Configuration.GetSection(Secrets.HeathCerberosAppScope).Value,
PrivateKey = builder.Configuration.GetSection(Secrets.PrivateKey).Value,
PublicKey = builder.Configuration.GetSection(Secrets.PublicKey).Value,
};
}
}
}

View File

@ -1,6 +1,6 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="RsaHelper.cs"> // <copyright file="RsaHelper.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto;
@ -10,7 +10,7 @@ using Org.BouncyCastle.Security;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Helpers
{ {
/// <summary> /// <summary>
/// Handles all methods related to RSA encryption"/>. /// Handles all methods related to RSA encryption"/>.
@ -62,7 +62,7 @@ namespace Core.Thalos.BuildingBlocks
/// <returns>The private key.</returns> /// <returns>The private key.</returns>
private RSACryptoServiceProvider GetPrivateKeyFromPemFile() private RSACryptoServiceProvider GetPrivateKeyFromPemFile()
{ {
using (TextReader privateKeyTextReader = new StringReader(File.ReadAllText(Path.Combine(exeDirectory, "PrivateKey.pem")))) using (TextReader privateKeyTextReader = new StringReader(File.ReadAllText(Path.Combine(exeDirectory, "HeathPrivateKey.pem"))))
{ {
AsymmetricCipherKeyPair readKeyPair = (AsymmetricCipherKeyPair)new PemReader(privateKeyTextReader).ReadObject(); AsymmetricCipherKeyPair readKeyPair = (AsymmetricCipherKeyPair)new PemReader(privateKeyTextReader).ReadObject();
@ -79,7 +79,7 @@ namespace Core.Thalos.BuildingBlocks
/// <returns>The public key.</returns> /// <returns>The public key.</returns>
public RSACryptoServiceProvider GetPublicKeyFromPemFile() public RSACryptoServiceProvider GetPublicKeyFromPemFile()
{ {
using (TextReader publicKeyTextReader = new StringReader(File.ReadAllText(Path.Combine(exeDirectory, "PublicKey.pem")))) using (TextReader publicKeyTextReader = new StringReader(File.ReadAllText(Path.Combine(exeDirectory, "HeathPublicKey.pem"))))
{ {
RsaKeyParameters publicKeyParam = (RsaKeyParameters)new PemReader(publicKeyTextReader).ReadObject(); RsaKeyParameters publicKeyParam = (RsaKeyParameters)new PemReader(publicKeyTextReader).ReadObject();

View File

@ -1,6 +1,6 @@
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Options
{ {
/// <summary> /// <summary>
/// JWT token Issuer options (used for JWT Factory) /// JWT token Issuer options (used for JWT Factory)

View File

@ -1,8 +1,11 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="TokenService.cs"> // <copyright file="T5okenService.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using Core.Cerberos.Adapters.Common.Constants;
using Core.Cerberos.Adapters.Contracts;
using Core.Cerberos.Adapters.Options;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
@ -13,7 +16,7 @@ using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims; using System.Security.Claims;
using System.Text.Json; using System.Text.Json;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.Services
{ {
/// <summary> /// <summary>
/// Service responsible for manage authenticacion. /// Service responsible for manage authenticacion.
@ -71,7 +74,7 @@ namespace Core.Thalos.BuildingBlocks
/// </summary> /// </summary>
/// <param name="user">The user data.</param> /// <param name="user">The user data.</param>
/// <returns>The user DTO with the generated token.</returns> /// <returns>The user DTO with the generated token.</returns>
public (string, IEnumerable<ModuleAdapter>) GenerateAccessToken(TokenAdapter adapter) public string GenerateAccessToken(TokenAdapter adapter)
{ {
@ -87,13 +90,14 @@ namespace Core.Thalos.BuildingBlocks
{ {
new Claim(Claims.Name, adapter?.User?.DisplayName ?? string.Empty), new Claim(Claims.Name, adapter?.User?.DisplayName ?? string.Empty),
new Claim(Claims.Id, adapter?.User?.Id ?? string.Empty), new Claim(Claims.GUID, adapter?.User?.Guid ?? string.Empty),
new Claim(Claims.Email, adapter?.User?.Email ?? string.Empty), new Claim(Claims.Email, adapter?.User?.Email ?? string.Empty),
new Claim(Claims.Tenant, adapter?.Tenant?.Name ?? string.Empty),
new Claim(Claims.Tenant, adapter?.Tenant?.Id ?? string.Empty),
new Claim(Claims.Role, adapter?.Role?.Name ?? string.Empty), new Claim(Claims.Role, adapter?.Role?.Name ?? string.Empty),
new Claim(Claims.RoleId, adapter?.Role?.Id ?? string.Empty), new Claim(Claims.RoleId, adapter?.Role?.Id ?? string.Empty),
new Claim(Claims.Applications, JsonSerializer.Serialize(adapter?.Role?.Applications), JsonClaimValueTypes.JsonArray), new Claim(Claims.Applications, JsonSerializer.Serialize(adapter?.Role?.Applications), JsonClaimValueTypes.JsonArray),
new Claim(Claims.Modules, JsonSerializer.Serialize(adapter?.Modules?.Select(m => new { m.Name, m.Application, m.Route, m.Icon, m.Order }), jsonOptions), JsonClaimValueTypes.JsonArray),
new Claim(Claims.Companies, JsonSerializer.Serialize(adapter?.User?.Companies), JsonClaimValueTypes.JsonArray),
new Claim(Claims.Projects, JsonSerializer.Serialize(adapter?.User?.Projects), JsonClaimValueTypes.JsonArray),
new Claim(Claims.Permissions, JsonSerializer.Serialize(adapter?.Permissions?.Select(p => $"{p.Name}.{p.AccessLevel}".Replace(" ", "")).ToArray()), JsonClaimValueTypes.JsonArray), new Claim(Claims.Permissions, JsonSerializer.Serialize(adapter?.Permissions?.Select(p => $"{p.Name}.{p.AccessLevel}".Replace(" ", "")).ToArray()), JsonClaimValueTypes.JsonArray),
}), }),
@ -105,7 +109,7 @@ namespace Core.Thalos.BuildingBlocks
var token = tokenHandler.CreateEncodedJwt(tokenDescriptor); var token = tokenHandler.CreateEncodedJwt(tokenDescriptor);
return (token, adapter.Modules); return token;
} }
public ActionResult<TimeSpan> ValidateTokenExpiration(string tokenExpiration) public ActionResult<TimeSpan> ValidateTokenExpiration(string tokenExpiration)

View File

@ -0,0 +1,25 @@
// ***********************************************************************
// <copyright file="AuthSettings.cs">
// Heath
// </copyright>
// ***********************************************************************
public class AuthSettings
{
// Azure AD Settings
public string? AzureADInstance { get; set; }
public string? AzureADTenantId { get; set; }
public string? AzureADClientId { get; set; }
public string? AzureADClientSecret { get; set; }
// Heath Cerberos App Settings
public string? HeathCerberosAppAuthorizationUrl { get; set; }
public string? HeathCerberosAppTokenUrl { get; set; }
public string? HeathCerberosAppClientId { get; set; }
public string? HeathCerberosAppScope { get; set; }
// Token Keys
public string? PrivateKey { get; set; }
public string? PublicKey { get; set; }
}

View File

@ -1,12 +1,13 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="HttpContextTokenProvider.cs"> // <copyright file="HttpContextTokenProvider.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using Core.Cerberos.Adapters.Contracts;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters.TokenProvider
{ {
/// <summary> /// <summary>
/// Class to return the access token to controllers. /// Class to return the access token to controllers.

View File

@ -1,12 +1,12 @@
// *********************************************************************** // ***********************************************************************
// <copyright file="UserExistenceAdapter.cs"> // <copyright file="UserExistenceAdapter.cs">
// AgileWebs // Heath
// </copyright> // </copyright>
// *********************************************************************** // ***********************************************************************
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks namespace Core.Cerberos.Adapters
{ {
/// <summary> /// <summary>
/// Adapter representing a user. /// Adapter representing a user.

View File

@ -1,32 +0,0 @@
using Core.Blueprint.Mongo;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace Core.Thalos.BuildingBlocks.Adapters
{
[CollectionAttributeName("Catalogs")]
public class CatalogAdapter : Document
{
[BsonElement("name")]
public string Name { get; set; } = null!;
[BsonElement("key")]
public string? Key { get; set; } = null!;
[BsonElement("description")]
public string? Description { get; set; }
public IEnumerable<CatalogValue>? Values { get; set; }
}
public class CatalogValue
{
[BsonId]
[BsonElement("_id")]
[BsonRepresentation(BsonType.ObjectId)]
public string _Id { get; set; } = null!;
[BsonElement("value")]
public string Value { get; set; } = null!;
}
}

View File

@ -1,45 +0,0 @@
// ***********************************************************************
// <copyright file="PermissionAdapter.cs">
// AgileWebs
// </copyright>
// ***********************************************************************
using Core.Blueprint.Mongo;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks
{
/// <summary>
/// Adapter for representing a permission.
/// </summary>
[CollectionAttributeName("Permissions")]
public class PermissionAdapter : Document
{
/// <summary>
/// Gets or sets the name of the entity.
/// </summary>
[BsonElement("name")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("name")]
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the description of the entity.
/// </summary>
[BsonElement("description")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("description")]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the status of the entity object.
/// </summary>
[BsonElement("accessLevel")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("accessLevel")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public AccessLevelEnum? AccessLevel { get; set; } = null!;
}
}

View File

@ -1,58 +0,0 @@
// ***********************************************************************
// <copyright file="RoleAdapter.cs">
// AgileWebs
// </copyright>
// ***********************************************************************
using Core.Blueprint.Mongo;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks
{
/// <summary>
/// Adapter representing a role.
/// </summary>
[CollectionAttributeName("Roles")]
public class RoleAdapter : Document
{
/// <summary>
/// Gets or sets the name of the role.
/// </summary>
[BsonElement("name")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("name")]
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the description of the role.
/// </summary>
[BsonElement("description")]
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("description")]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the status of the entity.
/// </summary>
[BsonElement("applications")]
[JsonPropertyName("applications")]
[JsonConverter(typeof(EnumArrayJsonConverter<ApplicationsEnum>))]
public ApplicationsEnum[]? Applications { get; set; }
/// <summary>
/// Gets or sets the modules of the role.
/// </summary>
[BsonElement("modules")]
[JsonPropertyName("modules")]
public string[] Modules { get; set; } = null!;
/// <summary>
/// Gets or sets the permissions of the role.
/// </summary>
[BsonElement("permissions")]
[JsonPropertyName("permissions")]
public string[] Permissions { get; set; } = null!;
}
}

View File

@ -1,53 +0,0 @@
using Core.Blueprint.Mongo;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace Core.Thalos.BuildingBlocks
{
[CollectionAttributeName("Tenants")]
public class TenantAdapter : Document
{
[BsonElement("name")]
public string Name { get; set; } = null!;
[BsonElement("taxIdentifier")]
public string TaxIdentifier { get; set; } = null!;
[BsonElement("addressLine1")]
public string AddressLine1 { get; set; } = null!;
[BsonElement("addressLine2")]
[BsonIgnoreIfNull]
public string? AddressLine2 { get; set; }
[BsonElement("city")]
public string City { get; set; } = null!;
[BsonElement("state")]
public string State { get; set; } = null!;
[BsonElement("country")]
public string Country { get; set; } = null!;
[BsonElement("postalCode")]
public string PostalCode { get; set; } = null!;
[BsonElement("contactEmail")]
public string ContactEmail { get; set; } = null!;
[BsonElement("contactPhone")]
public string ContactPhone { get; set; } = null!;
[BsonElement("website")]
[BsonIgnoreIfNull]
public string? Website { get; set; }
[BsonElement("connectionString")]
[BsonIgnoreIfNull]
public string? ConnectionString { get; set; }
[BsonElement("isolated")]
public bool Isolated { get; set; }
}
}

View File

@ -1,37 +0,0 @@
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Microsoft.Extensions.Configuration;
namespace Core.Thalos.BuildingBlocks
{
public class GoogleAuthorization(
IGoogleAuthHelper googleHelper, IConfiguration config, GoogleAuthSettings googlesettings) : IGoogleAuthorization
{
private string RedirectUrl = googlesettings.RedirectUri ?? string.Empty;
public async Task<UserCredential> ExchangeCodeForToken(string code)
{
var flow = new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = googleHelper.GetClientSecrets(),
Scopes = googleHelper.GetScopes()
});
var token = await flow.ExchangeCodeForTokenAsync(
"user", code, RedirectUrl, CancellationToken.None);
return new UserCredential(flow, "user", token);
}
public string GetAuthorizationUrl() =>
new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = googleHelper.GetClientSecrets(),
Scopes = googleHelper.GetScopes(),
Prompt = "consent"
}).CreateAuthorizationCodeRequest(RedirectUrl).Build().ToString();
}
}

View File

@ -1,10 +0,0 @@
using Google.Apis.Auth.OAuth2;
namespace Core.Thalos.BuildingBlocks
{
public interface IGoogleAuthorization
{
string GetAuthorizationUrl();
Task<UserCredential> ExchangeCodeForToken(string code);
}
}

View File

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
namespace Core.Thalos.BuildingBlocks
{
/// <summary>
/// Constants for policy.
/// </summary>
public class Policies
{
/// <summary>
/// Defines the access policy for reading mobile-related data.
/// This policy grants read-only permissions for retrieving mobile device information,
/// user mobile settings, or related data as per the application's authorization scope.
/// </summary>
public const string Read = "Read";
/// <summary>
/// Defines the access policy for writing mobile-related data.
/// This policy grants permissions to modify, update, or store mobile device information,
/// user mobile settings, or related data as per the application's authorization scope.
/// </summary>
public const string Write = "Write";
}
}

View File

@ -1,15 +0,0 @@
namespace Core.Thalos.BuildingBlocks
{
public class Roles
{
/// <summary>
/// The role for Guest.
/// </summary>
public const string Guest = "684909c4826cd093b4f61c11";
/// <summary>
/// The role for Admin.
/// </summary>
public const string Admin = "68407642ec46a0e6fe1e8ec9";
}
}

View File

@ -1,11 +0,0 @@
using Google.Apis.Auth.OAuth2;
namespace Core.Thalos.BuildingBlocks
{
public interface IGoogleAuthHelper
{
string[] GetScopes();
string ScopeToString();
ClientSecrets GetClientSecrets();
}
}

View File

@ -1,65 +0,0 @@
using Google.Apis.Auth;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using System.Text.Encodings.Web;
namespace Core.Thalos.BuildingBlocks
{
public class GoogleAccessTokenAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
IConfiguration config,
GoogleAuthSettings googleSettings
) : AuthenticationHandler<AuthenticationSchemeOptions>(options, logger, encoder)
{
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.ContainsKey("Authorization"))
return AuthenticateResult.Fail("Missing Authorization header");
var authHeader = Request.Headers.Authorization.ToString();
if (!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
return AuthenticateResult.Fail("Invalid Authorization header");
var idToken = authHeader["Bearer ".Length..].Trim();
GoogleJsonWebSignature.Payload payload;
try
{
payload = await GoogleJsonWebSignature.ValidateAsync(
idToken,
new GoogleJsonWebSignature.ValidationSettings
{
Audience = new[] { googleSettings.ClientId! }
});
}
catch (InvalidJwtException)
{
return AuthenticateResult.Fail("Invalid Google token");
}
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, payload.Subject),
new Claim(ClaimTypes.Email, payload.Email),
new Claim(ClaimTypes.Name, payload.Name ?? "")
};
var identity = new ClaimsIdentity(claims, Schemes.GoogleScheme);
var principal = new ClaimsPrincipal(identity);
var userEmail = principal.FindFirst(ClaimTypes.Email)?.Value;
if (string.IsNullOrEmpty(userEmail) ||
!userEmail.EndsWith("@agilewebs.com", StringComparison.OrdinalIgnoreCase))
return AuthenticateResult.Fail("Unauthorized Access");
var ticket = new AuthenticationTicket(principal, Schemes.GoogleScheme);
return AuthenticateResult.Success(ticket);
}
}
}

View File

@ -1,128 +0,0 @@
using Azure.Identity;
using Core.Blueprint.KeyVault;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Core.Thalos.BuildingBlocks
{
public static class AuthHelper
{
private static readonly ILogger logger = LoggerFactory.Create(builder =>
{
builder.AddConsole();
}).CreateLogger("AuthHelper");
public static async Task<AuthSettings> GetAuthSettings(this IServiceCollection services, WebApplicationBuilder builder, string appConfigLabel)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty;
var authSettings = new AuthSettings();
var identityProviders = new IdentityProviders();
builder.Configuration.GetSection("IdentityProviders").Bind(identityProviders);
using var serviceProvider = services.BuildServiceProvider();
var keyVaultProvider = serviceProvider.GetRequiredService<IKeyVaultProvider>();
if (environment != "Local")
{
builder.Configuration.AddAzureAppConfiguration(options =>
{
var endpoint = builder.Configuration.GetSection("Endpoints:AppConfigurationURI").Value;
if (string.IsNullOrEmpty(endpoint))
throw new ArgumentException("The app configuration is missing");
options.Connect(new Uri(endpoint), new DefaultAzureCredential())
.Select(KeyFilter.Any, "thalos_common")
.Select(KeyFilter.Any, appConfigLabel);
options.ConfigureKeyVault(keyVaultOptions =>
{
keyVaultOptions.SetCredential(new DefaultAzureCredential());
});
});
}
if (identityProviders.Google)
authSettings.Google = await GetGoogleSettings(keyVaultProvider, builder);
if (identityProviders.Azure)
authSettings.Azure = GetAzureSettings(builder);
authSettings.Token = await GetTokenSettings(keyVaultProvider, builder);
return authSettings;
}
private async static ValueTask<TokenAuthSettings> GetTokenSettings(IKeyVaultProvider keyVaultProvider, WebApplicationBuilder builder)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty;
var tokenSettings = new TokenAuthSettings();
if (environment == "Local")
{
tokenSettings.PublicKey = (await keyVaultProvider.GetSecretAsync(Secrets.PublicKey, new CancellationToken { })).Secret.Value;
tokenSettings.PrivateKey = (await keyVaultProvider.GetSecretAsync(Secrets.PrivateKey, new CancellationToken { })).Secret.Value;
tokenSettings.Issuer = (await keyVaultProvider.GetSecretAsync(Secrets.Issuer, new CancellationToken { })).Secret.Value;
tokenSettings.Audience = (await keyVaultProvider.GetSecretAsync(Secrets.Audience, new CancellationToken { })).Secret.Value;
}
else
{
tokenSettings.PrivateKey = builder.Configuration.GetSection(Secrets.PrivateKey).Value;
tokenSettings.PublicKey = builder.Configuration.GetSection(Secrets.PublicKey).Value;
tokenSettings.Issuer = builder.Configuration.GetSection(Secrets.Issuer).Value;
tokenSettings.Audience = builder.Configuration.GetSection(Secrets.Audience).Value;
}
if (string.IsNullOrEmpty(tokenSettings.PrivateKey) || string.IsNullOrEmpty(tokenSettings.PublicKey))
{
logger.LogError("Settings for token creation are missing or incorrectly formatted.");
throw new InvalidOperationException("Invalid public or private key.");
}
return tokenSettings;
}
private static AzureAuthSettings GetAzureSettings(WebApplicationBuilder builder)
{
return new AzureAuthSettings
{
Instance = builder.Configuration.GetSection(Secrets.AzureADInstance).Value,
TenantId = builder.Configuration.GetSection(Secrets.AzureADTenantId).Value,
ClientId = builder.Configuration.GetSection(Secrets.AzureADClientId).Value,
ClientSecret = builder.Configuration.GetSection(Secrets.AzureADClientSecret).Value,
ThalosAppAuthorizationUrl = builder.Configuration.GetSection(Secrets.ThalosAppAuthorizationUrl).Value,
ThalosAppTokenUrl = builder.Configuration.GetSection(Secrets.ThalosAppTokenUrl).Value,
ThalosAppClientId = builder.Configuration.GetSection(Secrets.ThalosAppClientId).Value,
ThalosAppScope = builder.Configuration.GetSection(Secrets.ThalosAppScope).Value,
};
}
private static async ValueTask<GoogleAuthSettings> GetGoogleSettings(IKeyVaultProvider keyVaultProvider, WebApplicationBuilder builder)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var googleSettings = new GoogleAuthSettings();
if (environment == "Local")
{
googleSettings.ClientId = (await keyVaultProvider.GetSecretAsync(Secrets.GoogleClientId, new CancellationToken { })).Secret.Value; ;
googleSettings.ClientSecret = (await keyVaultProvider.GetSecretAsync(Secrets.GoogleClientSecret, new CancellationToken { })).Secret.Value;
googleSettings.RedirectUri = builder.Configuration.GetSection(Secrets.GoogleLocalRedirectUri).Value;
}
else
{
googleSettings.ClientId = builder.Configuration.GetSection(Secrets.GoogleClientId).Value;
googleSettings.ClientSecret = builder.Configuration.GetSection(Secrets.GoogleClientSecret).Value;
googleSettings.RedirectUri = builder.Configuration.GetSection(Secrets.GoogleRedirectUri).Value;
}
return googleSettings;
}
}
}

View File

@ -1,31 +0,0 @@
using Google.Apis.Auth.OAuth2;
using Google.Apis.Oauth2.v2;
using Microsoft.Extensions.Configuration;
namespace Core.Thalos.BuildingBlocks
{
public class GoogleAuthHelper(IConfiguration config, GoogleAuthSettings googleSettings) : IGoogleAuthHelper
{
public ClientSecrets GetClientSecrets()
{
string clientId = googleSettings.ClientId ?? string.Empty;
string clientSecret = googleSettings.ClientSecret ?? string.Empty;
return new() { ClientId = clientId, ClientSecret = clientSecret };
}
public string[] GetScopes()
{
var scopes = new[]
{
Oauth2Service.Scope.Openid,
Oauth2Service.Scope.UserinfoEmail,
Oauth2Service.Scope.UserinfoProfile
};
return scopes;
}
public string ScopeToString() => string.Join(", ", GetScopes());
}
}

View File

@ -1,42 +0,0 @@
// ***********************************************************************
// <copyright file="AuthSettings.cs">
// AgileWebs
// </copyright>
// ***********************************************************************
namespace Core.Thalos.BuildingBlocks;
public class AuthSettings
{
public AzureAuthSettings? Azure { get; set; }
public TokenAuthSettings Token { get; set; } = null!;
public GoogleAuthSettings? Google { get; set; }
}
public class AzureAuthSettings
{
public string? Instance { get; set; }
public string? TenantId { get; set; }
public string? ClientId { get; set; }
public string? ClientSecret { get; set; }
public string? ThalosAppAuthorizationUrl { get; set; }
public string? ThalosAppTokenUrl { get; set; }
public string? ThalosAppClientId { get; set; }
public string? ThalosAppScope { get; set; }
}
public class GoogleAuthSettings
{
public string? ClientId { get; set; }
public string? ClientSecret { get; set; }
public string? RedirectUri { get; set; }
}
public class TokenAuthSettings
{
public string? PrivateKey { get; set; }
public string? PublicKey { get; set; }
public string? Audience { get; set; }
public string? Issuer { get; set; }
}

View File

@ -1,8 +0,0 @@
namespace Core.Thalos.BuildingBlocks
{
public class IdentityProviders
{
public bool Google { get; set; }
public bool Azure { get; set; }
}
}