Add google authentication
This commit is contained in:
		| @@ -1,127 +1,192 @@ | ||||
| using Asp.Versioning; | ||||
| 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.Services.AddEndpointsApiExplorer(); | ||||
| 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(configureOptions => { configureOptions.UseCaseSensitivePaths = true; }); | ||||
| builder.Logging.AddOpenTelemetry(options => | ||||
| builder.Services.AddResponseCaching(options => { options.UseCaseSensitivePaths = true; }); | ||||
|  | ||||
| builder.Logging.AddOpenTelemetry(logging => | ||||
| { | ||||
|     options.IncludeScopes = true; | ||||
|     options.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("core.thalos.bff.api")).AddConsoleExporter(); | ||||
|     logging.IncludeScopes = true; | ||||
|     logging.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("core.thalos.bff.api")) | ||||
|            .AddConsoleExporter(); | ||||
| }); | ||||
|  | ||||
| builder.Host.ConfigureServices((context, services) => | ||||
| { | ||||
|     builder.Services.AddHsts(options => | ||||
|     services.AddHsts(options => | ||||
|     { | ||||
|         options.Preload = true; | ||||
|         options.IncludeSubDomains = true; | ||||
|         options.MaxAge = TimeSpan.FromDays(60); | ||||
|     }); | ||||
|     builder.Services.AddResponseCaching(configureOptions => | ||||
|     { | ||||
|         configureOptions.UseCaseSensitivePaths = true; | ||||
|         configureOptions.MaximumBodySize = 2048; | ||||
|     }); | ||||
|     builder.Services.AddHttpsRedirection(options => | ||||
|     { | ||||
|         options.RedirectStatusCode = 308; | ||||
|     }); | ||||
|  | ||||
|     services.AddHttpLogging(http => | ||||
|     { | ||||
|         http.CombineLogs = true; | ||||
|     }); | ||||
|     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.AddCors(options => | ||||
|     services.AddMvc().AddJsonOptions(opt => | ||||
|     { | ||||
|         options.AddPolicy("AllowAll", policyBuilder => | ||||
|             policyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); | ||||
|         opt.JsonSerializerOptions.WriteIndented = true; | ||||
|         opt.JsonSerializerOptions.MaxDepth = 20; | ||||
|         opt.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals; | ||||
|     }); | ||||
|     services.AddMvc().AddJsonOptions(options => | ||||
|  | ||||
|     services.Configure<BrotliCompressionProviderOptions>(opt => opt.Level = CompressionLevel.SmallestSize); | ||||
|     services.Configure<GzipCompressionProviderOptions>(opt => opt.Level = CompressionLevel.SmallestSize); | ||||
|     services.AddResponseCompression(opt => | ||||
|     { | ||||
|         options.JsonSerializerOptions.WriteIndented = true; | ||||
|         options.JsonSerializerOptions.MaxDepth = 20; | ||||
|         options.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals; | ||||
|         opt.EnableForHttps = true; | ||||
|         opt.Providers.Add<BrotliCompressionProvider>(); | ||||
|         opt.Providers.Add<GzipCompressionProvider>(); | ||||
|     }); | ||||
|     services.Configure<BrotliCompressionProviderOptions>(options => | ||||
|     { | ||||
|         options.Level = CompressionLevel.SmallestSize; | ||||
|     }); | ||||
|     services.Configure<GzipCompressionProviderOptions>(options => | ||||
|     { | ||||
|         options.Level = CompressionLevel.SmallestSize; | ||||
|     }); | ||||
|     services.AddResponseCompression(options => | ||||
|     { | ||||
|         options.EnableForHttps = true; | ||||
|         options.Providers.Add<BrotliCompressionProvider>(); | ||||
|         options.Providers.Add<GzipCompressionProvider>(); | ||||
|     }); | ||||
|     services.AddResponseCaching(); | ||||
|  | ||||
|     services.AddControllers(); | ||||
|     services.AddEndpointsApiExplorer(); | ||||
|     services.AddSwaggerGen(); | ||||
|     services.AddLogging(); | ||||
|     services.AddProblemDetails(); | ||||
|     services.AddHttpContextAccessor(); | ||||
|     services.AddTransient<TrackingMechanismExtension>(); // Register the TrackingIdHandler | ||||
|     services.AddTransient<TrackingMechanismExtension>(); | ||||
|     services.RegisterExternalLayer(builder.Configuration); | ||||
|  | ||||
|     services.AddApiVersioning(options => options.ReportApiVersions = true) | ||||
|                    .AddApiExplorer(options => | ||||
|                    { | ||||
|                        options.GroupNameFormat = "'v'VVV"; | ||||
|                        options.SubstituteApiVersionInUrl = true; | ||||
|                    }); | ||||
|            .AddApiExplorer(opt => | ||||
|            { | ||||
|                opt.GroupNameFormat = "'v'VVV"; | ||||
|                opt.SubstituteApiVersionInUrl = true; | ||||
|            }); | ||||
| }); | ||||
|  | ||||
| builder.Services.AddCors(options => | ||||
| { | ||||
|     options.AddDefaultPolicy( | ||||
|         builder => | ||||
|         { | ||||
|             builder.AllowAnyOrigin() | ||||
|                                 .AllowAnyHeader() | ||||
|                                 .AllowAnyMethod(); | ||||
|         }); | ||||
| }); | ||||
| builder.Services.AddScoped<ITokenService, TokenService>(); | ||||
|  | ||||
| //*************************************************************************// | ||||
| var app = builder.Build(); | ||||
|  | ||||
| app.UseDeveloperExceptionPage(); | ||||
|  | ||||
| app.UseCors(options => options.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()); | ||||
| app.UseSwagger(); | ||||
|  | ||||
| app.UseCors(options => options.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().WithOrigins("https://localhost:7239")); | ||||
| app.UseSwaggerUI(options => | ||||
| { | ||||
|     foreach (var version in app.DescribeApiVersions().Select(version => version.GroupName)) | ||||
|     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(); | ||||
| @@ -132,5 +197,4 @@ app.MapControllers(); | ||||
| app.UseHsts(); | ||||
| app.UseAntiforgery(); | ||||
| app.UseLogging(builder.Configuration); | ||||
|  | ||||
| app.Run(); | ||||
| app.Run(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Oscar Morales
					Oscar Morales