201 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using Asp.Versioning;
 | ||
| using Azure.Identity;
 | ||
| using Core.Blueprint.Logging.Configuration;
 | ||
| using Core.Thalos.Adapters.Contracts;
 | ||
| using Core.Thalos.Adapters.Extensions;
 | ||
| using Core.Thalos.Adapters.Services;
 | ||
| using Core.Thalos.BFF.Api.Services;
 | ||
| using Core.Thalos.External.ClientConfiguration;
 | ||
| using Google.Protobuf.WellKnownTypes;
 | ||
| using Microsoft.AspNetCore.Authentication;
 | ||
| using Microsoft.AspNetCore.Authentication.Cookies;
 | ||
| using Microsoft.AspNetCore.Authentication.JwtBearer;
 | ||
| using Microsoft.AspNetCore.Authentication.OpenIdConnect;
 | ||
| using Microsoft.AspNetCore.ResponseCompression;
 | ||
| using Microsoft.Extensions.Configuration.AzureAppConfiguration;
 | ||
| using Microsoft.IdentityModel.Tokens;
 | ||
| using Microsoft.OpenApi.Any;
 | ||
| using Microsoft.OpenApi.Interfaces;
 | ||
| using Microsoft.OpenApi.Models;
 | ||
| using OpenTelemetry.Logs;
 | ||
| using OpenTelemetry.Resources;
 | ||
| using Swashbuckle.AspNetCore.SwaggerUI;
 | ||
| using System.IO.Compression;
 | ||
| using System.Reflection;
 | ||
| using System.Security.Claims;
 | ||
| 
 | ||
| var builder = WebApplication.CreateBuilder(args);
 | ||
| 
 | ||
| builder.Configuration
 | ||
|     .AddUserSecrets(Assembly.GetExecutingAssembly())
 | ||
|     .AddEnvironmentVariables();
 | ||
| 
 | ||
| // 🔑 Google Auth config
 | ||
| var googleClientId = builder.Configuration["Authentication:Google:ClientId"];
 | ||
| var googleClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
 | ||
| var redirectUri = builder.Configuration["Authentication:Google:RedirectUri"];
 | ||
| 
 | ||
| // 🧩 Authentication
 | ||
| builder.Services.AddAuthentication(options =>
 | ||
| {
 | ||
|     options.DefaultAuthenticateScheme = Constant.Scheme;
 | ||
|     options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
 | ||
| })
 | ||
| .AddScheme<AuthenticationSchemeOptions,
 | ||
| GoogleAccessTokenAuthenticationHandler>(Constant.Scheme, null)
 | ||
| .AddGoogle(options =>
 | ||
| {
 | ||
|     options.ClientId = googleClientId!;
 | ||
|     options.ClientSecret = googleClientSecret!;
 | ||
|     //options.SaveTokens = true;
 | ||
|     options.CallbackPath = $"/{redirectUri}";
 | ||
| });
 | ||
| 
 | ||
| builder.Services.AddAuthorization();
 | ||
| builder.Services.AddScoped<IGoogleAuthHelper, GoogleAuthHelperService>();
 | ||
| builder.Services.AddScoped<IGoogleAuthorization, GoogleAuthorizationService>();
 | ||
| builder.Services.AddEndpointsApiExplorer();
 | ||
| 
 | ||
| // 🧩 Swagger + OAuth2
 | ||
| builder.Services.AddSwaggerGen(opts =>
 | ||
| {
 | ||
|     const string schemeName = "oauth2";
 | ||
| 
 | ||
|     opts.SwaggerDoc("v1",
 | ||
|         new OpenApiInfo { Title = "Core.Thalos.BFF", Version = "v1" });
 | ||
| 
 | ||
|     opts.AddSecurityDefinition(schemeName, new OpenApiSecurityScheme
 | ||
|     {
 | ||
|         Type = SecuritySchemeType.OAuth2,
 | ||
|         Scheme = "bearer",              // tells Swagger-UI to build an Authorization header
 | ||
|         BearerFormat = "JWT",
 | ||
|         Name = "Authorization",
 | ||
|         In = ParameterLocation.Header,
 | ||
| 
 | ||
|         /* ⚠️  The key line – tell Swagger-UI to pick id_token instead of access_token */
 | ||
|         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" }
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|     });
 | ||
| 
 | ||
|     // every operation requires the scheme
 | ||
|     opts.AddSecurityRequirement(new OpenApiSecurityRequirement
 | ||
|     {
 | ||
|         [new OpenApiSecurityScheme
 | ||
|         {
 | ||
|             Reference = new OpenApiReference
 | ||
|             { Type = ReferenceType.SecurityScheme, Id = schemeName }
 | ||
|         }
 | ||
|         ] = new[] { "openid", "email", "profile" }
 | ||
|     });
 | ||
| });
 | ||
