1212using static NpgsqlRestClient . Config ;
1313using static NpgsqlRestClient . Builder ;
1414using static NpgsqlRest . Auth . ClaimsDictionary ;
15+ using NpgsqlRest . Auth ;
1516
1617namespace NpgsqlRestClient ;
1718
@@ -41,8 +42,8 @@ public static class ExternalAuthConfig
4142 public static string ClientAnaliticsIpKey { get ; private set ; } = default ! ;
4243
4344 private static readonly Dictionary < string , ExternalAuthClientConfig > DefaultClientConfigs =
44- new Dictionary < string , ExternalAuthClientConfig >
45- {
45+ new ( )
46+ {
4647 { "google" , new ExternalAuthClientConfig
4748 {
4849 AuthUrl = "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id={0}&redirect_uri={1}&scope=openid profile email&state={2}" ,
@@ -190,7 +191,7 @@ public static void Configure(WebApplication app, NpgsqlRestOptions options, Post
190191 string code = ( node [ "code" ] ? . ToString ( ) ) ??
191192 throw new ArgumentException ( "code retrieved from the external provider is null" ) ;
192193
193- await ProcessAsync ( code , body , config , context , options ) ;
194+ await ProcessAsync ( code , config , context , options ) ;
194195 return ;
195196 }
196197 catch ( Exception e )
@@ -216,15 +217,14 @@ private static void PrepareResponse(string contentType, HttpContext context)
216217 context . Response . Headers . Expires = "0" ;
217218 }
218219
219- private static readonly HttpClient _httpClient = new ( ) ;
220+ private static HttpClient ? _httpClient = null ;
220221 private static readonly string _agent = $ "{ Guid . NewGuid ( ) . ToString ( ) [ ..8 ] } ";
221222
222223 private const string browserSessionStateKey = "__external_state" ;
223224 private const string browserSessionParamsKey = "__external_params" ;
224225
225226 private static async Task ProcessAsync (
226227 string code ,
227- string body ,
228228 ExternalAuthClientConfig config ,
229229 HttpContext context ,
230230 NpgsqlRestOptions options )
@@ -233,6 +233,8 @@ private static async Task ProcessAsync(
233233 string ? name ;
234234 string token ;
235235
236+ _httpClient ??= new ( ) ;
237+
236238 using var requestTokenMessage = new HttpRequestMessage ( HttpMethod . Post , config . TokenUrl ) ;
237239 requestTokenMessage . Headers . Accept . Add ( new MediaTypeWithQualityHeaderValue ( Application . Json ) ) ;
238240 requestTokenMessage . Content = new FormUrlEncodedContent ( new Dictionary < string , string >
@@ -273,6 +275,7 @@ private static async Task ProcessAsync(
273275 infoRequest . Headers . Authorization = new AuthenticationHeaderValue ( "Bearer" , token ) ;
274276 using var infoResponse = await _httpClient . SendAsync ( infoRequest ) ;
275277 var infoContent = await infoResponse . Content . ReadAsStringAsync ( ) ;
278+ JsonNode infoNode ;
276279 if ( ! infoResponse . IsSuccessStatusCode )
277280 {
278281 throw new HttpRequestException ( $ "Info endpoint { config . InfoUrl } returned { infoResponse . StatusCode } with following content: { infoContent } ") ;
@@ -284,18 +287,18 @@ private static async Task ProcessAsync(
284287
285288 try
286289 {
287- JsonNode node = JsonNode . Parse ( infoContent ) ??
290+ infoNode = JsonNode . Parse ( infoContent ) ??
288291 throw new ArgumentException ( "info json node is null" ) ;
289292
290293 // Email parsing
291- email = node [ "email" ] ? . ToString ( ) ?? // Google, GitHub, Facebook, Microsoft
292- node [ "userPrincipalName" ] ? . ToString ( ) ?? // Microsoft (organizational accounts)
293- node ? [ "elements" ] ? [ 0 ] ? [ "handle~" ] ? [ "emailAddress" ] ? . ToString ( ) ; // LinkedIn
294+ email = infoNode [ "email" ] ? . ToString ( ) ?? // Google, GitHub, Facebook, Microsoft
295+ infoNode [ "userPrincipalName" ] ? . ToString ( ) ?? // Microsoft (organizational accounts)
296+ infoNode ? [ "elements" ] ? [ 0 ] ? [ "handle~" ] ? [ "emailAddress" ] ? . ToString ( ) ; // LinkedIn
294297
295298#pragma warning disable CS8602 // Dereference of a possibly null reference.
296- name = node [ "localizedLastName" ] is not null ?
297- $ "{ node [ "localizedFirstName" ] } { node [ "localizedLastName" ] } ". Trim ( ) : // linkedin format
298- node [ "name" ] ? . ToString ( ) ; // normal format
299+ name = infoNode [ "localizedLastName" ] is not null ?
300+ $ "{ infoNode [ "localizedFirstName" ] } { infoNode [ "localizedLastName" ] } ". Trim ( ) : // linkedin format
301+ infoNode [ "name" ] ? . ToString ( ) ; // normal format
299302#pragma warning restore CS8602 // Dereference of a possibly null reference.
300303 }
301304 catch ( Exception e )
@@ -323,6 +326,7 @@ private static async Task ProcessAsync(
323326 {
324327 JsonNode node = JsonNode . Parse ( emailContent ) ??
325328 throw new ArgumentException ( "email json node is null" ) ;
329+ infoNode [ "emailRequest" ] = node ;
326330
327331 email = node [ "email" ] ? . ToString ( ) ??
328332 node ? [ "elements" ] ? [ 0 ] ? [ "handle~" ] ? [ "emailAddress" ] ? . ToString ( ) ; // linkedin format
@@ -351,8 +355,8 @@ private static async Task ProcessAsync(
351355 await connection . OpenAsync ( ) ;
352356 using var command = connection . CreateCommand ( ) ;
353357 command . CommandText = ExternalAuthConfig . LoginCommand ;
354- var paramCount = command . CommandText [ command . CommandText . IndexOf ( Consts . OpenParenthesis ) ..] . Split ( Consts . Comma ) . Length ;
355358
359+ var paramCount = PostgreSqlParameterCounter . CountParameters ( command . CommandText ) ;
356360 if ( paramCount >= 1 ) command . Parameters . Add ( new NpgsqlParameter ( )
357361 {
358362 Value = config . ExternalType ,
@@ -368,9 +372,11 @@ private static async Task ProcessAsync(
368372 Value = name is not null ? name : DBNull . Value ,
369373 NpgsqlDbType = NpgsqlTypes . NpgsqlDbType . Text
370374 } ) ;
375+ //emailContent
376+
371377 if ( paramCount >= 4 ) command . Parameters . Add ( new NpgsqlParameter ( )
372378 {
373- Value = body is not null ? body : DBNull . Value ,
379+ Value = infoNode is not null ? infoContent . ToString ( ) : DBNull . Value ,
374380 NpgsqlDbType = NpgsqlTypes . NpgsqlDbType . Json
375381 } ) ;
376382 if ( paramCount >= 5 )
0 commit comments