From f216660afa405a88f3ae477faf63dd8aedd98817 Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Sun, 28 Jun 2026 19:29:54 +0900 Subject: [PATCH] fix(portal): skip unconfigured oauth providers --- TaxBaik.Web/Program.cs | 142 +++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 62 deletions(-) diff --git a/TaxBaik.Web/Program.cs b/TaxBaik.Web/Program.cs index c94bd7c..36e7255 100644 --- a/TaxBaik.Web/Program.cs +++ b/TaxBaik.Web/Program.cs @@ -64,7 +64,7 @@ if (isProduction && jwtKey.Contains("dev-secret", StringComparison.OrdinalIgnore throw new InvalidOperationException("Production JWT SecretKey must not use the development default."); var key = Encoding.ASCII.GetBytes(jwtKey); -builder.Services.AddAuthentication(opts => +var authenticationBuilder = builder.Services.AddAuthentication(opts => { opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; @@ -100,69 +100,87 @@ builder.Services.AddAuthentication(opts => opts.Cookie.HttpOnly = true; opts.Cookie.SameSite = SameSiteMode.Lax; opts.Cookie.SecurePolicy = isProduction ? CookieSecurePolicy.Always : CookieSecurePolicy.SameAsRequest; -}) -.AddGoogle(PortalOAuthDefaults.GoogleScheme, opts => -{ - opts.SignInScheme = PortalOAuthDefaults.ExternalScheme; - opts.ClientId = builder.Configuration["Authentication:Google:ClientId"] ?? ""; - opts.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"] ?? ""; - opts.CallbackPath = "/taxbaik/portal/signin-google"; -}) -.AddOAuth(PortalOAuthDefaults.NaverScheme, opts => -{ - opts.SignInScheme = PortalOAuthDefaults.ExternalScheme; - opts.ClientId = builder.Configuration["Authentication:Naver:ClientId"] ?? ""; - opts.ClientSecret = builder.Configuration["Authentication:Naver:ClientSecret"] ?? ""; - opts.CallbackPath = "/taxbaik/portal/signin-naver"; - opts.AuthorizationEndpoint = "https://nid.naver.com/oauth2.0/authorize"; - opts.TokenEndpoint = "https://nid.naver.com/oauth2.0/token"; - opts.UserInformationEndpoint = "https://openapi.naver.com/v1/nid/me"; - opts.SaveTokens = true; - opts.Events = new OAuthEvents - { - OnCreatingTicket = async context => - { - var request = new HttpRequestMessage(HttpMethod.Get, opts.UserInformationEndpoint); - request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", context.AccessToken); - var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted); - response.EnsureSuccessStatusCode(); - using var payload = System.Text.Json.JsonDocument.Parse(await response.Content.ReadAsStringAsync(context.HttpContext.RequestAborted)); - var responseRoot = payload.RootElement.GetProperty("response"); - context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, responseRoot.GetProperty("id").GetString() ?? "")); - context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, responseRoot.GetProperty("name").GetString() ?? "")); - context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Email, responseRoot.GetProperty("email").GetString() ?? "")); - } - }; -}) -.AddOAuth(PortalOAuthDefaults.KakaoScheme, opts => -{ - opts.SignInScheme = PortalOAuthDefaults.ExternalScheme; - opts.ClientId = builder.Configuration["Authentication:Kakao:ClientId"] ?? ""; - opts.ClientSecret = builder.Configuration["Authentication:Kakao:ClientSecret"] ?? ""; - opts.CallbackPath = "/taxbaik/portal/signin-kakao"; - opts.AuthorizationEndpoint = "https://kauth.kakao.com/oauth/authorize"; - opts.TokenEndpoint = "https://kauth.kakao.com/oauth/token"; - opts.UserInformationEndpoint = "https://kapi.kakao.com/v2/user/me"; - opts.SaveTokens = true; - opts.Events = new OAuthEvents - { - OnCreatingTicket = async context => - { - var request = new HttpRequestMessage(HttpMethod.Get, opts.UserInformationEndpoint); - request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", context.AccessToken); - var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted); - response.EnsureSuccessStatusCode(); - using var payload = System.Text.Json.JsonDocument.Parse(await response.Content.ReadAsStringAsync(context.HttpContext.RequestAborted)); - var kakaoAccount = payload.RootElement.GetProperty("kakao_account"); - var profile = kakaoAccount.GetProperty("profile"); - context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, payload.RootElement.GetProperty("id").GetInt64().ToString())); - context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, profile.GetProperty("nickname").GetString() ?? "")); - if (kakaoAccount.TryGetProperty("email", out var emailProp)) - context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Email, emailProp.GetString() ?? "")); - } - }; }); +var googleClientId = builder.Configuration["Authentication:Google:ClientId"]; +var googleClientSecret = builder.Configuration["Authentication:Google:ClientSecret"]; +if (!string.IsNullOrWhiteSpace(googleClientId) && !string.IsNullOrWhiteSpace(googleClientSecret)) +{ + authenticationBuilder.AddGoogle(PortalOAuthDefaults.GoogleScheme, opts => + { + opts.SignInScheme = PortalOAuthDefaults.ExternalScheme; + opts.ClientId = googleClientId; + opts.ClientSecret = googleClientSecret; + opts.CallbackPath = "/taxbaik/portal/signin-google"; + }); +} + +var naverClientId = builder.Configuration["Authentication:Naver:ClientId"]; +var naverClientSecret = builder.Configuration["Authentication:Naver:ClientSecret"]; +if (!string.IsNullOrWhiteSpace(naverClientId) && !string.IsNullOrWhiteSpace(naverClientSecret)) +{ + authenticationBuilder.AddOAuth(PortalOAuthDefaults.NaverScheme, opts => + { + opts.SignInScheme = PortalOAuthDefaults.ExternalScheme; + opts.ClientId = naverClientId; + opts.ClientSecret = naverClientSecret; + opts.CallbackPath = "/taxbaik/portal/signin-naver"; + opts.AuthorizationEndpoint = "https://nid.naver.com/oauth2.0/authorize"; + opts.TokenEndpoint = "https://nid.naver.com/oauth2.0/token"; + opts.UserInformationEndpoint = "https://openapi.naver.com/v1/nid/me"; + opts.SaveTokens = true; + opts.Events = new OAuthEvents + { + OnCreatingTicket = async context => + { + var request = new HttpRequestMessage(HttpMethod.Get, opts.UserInformationEndpoint); + request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", context.AccessToken); + var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted); + response.EnsureSuccessStatusCode(); + using var payload = System.Text.Json.JsonDocument.Parse(await response.Content.ReadAsStringAsync(context.HttpContext.RequestAborted)); + var responseRoot = payload.RootElement.GetProperty("response"); + context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, responseRoot.GetProperty("id").GetString() ?? "")); + context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, responseRoot.GetProperty("name").GetString() ?? "")); + context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Email, responseRoot.GetProperty("email").GetString() ?? "")); + } + }; + }); +} + +var kakaoClientId = builder.Configuration["Authentication:Kakao:ClientId"]; +var kakaoClientSecret = builder.Configuration["Authentication:Kakao:ClientSecret"]; +if (!string.IsNullOrWhiteSpace(kakaoClientId) && !string.IsNullOrWhiteSpace(kakaoClientSecret)) +{ + authenticationBuilder.AddOAuth(PortalOAuthDefaults.KakaoScheme, opts => + { + opts.SignInScheme = PortalOAuthDefaults.ExternalScheme; + opts.ClientId = kakaoClientId; + opts.ClientSecret = kakaoClientSecret; + opts.CallbackPath = "/taxbaik/portal/signin-kakao"; + opts.AuthorizationEndpoint = "https://kauth.kakao.com/oauth/authorize"; + opts.TokenEndpoint = "https://kauth.kakao.com/oauth/token"; + opts.UserInformationEndpoint = "https://kapi.kakao.com/v2/user/me"; + opts.SaveTokens = true; + opts.Events = new OAuthEvents + { + OnCreatingTicket = async context => + { + var request = new HttpRequestMessage(HttpMethod.Get, opts.UserInformationEndpoint); + request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", context.AccessToken); + var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted); + response.EnsureSuccessStatusCode(); + using var payload = System.Text.Json.JsonDocument.Parse(await response.Content.ReadAsStringAsync(context.HttpContext.RequestAborted)); + var kakaoAccount = payload.RootElement.GetProperty("kakao_account"); + var profile = kakaoAccount.GetProperty("profile"); + context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, payload.RootElement.GetProperty("id").GetInt64().ToString())); + context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, profile.GetProperty("nickname").GetString() ?? "")); + if (kakaoAccount.TryGetProperty("email", out var emailProp)) + context.Identity?.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Email, emailProp.GetString() ?? "")); + } + }; + }); +} + // Blazor 인증 builder.Services.AddScoped(); builder.Services.AddScoped();