| 
 | ||
| // 🎯 Existing configs (unchanged)
 | ||
| builder.Services.AddResponseCompression();
 | ||
| builder.Services.AddProblemDetails();
 | ||
| builder.Services.AddLogs(builder);
 | ||
| builder.Services.AddMemoryCache();
 | ||
| builder.Services.AddResponseCaching(options => { options.UseCaseSensitivePaths = true; });
 | ||
| 
 | ||
| builder.Logging.AddOpenTelemetry(logging =>
 | ||
| {
 | ||
|     logging.IncludeScopes = true;
 | ||
|     logging.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("core.thalos.bff.api"))
 | ||
|            .AddConsoleExporter();
 | ||
| });
 | ||
| 
 | ||
| builder.Host.ConfigureServices((context, services) =>
 | ||
| {
 | ||
|     services.AddHsts(options =>
 | ||
|     {
 | ||
|         options.Preload = true;
 | ||
|         options.IncludeSubDomains = true;
 | ||
|         options.MaxAge = TimeSpan.FromDays(60);
 | ||
|     });
 | ||
| 
 | ||
|     services.AddHttpsRedirection(options => { options.RedirectStatusCode = 308; });
 | ||
|     services.AddAntiforgery();
 | ||
|     services.AddHttpLogging(http => http.CombineLogs = true);
 | ||
|     services.AddCors(options => options.AddPolicy("AllowAll", policy => policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));
 | ||
| 
 | ||
|     services.AddMvc().AddJsonOptions(opt =>
 | ||
|     {
 | ||
|         opt.JsonSerializerOptions.WriteIndented = true;
 | ||
|         opt.JsonSerializerOptions.MaxDepth = 20;
 | ||
|         opt.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals;
 | ||
|     });
 | ||
| 
 | ||
|     services.Configure<BrotliCompressionProviderOptions>(opt => opt.Level = CompressionLevel.SmallestSize);
 | ||
|     services.Configure<GzipCompressionProviderOptions>(opt => opt.Level = CompressionLevel.SmallestSize);
 | ||
|     services.AddResponseCompression(opt =>
 | ||
|     {
 | ||
|         opt.EnableForHttps = true;
 | ||
|         opt.Providers.Add<BrotliCompressionProvider>();
 | ||
|         opt.Providers.Add<GzipCompressionProvider>();
 | ||
|     });
 | ||
| 
 | ||
|     services.AddControllers();
 | ||
|     services.AddHttpContextAccessor();
 | ||
|     services.AddTransient<TrackingMechanismExtension>();
 | ||
|     services.RegisterExternalLayer(builder.Configuration);
 | ||
| 
 | ||
|     services.AddApiVersioning(options => options.ReportApiVersions = true)
 | ||
|            .AddApiExplorer(opt =>
 | ||
|            {
 | ||
|                opt.GroupNameFormat = "'v'VVV";
 | ||
|                opt.SubstituteApiVersionInUrl = true;
 | ||
|            });
 | ||
| });
 | ||
| 
 | ||
| builder.Services.AddScoped<ITokenService, TokenService>();
 | ||
| 
 | ||
| var app = builder.Build();
 | ||
| 
 | ||
| app.UseDeveloperExceptionPage();
 | ||
| 
 | ||
| app.UseSwagger();
 | ||
| 
 | ||
| app.UseCors(options => options.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().WithOrigins("https://localhost:7239"));
 | ||
| app.UseSwaggerUI(options =>
 | ||
| {
 | ||
|     foreach (var version in app.DescribeApiVersions().Select(v => v.GroupName))
 | ||
|         options.SwaggerEndpoint($"/swagger/{version}/swagger.json", version);
 | ||
| 
 | ||
|     options.DisplayRequestDuration();
 | ||
|     options.EnableTryItOutByDefault();
 | ||
|     options.DocExpansion(DocExpansion.None);
 | ||
| 
 | ||
|     options.OAuthClientId(googleClientId);
 | ||
|     options.OAuthClientSecret(googleClientSecret);
 | ||
|     options.OAuthUsePkce();
 | ||
|     options.OAuthScopes("openid", "email", "profile");
 | ||
| });
 | ||
| 
 | ||
| app.UseResponseCompression();
 | ||
| app.UseResponseCaching();
 | ||
| app.UseHttpsRedirection();
 | ||
| 
 | ||
| app.UseAuthentication();
 | ||
| app.UseAuthorization();
 | ||
| app.MapControllers();
 | ||
| app.UseHsts();
 | ||
| app.UseAntiforgery();
 | ||
| app.UseLogging(builder.Configuration);
 | ||
| app.Run();
 | 
