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
VisualStudioVersion = 17.10.34928.147
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
Global
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
{

View File

@ -1,22 +1,30 @@
// ***********************************************************************
// <copyright file="ModuleAdapter.cs">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
using Core.Blueprint.Mongo;
using Core.Cerberos.Adapters.Common.Enums;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters
{
/// <summary>
/// Adapter for representing a module.
/// </summary>
[CollectionAttributeName("Modules")]
public class ModuleAdapter : Document
public class ModuleAdapter
{
/// <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>
/// Gets or sets the name of the module.
/// </summary>
@ -65,5 +73,46 @@ namespace Core.Thalos.BuildingBlocks
[JsonPropertyName("application")]
[JsonConverter(typeof(JsonStringEnumConverter))]
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">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters
{
public class TokenAdapter
{
public UserAdapter? User { get; set; }
public RoleAdapter? Role { get; set; }
public TenantAdapter? Tenant { 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">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
using Core.Blueprint.Mongo;
using Core.Cerberos.Adapters.Common.Enums;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters
{
/// <summary>
/// Adapter representing a user.
/// </summary>
[CollectionAttributeName("Users")]
public class UserAdapter : Document
public class UserAdapter : BaseAdapterResponse
{
/// <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>
/// Gets or sets the email address of the user.
/// </summary>
@ -56,14 +72,6 @@ namespace Core.Thalos.BuildingBlocks
[JsonPropertyName("displayName")]
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>
/// Gets or sets the role ID of the user.
/// </summary>
@ -72,6 +80,28 @@ namespace Core.Thalos.BuildingBlocks
[JsonPropertyName("roleId")]
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>
/// Gets or sets the timestamp of the last login of the user.
/// </summary>
@ -96,5 +126,46 @@ namespace Core.Thalos.BuildingBlocks
[BsonRepresentation(BsonType.String)]
[JsonPropertyName("token")]
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
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
using System.Globalization;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.Common.Constants
{
/// <summary>
/// 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">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.Common.Constants
{
/// <summary>
/// Constants of the routes of this service.
@ -24,7 +24,7 @@ namespace Core.Thalos.BuildingBlocks
/// <summary>
/// The identifier route.
/// </summary>
public const string Id = "{_id}";
public const string Id = "{id}";
/// <summary>
/// The Authentication route.
@ -74,7 +74,7 @@ namespace Core.Thalos.BuildingBlocks
/// <summary>
/// The ChangeStatus route.
/// </summary>
public const string ChangeStatus = "{_id}/{newStatus}/ChangeStatus";
public const string ChangeStatus = "{id}/{newStatus}/ChangeStatus";
/// <summary>
/// The AddCompany route.

View File

@ -1,4 +1,4 @@
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.Common.Constants
{
/// <summary>
/// Constants for schemes.
@ -6,18 +6,13 @@
public class Schemes
{
/// <summary>
/// The default scheme.
/// The heath scheme.
/// </summary>
public const string DefaultScheme = "DefaultScheme";
public const string HeathScheme = "HeathScheme";
/// <summary>
/// The azure scheme.
/// </summary>
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">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.Common.Constants
{
/// <summary>
/// Constants for secrets in azure key vault.
@ -23,12 +23,12 @@ namespace Core.Thalos.BuildingBlocks
/// <summary>
/// The Issuer parameter for JWT settings.
/// </summary>
public const string Issuer = "JWTIssuer";
public const string Issuer = "Issuer";
/// <summary>
/// The Audience parameter for JWT settings.
/// </summary>
public const string Audience = "JWTAudience";
public const string Audience = "Audience";
/// <summary>
/// The TokenExpirationInMinutes parameter for JWT settings.
@ -49,15 +49,11 @@ namespace Core.Thalos.BuildingBlocks
public const string AzureADTenantId = "B2C:TenantId";
public const string AzureADClientId = "B2C:ClientId";
public const string AzureADClientSecret = "B2C:ClientSecret";
public const string ThalosAppAuthorizationUrl = "Swagger:AuthorizationUri";
public const string ThalosAppTokenUrl = "Swagger:TokenUri";
public const string ThalosAppClientId = "Swagger:ClientId";
public const string ThalosAppScope = "Swagger:Scope";
public const string PrivateKey = "JwtTokenPrivateKey";
public const string PublicKey = "JwtTokenPublicKey";
public const string GoogleClientId = "GoogleClientId";
public const string GoogleClientSecret = "GoogleClientSecret";
public const string GoogleRedirectUri = "GoogleRedirectUri";
public const string GoogleLocalRedirectUri = "GoogleLocalRedirectUri";
public const string HeathCerberosAppAuthorizationUrl = "Swagger:AuthorizationUri";
public const string HeathCerberosAppTokenUrl = "Swagger:TokenUri";
public const string HeathCerberosAppClientId = "Swagger:ClientId";
public const string HeathCerberosAppScope = "Swagger:Scope";
public const string PrivateKey = "B2C:JwtIssuerOptions:TokenPrivateKey";
public const string PublicKey = "B2C:JwtIssuerOptions:TokenPublicKey";
}
}

View File

@ -1,12 +1,12 @@
// ***********************************************************************
// <copyright file="ApplicationsEnum.cs">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.Common.Enums
{
/// <summary>
/// Defines the applications associated with the role.
@ -15,13 +15,28 @@ namespace Core.Thalos.BuildingBlocks
public enum ApplicationsEnum
{
/// <summary>
/// Thalos application.
/// LSA Web Portal application.
/// </summary>
Thalos = 0,
LSAWebPortal = 0,
/// <summary>
/// DreamViewer application.
/// Customer DashBoard application.
/// </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">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.Common.Enums
{
/// <summary>
/// Defines the status of an entity.

View File

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

View File

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

View File

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

View File

@ -8,35 +8,23 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<VersionPrefix>1.0.5</VersionPrefix>
<VersionSuffix>$(Date:yyyyMMddHHmm)</VersionSuffix>
</PropertyGroup>
<ItemGroup>
<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.Extensions.Configuration.AzureAppConfiguration" Version="8.2.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.7" />
<PackageReference Include="Microsoft.Identity.Web" Version="3.9.1" />
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="3.9.1" />
<PackageReference Include="MongoDB.Bson" Version="3.4.0" />
<PackageReference Include="OpenTelemetry" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="8.0.0" />
<PackageReference Include="Microsoft.Identity.Web" Version="3.2.2" />
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="3.2.2" />
<PackageReference Include="MongoDB.Bson" Version="3.0.0" />
<PackageReference Include="OpenTelemetry" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
<PackageReference Include="System.Text.Json" Version="9.0.5" />
</ItemGroup>
<ItemGroup>
<Folder Include="Handlers\Adapters\" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.9.0" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>
</Project>

View File

@ -1,10 +1,14 @@
// ***********************************************************************
// <copyright file="AuthExtension.cs">
// AgileWebs
// Heath
// </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.Authorization;
using Microsoft.Extensions.Configuration;
@ -13,7 +17,7 @@ using Microsoft.Identity.Web;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;
namespace Core.Thalos.BuildingBlocks.Configuration
namespace Core.Cerberos.Adapters.Extensions
{
/// <summary>
/// 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 identityProviders = new IdentityProviders();
configuration.GetSection("IdentityProviders").Bind(identityProviders);
AddCustomAuthentication(services, authSettings.Token);
if (identityProviders.Azure)
AddAzureAuthentication(authSettings, configuration, services);
if (identityProviders.Google)
AddGoogleAuthentication(services, authSettings.Google);
services.AddAuthorization();
services.AddTransient<IAuthorizationHandler, PermissionsAuthorizationHandler>();
services.AddTransient<ITokenService, TokenService>();
}
public static void AddCustomAuthentication(IServiceCollection services, TokenAuthSettings tokenAuthSettings)
var azureAdInMemorySettings = new Dictionary<string, string?>
{
{ "AzureAdB2C:Instance", authSettings.AzureADInstance ?? string.Empty },
{ "AzureAdB2C:TenantId", authSettings.AzureADTenantId ?? string.Empty },
{ "AzureAdB2C:ClientId", authSettings.AzureADClientId ?? string.Empty },
{ "AzureAdB2C:ClientSecret", authSettings.AzureADClientSecret ?? 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();
var rsa = RSA.Create();
rsa.ImportFromPem(tokenAuthSettings.PrivateKey?.ToCharArray());
rsa.ImportFromPem(authSettings.PrivateKey?.ToCharArray());
var rsaPrivateKey = new RsaSecurityKey(rsa);
var rsaPublic = RSA.Create();
rsaPublic.ImportFromPem(tokenAuthSettings.PublicKey?.ToCharArray());
rsaPublic.ImportFromPem(authSettings.PublicKey?.ToCharArray());
var rsaPublicKey = new RsaSecurityKey(rsaPublic);
var jwtIssuerOptions = new JwtIssuerOptions
{
Audience = tokenAuthSettings.Audience,
Issuer = tokenAuthSettings.Issuer,
};
var jwtAppSettingOptions = configuration.GetSection("B2C:JwtIssuerOptions");
var jwtIssuerOptions = jwtAppSettingOptions.Get<JwtIssuerOptions>();
if (string.IsNullOrEmpty(jwtIssuerOptions?.Issuer) || string.IsNullOrEmpty(jwtIssuerOptions.Audience))
throw new InvalidOperationException("JwtIssuerOptions are not configured correctly.");
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(Schemes.DefaultScheme, x =>
.AddJwtBearer(Schemes.HeathScheme, x =>
{
x.TokenValidationParameters = new TokenValidationParameters
{
@ -86,52 +88,10 @@ namespace Core.Thalos.BuildingBlocks.Configuration
options.Audience = jwtIssuerOptions?.Audience;
options.SigningCredentials = new SigningCredentials(rsaPrivateKey, SecurityAlgorithms.RsaSha256);
});
}
public static void AddAzureAuthentication(AuthSettings authSettings, IConfiguration configuration, IServiceCollection services)
{
var azureAdInMemorySettings = new Dictionary<string, string?>
{
{ "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>();
services.AddSingleton(jwtAppSettingOptions);
services.AddTransient<IAuthorizationHandler, PermissionsAuthorizationHandler>();
services.AddTransient<ITokenService, TokenService>();
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,12 @@
// ***********************************************************************
// <copyright file="AuthenticatedHttpClientHandler.cs">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
using Core.Cerberos.Adapters.Contracts;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.Handlers
{
/// <summary>
/// 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>
{

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">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
using Org.BouncyCastle.Crypto;
@ -10,7 +10,7 @@ using Org.BouncyCastle.Security;
using System.Security.Cryptography;
using System.Text;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.Helpers
{
/// <summary>
/// Handles all methods related to RSA encryption"/>.
@ -62,7 +62,7 @@ namespace Core.Thalos.BuildingBlocks
/// <returns>The private key.</returns>
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();
@ -79,7 +79,7 @@ namespace Core.Thalos.BuildingBlocks
/// <returns>The public key.</returns>
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();

View File

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

View File

@ -1,8 +1,11 @@
// ***********************************************************************
// <copyright file="TokenService.cs">
// AgileWebs
// <copyright file="T5okenService.cs">
// Heath
// </copyright>
// ***********************************************************************
using Core.Cerberos.Adapters.Common.Constants;
using Core.Cerberos.Adapters.Contracts;
using Core.Cerberos.Adapters.Options;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
@ -13,7 +16,7 @@ using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text.Json;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.Services
{
/// <summary>
/// Service responsible for manage authenticacion.
@ -71,7 +74,7 @@ namespace Core.Thalos.BuildingBlocks
/// </summary>
/// <param name="user">The user data.</param>
/// <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.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.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.RoleId, adapter?.Role?.Id ?? string.Empty),
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),
}),
@ -105,7 +109,7 @@ namespace Core.Thalos.BuildingBlocks
var token = tokenHandler.CreateEncodedJwt(tokenDescriptor);
return (token, adapter.Modules);
return token;
}
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">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
using Core.Cerberos.Adapters.Contracts;
using Microsoft.AspNetCore.Http;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters.TokenProvider
{
/// <summary>
/// Class to return the access token to controllers.

View File

@ -1,12 +1,12 @@
// ***********************************************************************
// <copyright file="UserExistenceAdapter.cs">
// AgileWebs
// Heath
// </copyright>
// ***********************************************************************
using System.Text.Json.Serialization;
namespace Core.Thalos.BuildingBlocks
namespace Core.Cerberos.Adapters
{
/// <summary>
/// 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; }
}
}