-
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathappsettings.json
More file actions
2563 lines (2526 loc) · 117 KB
/
Copy pathappsettings.json
File metadata and controls
2563 lines (2526 loc) · 117 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{
//
// The application name used to set the application name property in connection string by "NpgsqlRest.SetApplicationNameInConnection" or the "NpgsqlRest.UseJsonApplicationName" settings.
// It is the name of the top-level directory if set to null.
//
"ApplicationName": null,
//
// Production or Development
//
"EnvironmentName": "Production",
//
// Specify the urls the web host will listen on. See https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.hostingabstractionswebhostbuilderextensions.useurls?view=aspnetcore-8.0
//
"Urls": "http://localhost:8080",
//
// Logs at startup, format placeholders:
// {time} - startup time
// {urls} - listening on urls
// {version} - current version
// {environment} - EnvironmentName
// {application} - ApplicationName
//
// Note: This message is logged at Information level. To disable this message, set to empty string.
//
"StartupMessage": "Started in {time}, listening on {urls}, version {version}",
//
// Configuration settings
//
"Config": {
//
// Add the environment variables to configuration.
// When enabled, environment variables will override the settings in this configuration file but can be overridden by command line arguments.
// Complex hierarchical keys can be defined using double underscore as a separator.
// For example, "ConnectionStrings__Default" environment variable will override the "ConnectionStrings.Default" setting in this configuration file.
//
"AddEnvironmentVariables": false,
//
// When set, configuration values will be parsed for environment variables in the format {ENV_VAR_NAME}
// and replaced with the value of the environment variable when available.
//
"ParseEnvironmentVariables": true,
//
// Path to a .env file containing environment variables.
// When AddEnvironmentVariables or ParseEnvironmentVariables is true and this file exists,
// variables from this file will be loaded and made available for configuration parsing.
// Format: KEY=VALUE (one per line)
//
"EnvFile": null,
//
// Validate configuration keys against known defaults at startup.
// "Ignore" - no validation
// "Warning" - log warnings for unknown keys, continue startup (default)
// "Error" - log errors for unknown keys and exit
//
"ValidateConfigKeys": "Warning"
},
//
// List of named connection strings to PostgreSQL databases.
// The "Default" connection string is used when no connection name is specified.
// For connection string definition see https://www.npgsql.org/doc/connection-string-parameters.html
//
"ConnectionStrings": {
"Default": "Host={PGHOST};Port=5432;Database={PGDATABASE};Username={PGUSER};Password={PGPASSWORD}"
},
//
// Additional connection settings and options.
//
"ConnectionSettings": {
//
// Sets the ApplicationName connection property in the connection string to the value of the ApplicationName configuration.
// Note: This option is ignored if the UseJsonApplicationName option is enabled.
//
"SetApplicationNameInConnection": true,
//
// Sets the ApplicationName connection property dynamically on every request in the following format:
// {"app":"<ApplicationName>","uid":"<user_id>","id":"<NpgsqlRest.ExecutionIdHeaderName>"}
// Note: The ApplicationName connection property is limited to 64 characters.
//
"UseJsonApplicationName": false,
//
// Test any connection string before initializing the application and using it. The connection string is tested by opening and closing the connection.
//
"TestConnectionStrings": true,
//
// Connection open retry options.
//
"RetryOptions": {
"Enabled": true,
//
// Retry sequence in seconds. Accepts decimal numbers (0.25 is quarter of a second). The length of the array determines the maximum number of retries.
//
"RetrySequenceSeconds": [1, 3, 6, 12],
//
// Error codes that will trigger a retry when opening a connection. See https://www.postgresql.org/docs/current/errcodes-appendix.html
//
"ErrorCodes": [
"08000", "08003", "08006", "08001", "08004", // Connection failure codes
"55P03", // Lock not available
"55006", // Object in use
"53300", // Too many connections
"57P03", // Cannot connect now
"40001" // Serialization failure (can be retried)
]
},
//
// The connection name in ConnectionStrings configuration that will be used to execute the metadata query. If this value is null, the default connection string will be used.
//
"MetadataQueryConnectionName": null,
//
// Set the search path to this schema before executing the metadata query function.
// When null (default), no search path is set and the server's default search path is used.
//
// This is needed when using non superuser connection roles with limited schema access and mapping the metadata function to a specific schema.
// If the connection string contains the same "Search Path=" it will be skipped.
//
"MetadataQuerySchema": null,
// Any: Any successful connection is acceptable.
// Primary: Server must not be in hot standby mode (pg_is_in_recovery() must return false).
// Standby: Server must be in hot standby mode (pg_is_in_recovery() must return true).
// PreferPrimary: First try to find a primary server, but if none of the listed hosts is a primary server, try again in Any mode.
// PreferStandby: First try to find a standby server, but if none of the listed hosts is a standby server, try again in Any mode.
// ReadWrite: Session must accept read-write transactions by default (that is, the server must not be in hot standby mode and the default_transaction_read_only parameter must be off).
// ReadOnly: Session must not accept read-write transactions by default (the converse).
// see https://www.npgsql.org/doc/failover-and-load-balancing.html
"MultiHostConnectionTargets": {
// all connections use the same target mode
"Default": "Any",
// per connection overrides { "name": "Primary|Standby|Any|PreferPrimary|PreferStandby|ReadWrite|ReadOnly" }
"ByConnectionName": { }
}
},
//
// Enable to invoke UseKestrelHttpsConfiguration. See https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.webhostbuilderkestrelextensions.usekestrelhttpsconfiguration?view=aspnetcore-8.0
//
"Ssl": {
"Enabled": false,
//
// Adds middleware for redirecting HTTP Requests to HTTPS. See https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.httpspolicybuilderextensions.usehttpsredirection?view=aspnetcore-8.0
//
"UseHttpsRedirection": true,
//
// Adds middleware for using HSTS, which adds the Strict-Transport-Security header. See https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.hstsbuilderextensions.usehsts?view=aspnetcore-2.1
//
"UseHsts": true
},
//
// Data protection settings. Encryption/decryption settings for Auth Cookies, Antiforgery tokens and custom data protection needs.
//
"DataProtection": {
"Enabled": true,
//
// Set to null to use the current "ApplicationName" value.
// This value determines encryption type or class. Meaning, different application names will not be able to decrypt each other's data.
//
"CustomApplicationName": null,
//
// Sets the default lifetime in days of keys created by the data protection system.
// Represents a number of days how long before keys are rotated.
//
"DefaultKeyLifetimeDays": 90,
//
// Data protection location: "Default", "FileSystem" or "Database"
//
// Note: When running on Linux, using Default location means keys will not be persisted.
// When keys are lost on restart, encrypted tokens (auth) will also not work on restart.
// Linux users should use FileSystem or Database storage.
//
"Storage": "Default",
//
// FileSystem storage path. Set to a valid path when using FileSystem.
// Note: When running in Docker environment, the path must be a Docker volume path to persist the keys.
//
"FileSystemPath": "./data-protection-keys",
//
// GetAllElements database command. Expected to return rows with a single column of type text.
//
"GetAllElementsCommand": "select get_data_protection_keys()",
//
// StoreElement database command. Receives two parameters: name and data of type text. Doesn't return anything.
//
"StoreElementCommand": "call store_data_protection_keys($1,$2)",
//
// Configure encryption algorithms for data protection keys or null to use the default algorithm.
// Values: AES_128_CBC, AES_192_CBC, AES_256_CBC, AES_128_GCM, AES_192_GCM, AES_256_GCM
//
"EncryptionAlgorithm": null,
//
// Configure validation algorithms for data protection keys or null to use the default algorithm.
// Values: HMACSHA256, HMACSHA512
//
"ValidationAlgorithm": null,
//
// Key encryption method: "None", "Certificate", or "Dpapi" (Windows only)
// None: Keys are not encrypted at rest (default)
// Certificate: Keys are encrypted using an X.509 certificate
// Dpapi: Keys are encrypted using Windows Data Protection API (Windows only)
//
"KeyEncryption": "None",
//
// Path to the X.509 certificate file (.pfx) when using Certificate key encryption.
//
"CertificatePath": null,
//
// Password for the certificate file. Can be null for certificates without password.
// For security, consider using environment variable reference: "${CERT_PASSWORD}"
//
"CertificatePassword": null,
//
// When using Dpapi key encryption, set to true to protect keys to the local machine.
// If false (default), keys are protected to the current user account.
//
"DpapiLocalMachine": false
},
//
// Uncomment to configure Kestrel web server and to add certificates
// See https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-9.0
//
"Kestrel": {
// "Endpoints": {
// "Http": {
// "Url": "http://localhost:5000"
// },
// "HttpsInlineCertFile": {
// "Url": "https://localhost:5001",
// "Certificate": {
// "Path": "<path to .pfx file>",
// "Password": "$CREDENTIAL_PLACEHOLDER$"
// }
// },
// "HttpsInlineCertAndKeyFile": {
// "Url": "https://localhost:5002",
// "Certificate": {
// "Path": "<path to .pem/.crt file>",
// "KeyPath": "<path to .key file>",
// "Password": "$CREDENTIAL_PLACEHOLDER$"
// }
// },
// "HttpsInlineCertStore": {
// "Url": "https://localhost:5003",
// "Certificate": {
// "Subject": "<subject; required>",
// "Store": "<certificate store; required>",
// "Location": "<location; defaults to CurrentUser>",
// "AllowInvalid": "<true or false; defaults to false>"
// }
// },
// "HttpsDefaultCert": {
// "Url": "https://localhost:5004"
// }
// },
// "Certificates": {
// "Default": {
// "Path": "<path to .pfx file>",
// "Password": "$CREDENTIAL_PLACEHOLDER$"
// }
// },
// "Limits": {
// "MaxConcurrentConnections": 100,
// "MaxConcurrentUpgradedConnections": 100,
// "MaxRequestBodySize": 30000000,
// "MaxRequestBufferSize": 1048576,
// "MaxRequestHeaderCount": 100,
// "MaxRequestHeadersTotalSize": 32768,
// "MaxRequestLineSize": 8192,
// "MaxResponseBufferSize": 65536,
// "KeepAliveTimeout": "00:02:00",
// "RequestHeadersTimeout": "00:00:30",
// "Http2": {
// "MaxStreamsPerConnection": 100,
// "HeaderTableSize": 4096,
// "MaxFrameSize": 16384,
// "MaxRequestHeaderFieldSize": 8192,
// "InitialConnectionWindowSize": 65535,
// "InitialStreamWindowSize": 65535,
// "MaxReadFrameSize": 16384,
// "KeepAlivePingDelay": "00:00:30",
// "KeepAlivePingTimeout": "00:01:00",
// "KeepAlivePingPolicy": "WithActiveRequests"
// },
// "Http3": {
// "MaxRequestHeaderFieldSize": 8192
// }
// },
// "DisableStringReuse": false,
// "AllowAlternateSchemes": false,
// "AllowSynchronousIO": false,
// "AllowResponseHeaderCompression": true,
// "AddServerHeader": true,
// "AllowHostHeaderOverride": false
},
//
// Thread pool configuration settings for optimizing application performance
//
"ThreadPool": {
//
// Minimum number of worker threads in the thread pool. Set to null to use system defaults.
//
"MinWorkerThreads": null,
//
// Minimum number of completion port threads. Set to null to use system defaults.
//
"MinCompletionPortThreads": null,
//
// Maximum number of worker threads in the thread pool. Set to null to use system defaults.
//
"MaxWorkerThreads": null,
//
// Maximum number of completion port threads. Set to null to use system defaults.
//
"MaxCompletionPortThreads": null
},
//
// Authentication and Authorization settings
//
"Auth": {
//
// Enable Cookie Auth
//
"CookieAuth": false,
//
// Authentication scheme name for cookie authentication. Set to null to use default.
//
"CookieAuthScheme": null,
//
// Number of days the cookie remains valid.
//
"CookieValidDays": 14,
//
// Custom name for the authentication cookie. Set to null to use default.
//
"CookieName": null,
//
// Path scope for the authentication cookie. Set to null to use default.
//
"CookiePath": null,
//
// Domain scope for the authentication cookie. Set to null to use default.
//
"CookieDomain": null,
//
// Allow multiple concurrent sessions for the same user.
//
"CookieMultiSessions": true,
//
// Make cookie accessible only via HTTP (not JavaScript).
//
"CookieHttpOnly": true,
//
// Enable Microsoft Bearer Token Auth (proprietary format, not JWT)
//
"BearerTokenAuth": false,
//
// Authentication scheme name for bearer token authentication. Set to null to use default.
//
"BearerTokenAuthScheme": null,
//
// Number of hours before bearer token expires.
//
"BearerTokenExpireHours": 1,
// POST { "refresh": "{{refreshToken}}" }
"BearerTokenRefreshPath": "/api/token/refresh",
//
// Enable standard JWT (JSON Web Token) Bearer Authentication
//
"JwtAuth": false,
//
// Authentication scheme name for JWT authentication. Set to null to use default "JwtBearer".
//
"JwtAuthScheme": null,
//
// Secret key used to sign JWT tokens. Must be at least 32 characters for HS256.
// IMPORTANT: Use a strong, unique secret in production. Store securely (e.g., environment variable).
//
"JwtSecret": null,
//
// JWT issuer (iss claim). Identifies the principal that issued the JWT.
//
"JwtIssuer": null,
//
// JWT audience (aud claim). Identifies the recipients that the JWT is intended for.
//
"JwtAudience": null,
//
// Number of minutes before JWT access token expires. Default is 60 minutes.
//
"JwtExpireMinutes": 60,
//
// Number of days before JWT refresh token expires. Default is 7 days.
//
"JwtRefreshExpireDays": 7,
//
// Validate the issuer (iss) claim. Set to true if JwtIssuer is configured.
//
"JwtValidateIssuer": false,
//
// Validate the audience (aud) claim. Set to true if JwtAudience is configured.
//
"JwtValidateAudience": false,
//
// Validate the token lifetime (exp claim). Default is true.
//
"JwtValidateLifetime": true,
//
// Validate the signing key. Default is true.
//
"JwtValidateIssuerSigningKey": true,
//
// Clock skew to apply when validating token lifetime. Format: PostgreSQL interval.
// Default is 5 minutes to account for clock differences between servers.
//
"JwtClockSkew": "5 minutes",
//
// URL path for JWT token refresh endpoint. POST with { "refreshToken": "..." }
// Returns new access token and refresh token pair.
//
"JwtRefreshPath": "/api/jwt/refresh",
//
// Enable external auth providers
//
"External": {
"Enabled": false,
//
// sessionStorage key to store the status of the external auth process returned by the signin page.
// The value is HTTP status code (200 for success, 401 for unauthorized, 403 for forbidden, etc.)
//
"BrowserSessionStatusKey": "__external_status",
//
// sessionStorage key to store the message of the external auth process returned by the signin page.
//
"BrowserSessionMessageKey": "__external_message",
//
// Path to the signin page to handle the external auth process. Redirect to this page to start the external auth process.
// Format placeholder {0} is the provider name in lowercase (google, linkedin, github, etc.)
//
"SigninUrl": "/signin-{0}",
//
// Sign in page template. Format placeholders {0} is the provider name, {1} is the script to redirect to the external auth provider.
//
"SignInHtmlTemplate": "<!DOCTYPE html><html><head><meta charset=\"utf-8\" /><title>Talking To {0}</title></head><body>Loading...{1}</body></html>",
//
// URL to redirect after the external auth process is completed. Usually this is resolved from the request automatically. Except when it's not.
//
"RedirectUrl": null,
//
// Path to redirect after the external auth process is completed.
//
"ReturnToPath": "/",
//
// Query string key to store the path to redirect after the external auth process is completed.
// Use this to set dynamic return path. If this query string key is not found, the ReturnToPath value is used.
//
"ReturnToPathQueryStringKey": "return_to",
//
// Login command to execute after the external auth process is completed. There are five positional and optional parameters:
// $1 - external login provider (if parameter exists, type text).
// $2 - external login email (if parameter exists, type text).
// $3 - external login name (if parameter exists, type text).
// $4 - external login JSON data received (if parameter exists, type text, JSON or JSONB).
// $5 - client browser analytics JSON data (if parameter exists, type text, JSON or JSONB).
//
// The command uses the same rules as the login enabled routine.
// See: "NpgsqlRest.“LoginPath"
//
"LoginCommand": "select * from external_login($1,$2,$3,$4,$5)",
//
// Browser client analytics data that will be sent as JSON to external auth command as the 5th parameter if supplied.
//
"ClientAnalyticsData": "{timestamp:new Date().toISOString(),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,screen:{width:window.screen.width,height:window.screen.height,colorDepth:window.screen.colorDepth,pixelRatio:window.devicePixelRatio,orientation:screen.orientation.type},browser:{userAgent:navigator.userAgent,language:navigator.language,languages:navigator.languages,cookiesEnabled:navigator.cookieEnabled,doNotTrack:navigator.doNotTrack,onLine:navigator.onLine,platform:navigator.platform,vendor:navigator.vendor},memory:{deviceMemory:navigator.deviceMemory,hardwareConcurrency:navigator.hardwareConcurrency},window:{innerWidth:window.innerWidth,innerHeight:window.innerHeight,outerWidth:window.outerWidth,outerHeight:window.outerHeight},location:{href:window.location.href,hostname:window.location.hostname,pathname:window.location.pathname,protocol:window.location.protocol,referrer:document.referrer},performance:{navigation:{type:performance.navigation?.type,redirectCount:performance.navigation?.redirectCount},timing:performance.timing?{loadEventEnd:performance.timing.loadEventEnd,loadEventStart:performance.timing.loadEventStart,domComplete:performance.timing.domComplete,domInteractive:performance.timing.domInteractive,domContentLoadedEventEnd:performance.timing.domContentLoadedEventEnd}:null}}",
//
// Client IP address that will be added to the client analytics data under this JSON key.
//
"ClientAnalyticsIpKey": "ip",
//
// External providers
//
"Google": {
//
// visit https://console.cloud.google.com/apis/ to configure your Google app and get your client id and client secret
//
"Enabled": false,
"ClientId": "",
"ClientSecret": "",
"AuthUrl": "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id={0}&redirect_uri={1}&scope=openid profile email&state={2}",
"TokenUrl": "https://oauth2.googleapis.com/token",
"InfoUrl": "https://www.googleapis.com/oauth2/v3/userinfo",
"EmailUrl": null
},
"LinkedIn": {
//
// visit https://www.linkedin.com/developers/apps/ to configure your LinkedIn app and get your client id and client secret
//
"Enabled": false,
"ClientId": "",
"ClientSecret": "",
"AuthUrl": "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id={0}&redirect_uri={1}&state={2}&scope=r_liteprofile%20r_emailaddress",
"TokenUrl": "https://www.linkedin.com/oauth/v2/accessToken",
"InfoUrl": "https://api.linkedin.com/v2/me",
"EmailUrl": "https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements//(handle~))"
},
"GitHub": {
//
// visit https://github.com/settings/developers/ to configure your GitHub app and get your client id and client secret
//
"Enabled": false,
"ClientId": "",
"ClientSecret": "",
"AuthUrl": "https://github.com/login/oauth/authorize?client_id={0}&redirect_uri={1}&state={2}&allow_signup=false",
"TokenUrl": "https://github.com/login/oauth/access_token",
"InfoUrl": "https://api.github.com/user",
"EmailUrl": null
},
"Microsoft": {
//
// visit https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade to configure your Microsoft app and get your client id and client secret
// Documentation: https://learn.microsoft.com/en-us/entra/identity-platform/
//
"Enabled": false,
"ClientId": "",
"ClientSecret": "",
"AuthUrl": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?response_type=code&client_id={0}&redirect_uri={1}&scope=openid%20profile%20email&state={2}",
"TokenUrl": "https://login.microsoftonline.com/common/oauth2/v2.0/token",
"InfoUrl": "https://graph.microsoft.com/oidc/userinfo",
"EmailUrl": null
},
"Facebook": {
//
// visit https://developers.facebook.com/apps/ to configure your Facebook app and get your client id and client secret
// Documentation: https://developers.facebook.com/docs/facebook-login/
//
"Enabled": false,
"ClientId": "",
"ClientSecret": "",
"AuthUrl": "https://www.facebook.com/v20.0/dialog/oauth?response_type=code&client_id={0}&redirect_uri={1}&scope=public_profile%20email&state={2}",
"TokenUrl": "https://graph.facebook.com/v20.0/oauth/access_token",
"InfoUrl": "https://graph.facebook.com/me?fields=id,name,email",
"EmailUrl": null
}
},
//
// WebAuthn/FIDO2 Passkey Authentication
// Provides phishing-resistant, passwordless authentication using device-native biometrics or PINs.
//
"PasskeyAuth": {
//
// Enable passkey authentication.
//
"Enabled": false,
//
// Enable registration endpoints.
//
"EnableRegister": false,
//
// Rate limiter policy name to apply to all passkey endpoints.
// It is recommended to enable rate limiting on passkey endpoints to protect against brute-force attacks.
// Set to the name of a configured rate limiter policy, or null to disable rate limiting.
//
"RateLimiterPolicy": null,
//
// Optional connection name for named DataSource or ConnectionString lookup.
// If null, uses the default DataSource or ConnectionString from NpgsqlRest options.
//
"ConnectionName": null,
//
// Command retry strategy name from CommandRetryOptions.Strategies.
// Set to null to disable command retry for passkey endpoints.
//
"CommandRetryStrategy": "default",
//
// Relying Party ID (domain name). Should match your application domain (e.g., "example.com").
// If null, auto-detected from the request host.
// Note: IP addresses are not permitted - use "localhost" for local development.
//
"RelyingPartyId": null,
//
// Human-readable Relying Party name displayed to users during registration and authentication.
// If null, uses the ApplicationName from configuration.
//
"RelyingPartyName": null,
//
// Allowed origins for origin validation (scheme + domain + port).
// Example: ["https://example.com", "https://www.example.com"]
// If empty, auto-detected from the request.
// Note: IP addresses are not permitted - use "http://localhost:port" for local development.
//
"RelyingPartyOrigins": [],
//
// Post path for adding a passkey to an existing authenticated user (options).
// Post any additional data in the body as JSON (e.g., { "deviceName": "My Phone" }).
// Requires authentication. Set to null to disable this endpoint.
//
"AddPasskeyOptionsPath": "/api/passkey/add/options",
//
// Post path for adding a passkey to an existing authenticated user (completion).
// Post the WebAuthn response data in the body as JSON (challengeId, credentialId, attestationObject, clientDataJSON, transports).
// Additional JSON body fields are userContext passed through to the CompleteAddExistingUserCommand and optional analyticsData.
// Requires authentication. Set to null to disable this endpoint.
//
"AddPasskeyPath": "/api/passkey/add",
//
// Post path for registration options (new user with passkey).
// Post the user registration data the body as JSON (e.g., { "user_name": "...", "user_display_name": "...", "deviceName": "My Phone" }).
// No authentication required. Set to null to disable registration.
//
"RegistrationOptionsPath": "/api/passkey/register/options",
//
// Post path for registration completion (new user with passkey).
// Post the WebAuthn response data in the body as JSON (challengeId, credentialId, attestationObject, clientDataJSON, transports).
// Additional JSON body fields are userContext passed through to the CompleteAddExistingUserCommand and optional analyticsData.
// No authentication required. Set to null to disable registration.
//
"RegistrationPath": "/api/passkey/register",
//
// Post path for the login options endpoint.
// Post the user login data in the body as JSON (e.g., { "user_name": "..." } ).
// Posting the user_name is optional when using discoverable credentials. When discoverable credentials ate not enabled on the authenticator, user_name is required.
//
"LoginOptionsPath": "/api/passkey/login/options",
//
// Post path for the login completion endpoint.
// Post the WebAuthn response data in the body as JSON (challengeId, credentialId, authenticatorData, clientDataJSON, signature, userHandle) and optional analyticsData.
//
"LoginPath": "/api/passkey/login",
//
// Challenge timeout in minutes. Challenges not used within this time will expire.
//
"ChallengeTimeoutMinutes": 5,
//
// User verification requirement:
// - "preferred": Request UV if available, but allow authentication without it
// - "required": Require UV, fail if not available
// - "discouraged": Don't request UV (not recommended for most use cases)
//
// Practical implications:
// - "required": User MUST authenticate with biometric (fingerprint, face) or device PIN.
// High security - proves the person is present, not just possession of the device.
// - "preferred": Browser will request biometric/PIN if available, but allows passkey
// authentication even if UV isn't supported (e.g., older security keys).
// - "discouraged": Just proves device possession, no biometric/PIN prompt. Lower security.
//
// For most apps, use "preferred". For banking/sensitive apps, use "required".
//
"UserVerificationRequirement": "required",
//
// Resident key (discoverable credential) requirement:
// - "preferred": Request discoverable credentials if supported
// - "required": Require discoverable credentials, fail if not supported
// - "discouraged": Request non-discoverable credentials
//
// Practical implications:
// - "required": True passwordless. Browser shows passkey picker with all accounts at login.
// User picks account and authenticates with biometric/PIN. No username input needed.
// - "preferred"/"discouraged": User enters username first, then authenticates with passkey.
//
// For passwordless flows (no username field), set to "required".
//
"ResidentKeyRequirement": "required",
//
// Attestation conveyance preference - controls whether the server requests the authenticator
// to provide cryptographic proof of its identity (make/model) and security properties during registration.
//
// Options:
// - "none": Don't request attestation. Accept any valid authenticator without verifying its identity.
// Best for most apps - simpler, better user privacy, wider device compatibility. (Recommended)
// - "indirect": Request attestation but allow the browser/platform to anonymize it. Rarely useful.
// - "direct": Request full attestation certificate chain from the authenticator.
// Use when you need to verify the authenticator vendor/model meets security requirements.
// - "enterprise": Request enterprise-specific attestation for managed corporate devices
// where IT needs to verify only organization-approved hardware authenticators are used.
//
// When to use non-"none" values:
// - Banking/financial apps requiring hardware security keys only
// - Enterprise environments restricting to specific authenticator models
// - Compliance requirements mandating certain security certifications (FIDO2 L1/L2)
//
// For most consumer applications, "none" is the correct choice - you just want the user
// to authenticate securely, not audit their hardware.
//
"AttestationConveyance": "none",
//
// Whether to validate and update the signature counter (sign count).
// When true, validates that the new sign count is greater than stored, and updates it after authentication.
// When false, skips sign count validation and update entirely.
// Set to false if authenticators don't support it or you want to simplify your database schema.
//
"ValidateSignCount": true,
//
// SQL command to create a challenge when adding a passkey to an existing authenticated user.
// Parameters:
// - $1 = claims (json): JSON object with user claims from the authenticated session
// - $2 = body (json): JSON object from request body (e.g., { "deviceName": "My Phone" })
// Expected return columns (by name):
// - status (int): HTTP status code. Return 200 to proceed, any other status aborts.
// - message (text): Error message when status != 200.
// - challenge (text): Base64-encoded random challenge bytes (typically 32 bytes).
// - challenge_id: Server-side identifier (uuid, int, bigint, or text).
// - user_handle (text): Base64-encoded random bytes (typically 32 bytes) for WebAuthn user.id.
// - user_name (text): Username displayed in the authenticator UI.
// - user_display_name (text): Display name shown in the authenticator UI.
// - exclude_credentials (text): JSON array of existing credentials.
// - user_context (json): Opaque JSON passed through to CompleteAddExistingUserCommand.
// Called by AddPasskeyOptionsPath endpoint
//
"ChallengeAddExistingUserCommand": "select * from passkey_challenge_add_existing($1,$2)",
//
// SQL command to create a challenge for standalone registration (new user).
// Parameter: $1 = JSON object from request body (e.g., { "user_name": "...", "display_name": "..." })
// Expected return columns (by name): Same as ChallengeAddExistingUserCommand
// - user_context should NOT contain "id" field (distinguishes from add-existing-user flow)
// Called by StandaloneRegistrationOptionsPath endpoint
//
"ChallengeRegistrationCommand": "select * from passkey_challenge_registration($1)",
//
// SQL command to create a challenge for authentication.
// Parameters:
// - $1 = user_name (text, optional - null for discoverable credential flow)
// - $2 = body (json): JSON object from request body (e.g., { "deviceInfo": "..." })
// Expected return columns (by name): status, message, challenge, challenge_id, allow_credentials
// Called by AuthenticationOptionsPath endpoint
//
"ChallengeAuthenticationCommand": "select * from passkey_challenge_authentication($1,$2)",
//
// Used by: Flow 1, Flow 2, Flow 3 (ALL flows)
// SQL command to verify and consume a challenge.
// Parameters: $1 = challenge_id (uuid, int, bigint, or text), $2 = operation (text: "registration" or "authentication")
// Returns: challenge (bytea) - the original challenge bytes, or NULL if not found/expired
// Called by all endpoints
//
"VerifyChallengeCommand": "select * from passkey_verify_challenge($1,$2)",
//
// SQL command to get credential data for authentication.
// Parameter: $1 = credential_id (bytea)
// Expected return columns (by name): status, message, public_key, public_key_algorithm, sign_count, user_context
// Note: user_context is passed through to CompleteAuthenticateCommand (typically contains user_id)
// Called by AuthenticatePath endpoint
//
"AuthenticateDataCommand": "select * from passkey_authenticate_data($1)",
//
// SQL command to complete adding a passkey to an existing user account.
// Parameters:
// - $1 = credential_id (bytea): Unique credential identifier from authenticator.
// - $2 = user_handle (bytea): WebAuthn user.id from registration options.
// - $3 = public_key (bytea): Public key in COSE format.
// - $4 = algorithm (int): COSE algorithm identifier (-7 for ES256, -257 for RS256).
// - $5 = transports (text[]): Transport hints (e.g., ["internal", "hybrid"]).
// - $6 = backup_eligible (boolean): Whether credential can be backed up/synced.
// - $7 = user_context (json): Opaque JSON from ChallengeAddExistingUserCommand (contains user ID).
// - $8 = analytics_data (json, optional): Client analytics with server-added IP.
// Expected return columns (by name): status, message
// Called by RegisterPath endpoint
//
"CompleteAddExistingUserCommand": "select * from passkey_complete_add_existing($1,$2,$3,$4,$5,$6,$7,$8)",
//
// SQL command to complete standalone passkey registration (creates new user).
// Parameters: Same as CompleteAddExistingUserCommand
// - user_context should NOT contain "id" field (creates new user instead of linking to existing)
// Expected return columns (by name): status, message
// Called by RegisterPath endpoint
//
"CompleteRegistrationCommand": "select * from passkey_complete_registration($1,$2,$3,$4,$5,$6,$7,$8)",
//
// Flow 3: Login -> AuthenticatePath endpoint (after signature validation)
// SQL command to update sign count and return user claims.
// Parameters:
// - $1 = credential_id (bytea)
// - $2 = new_sign_count (bigint)
// - $3 = user_context (json): Opaque JSON from AuthenticateDataCommand
// - $4 = analytics_data (json, optional): Client analytics with server-added IP
// Expected return columns (by name): status, user_id, user_name, user_roles (plus any custom claims)
// Called by AuthenticatePath endpoint
//
"CompleteAuthenticateCommand": "select * from passkey_complete_authenticate($1,$2,$3,$4)",
//
// The JSON key name used to add the client's IP address to the analytics data server-side.
// Set to null or empty string to disable IP address collection.
//
"ClientAnalyticsIpKey": "ip",
//
// Column name configuration for database responses
//
"StatusColumnName": "status",
"MessageColumnName": "message",
"ChallengeColumnName": "challenge",
"ChallengeIdColumnName": "challenge_id",
"UserNameColumnName": "user_name",
"UserDisplayNameColumnName": "user_display_name",
"UserHandleColumnName": "user_handle",
"ExcludeCredentialsColumnName": "exclude_credentials",
"AllowCredentialsColumnName": "allow_credentials",
"PublicKeyColumnName": "public_key",
"PublicKeyAlgorithmColumnName": "public_key_algorithm",
"SignCountColumnName": "sign_count"
}
},
//
// Serilog settings
//
"Log": {
//
// See https://github.com/serilog/serilog/wiki/Configuration-Basics#minimum-level
// Verbose, Debug, Information, Warning, Error, Fatal.
// Note: NpgsqlRest logger applies to main application logger, which will, by default have the name defined in the ApplicationName setting.
//
"MinimalLevels": {
"NpgsqlRest": "Information",
"NpgsqlRestClient": "Information",
"System": "Warning",
"Microsoft": "Warning"
},
//
// Enable logging to console output.
//
"ToConsole": true,
//
// Minimum log level for console output: Verbose, Debug, Information, Warning, Error, Fatal.
//
"ConsoleMinimumLevel": "Verbose",
//
// Enable logging to file system.
//
"ToFile": false,
//
// File path for log files.
//
"FilePath": "logs/log.txt",
//
// Maximum size limit for log files in bytes before rolling to a new file.
//
"FileSizeLimitBytes": 30000000,
//
// Minimum log level for file output: Verbose, Debug, Information, Warning, Error, Fatal.
//
"FileMinimumLevel": "Verbose",
//
// Maximum number of log files to retain.
//
"RetainedFileCountLimit": 30,
//
// Create a new log file when size limit is reached.
//
"RollOnFileSizeLimit": true,
//
// Enable logging to PostgreSQL database.
//
"ToPostgres": false,
// $1 - log level text, $2 - message text, $3 - timestamp with tz in utc, $4 - exception text or null, $5 - source context
//
// PostgreSQL command to execute for database logging. Parameters: $1=level, $2=message, $3=timestamp, $4=exception, $5=source.
//
"PostgresCommand": "call log($1,$2,$3,$4,$5)",
//
// Minimum log level for PostgreSQL output: Verbose, Debug, Information, Warning, Error, Fatal.
//
"PostgresMinimumLevel": "Verbose",
//
// Enable OpenTelemetry protocol (OTLP) logging output. Requires an OTLP collector endpoint.
//
"ToOpenTelemetry": false,
"OTLPEndpoint": "http://localhost:4317",
"OTLPProtocol": "Grpc", // "Grpc" or "HttpProtobuf"
"OTLResourceAttributes": {
"service.name": "{application}", // application name from the ApplicationName setting
"service.version": "1.0", // application version, set to a static value or use a build process to update it
"service.environment": "{environment}" // environment name from the EnvironmentName setting
},
"OTLPHeaders": {},
"OTLPMinimumLevel": "Verbose",
//
// See https://github.com/serilog/serilog/wiki/Formatting-Output
//
"OutputTemplate": "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj} [{SourceContext}]{NewLine}{Exception}"
},
//
// Response compression settings
//
"ResponseCompression": {
//
// Enable response compression for HTTP responses.
//
"Enabled": false,
//
// Enable response compression for HTTPS responses.
//
"EnableForHttps": false,
//
// Use Brotli compression algorithm when supported by client.
//
"UseBrotli": true,
//
// Use Gzip compression as fallback when Brotli is not supported.
//
"UseGzipFallback": true,
//
// Compression level: Optimal, Fastest, NoCompression, SmallestSize.
//
"CompressionLevel": "Optimal",
//
// MIME types to include for compression.
//
"IncludeMimeTypes": [
"text/plain",
"text/css",
"application/javascript",
"text/javascript",
"text/html",
"application/xml",
"text/xml",
"application/json",
"text/json",
"image/svg+xml",
"font/woff",
"font/woff2",
"application/font-woff",
"application/font-woff2"
],
//
// MIME types to exclude from compression.
//
"ExcludeMimeTypes": []
},
//
// Antiforgery Token Configuration: Protects against Cross-Site Request Forgery (CSRF/XSRF) attacks.
// CSRF attacks occur when a malicious site tricks a user's browser into making unwanted requests to your application
// using the user's authenticated session (cookies).
//
// How it works:
// 1. Server generates a unique token for each session/request
// 2. Token is embedded in forms (hidden field) or sent via header (for AJAX)
// 3. On state-changing requests (POST, PUT, DELETE), server validates the token
// 4. Requests without valid tokens are rejected (400 Bad Request)
//
// Usage in HTML forms:
// <form method="post">
// <input type="hidden" name="__RequestVerificationToken" value="{antiForgeryToken}" />
// ...
// </form>
//
// Usage in AJAX/JavaScript:
// fetch('/api/endpoint', {
// method: 'POST',
// headers: { 'RequestVerificationToken': tokenValue },
// body: JSON.stringify(data)
// });
//
// Note: Antiforgery automatically sets the X-Frame-Options: SAMEORIGIN header to help prevent clickjacking.
// If you're using the SecurityHeaders middleware with X-Frame-Options, the Antiforgery header takes precedence
// (SecurityHeaders will skip X-Frame-Options when Antiforgery is enabled).
//
// Reference: https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery
//
"Antiforgery": {
//
// Enable antiforgery token validation for state-changing requests.
//
"Enabled": false,
//
// Name of the cookie that stores the antiforgery token.
// Set to null to use the ASP.NET Core default (unique per application, starts with ".AspNetCore.Antiforgery.").
// Custom names are useful when running multiple applications on the same domain.
//
"CookieName": null,
//
// Name of the hidden form field that contains the request verification token.
// This must match the name used in your HTML forms.
//
"FormFieldName": "__RequestVerificationToken",
//
// Name of the HTTP header that can contain the antiforgery token.
// Useful for AJAX requests where adding a form field is not possible.
// JavaScript can read the token from a cookie or meta tag and send it in this header.
//
"HeaderName": "RequestVerificationToken",
//
// When true, the server will NOT look for the token in the form body.
// Forces header-only validation - useful for pure API scenarios where all requests use headers.
// When false (default), server checks both form field and header.
//
"SuppressReadingTokenFromFormBody": false,
//
// When true, prevents the automatic X-Frame-Options: SAMEORIGIN header from being set.
// X-Frame-Options helps prevent clickjacking attacks by blocking the page from being embedded in iframes.
// Only set to true if:
// - You need your pages to be embedded in iframes from other origins, OR
// - You're setting X-Frame-Options elsewhere (e.g., in SecurityHeaders or at the proxy level)
// Default: false (header is set for security)
//