Skip to content

Commit 4d02964

Browse files
feat(auth): introduce EmailOptional config for providers (#4179)
* feat(auth): introduce `EmailOptional` config for providers * chore: add config to template * chore: enable new config in tests --------- Co-authored-by: Qiao Han <[email protected]>
1 parent 1d337c9 commit 4d02964

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

internal/start/start.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ EOF
685685
fmt.Sprintf("GOTRUE_EXTERNAL_%s_CLIENT_ID=%s", strings.ToUpper(name), config.ClientId),
686686
fmt.Sprintf("GOTRUE_EXTERNAL_%s_SECRET=%s", strings.ToUpper(name), config.Secret.Value),
687687
fmt.Sprintf("GOTRUE_EXTERNAL_%s_SKIP_NONCE_CHECK=%t", strings.ToUpper(name), config.SkipNonceCheck),
688+
fmt.Sprintf("GOTRUE_EXTERNAL_%s_EMAIL_OPTIONAL=%t", strings.ToUpper(name), config.EmailOptional),
688689
)
689690

690691
redirectUri := config.RedirectUri

pkg/config/auth.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ type (
354354
Url string `toml:"url"`
355355
RedirectUri string `toml:"redirect_uri"`
356356
SkipNonceCheck bool `toml:"skip_nonce_check"`
357+
EmailOptional bool `toml:"email_optional"`
357358
}
358359

359360
solana struct {
@@ -952,6 +953,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
952953
if len(p.Secret.SHA256) > 0 {
953954
body.ExternalAppleSecret = nullable.NewNullableWithValue(p.Secret.Value)
954955
}
956+
body.ExternalAppleEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
955957
}
956958
}
957959
if p, ok := e["azure"]; ok {
@@ -961,6 +963,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
961963
body.ExternalAzureSecret = nullable.NewNullableWithValue(p.Secret.Value)
962964
}
963965
body.ExternalAzureUrl = nullable.NewNullableWithValue(p.Url)
966+
body.ExternalAzureEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
964967
}
965968
}
966969
if p, ok := e["bitbucket"]; ok {
@@ -969,6 +972,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
969972
if len(p.Secret.SHA256) > 0 {
970973
body.ExternalBitbucketSecret = nullable.NewNullableWithValue(p.Secret.Value)
971974
}
975+
body.ExternalBitbucketEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
972976
}
973977
}
974978
if p, ok := e["discord"]; ok {
@@ -977,6 +981,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
977981
if len(p.Secret.SHA256) > 0 {
978982
body.ExternalDiscordSecret = nullable.NewNullableWithValue(p.Secret.Value)
979983
}
984+
body.ExternalDiscordEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
980985
}
981986
}
982987
if p, ok := e["facebook"]; ok {
@@ -985,6 +990,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
985990
if len(p.Secret.SHA256) > 0 {
986991
body.ExternalFacebookSecret = nullable.NewNullableWithValue(p.Secret.Value)
987992
}
993+
body.ExternalFacebookEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
988994
}
989995
}
990996
if p, ok := e["figma"]; ok {
@@ -993,6 +999,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
993999
if len(p.Secret.SHA256) > 0 {
9941000
body.ExternalFigmaSecret = nullable.NewNullableWithValue(p.Secret.Value)
9951001
}
1002+
body.ExternalFigmaEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
9961003
}
9971004
}
9981005
if p, ok := e["github"]; ok {
@@ -1001,6 +1008,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10011008
if len(p.Secret.SHA256) > 0 {
10021009
body.ExternalGithubSecret = nullable.NewNullableWithValue(p.Secret.Value)
10031010
}
1011+
body.ExternalGithubEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10041012
}
10051013
}
10061014
if p, ok := e["gitlab"]; ok {
@@ -1010,6 +1018,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10101018
body.ExternalGitlabSecret = nullable.NewNullableWithValue(p.Secret.Value)
10111019
}
10121020
body.ExternalGitlabUrl = nullable.NewNullableWithValue(p.Url)
1021+
body.ExternalGitlabEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10131022
}
10141023
}
10151024
if p, ok := e["google"]; ok {
@@ -1019,6 +1028,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10191028
body.ExternalGoogleSecret = nullable.NewNullableWithValue(p.Secret.Value)
10201029
}
10211030
body.ExternalGoogleSkipNonceCheck = nullable.NewNullableWithValue(p.SkipNonceCheck)
1031+
body.ExternalGoogleEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10221032
}
10231033
}
10241034
if p, ok := e["kakao"]; ok {
@@ -1027,6 +1037,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10271037
if len(p.Secret.SHA256) > 0 {
10281038
body.ExternalKakaoSecret = nullable.NewNullableWithValue(p.Secret.Value)
10291039
}
1040+
body.ExternalKakaoEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10301041
}
10311042
}
10321043
if p, ok := e["keycloak"]; ok {
@@ -1036,6 +1047,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10361047
body.ExternalKeycloakSecret = nullable.NewNullableWithValue(p.Secret.Value)
10371048
}
10381049
body.ExternalKeycloakUrl = nullable.NewNullableWithValue(p.Url)
1050+
body.ExternalKeycloakEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10391051
}
10401052
}
10411053
if p, ok := e["linkedin_oidc"]; ok {
@@ -1044,6 +1056,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10441056
if len(p.Secret.SHA256) > 0 {
10451057
body.ExternalLinkedinOidcSecret = nullable.NewNullableWithValue(p.Secret.Value)
10461058
}
1059+
body.ExternalLinkedinOidcEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10471060
}
10481061
}
10491062
if p, ok := e["notion"]; ok {
@@ -1052,6 +1065,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10521065
if len(p.Secret.SHA256) > 0 {
10531066
body.ExternalNotionSecret = nullable.NewNullableWithValue(p.Secret.Value)
10541067
}
1068+
body.ExternalNotionEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10551069
}
10561070
}
10571071
if p, ok := e["slack_oidc"]; ok {
@@ -1060,6 +1074,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10601074
if len(p.Secret.SHA256) > 0 {
10611075
body.ExternalSlackOidcSecret = nullable.NewNullableWithValue(p.Secret.Value)
10621076
}
1077+
body.ExternalSlackOidcEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10631078
}
10641079
}
10651080
if p, ok := e["spotify"]; ok {
@@ -1068,6 +1083,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10681083
if len(p.Secret.SHA256) > 0 {
10691084
body.ExternalSpotifySecret = nullable.NewNullableWithValue(p.Secret.Value)
10701085
}
1086+
body.ExternalSpotifyEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10711087
}
10721088
}
10731089
if p, ok := e["twitch"]; ok {
@@ -1076,6 +1092,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10761092
if len(p.Secret.SHA256) > 0 {
10771093
body.ExternalTwitchSecret = nullable.NewNullableWithValue(p.Secret.Value)
10781094
}
1095+
body.ExternalTwitchEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10791096
}
10801097
}
10811098
if p, ok := e["twitter"]; ok {
@@ -1084,6 +1101,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
10841101
if len(p.Secret.SHA256) > 0 {
10851102
body.ExternalTwitterSecret = nullable.NewNullableWithValue(p.Secret.Value)
10861103
}
1104+
body.ExternalTwitterEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
10871105
}
10881106
}
10891107
if p, ok := e["workos"]; ok {
@@ -1101,6 +1119,7 @@ func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
11011119
if len(p.Secret.SHA256) > 0 {
11021120
body.ExternalZoomSecret = nullable.NewNullableWithValue(p.Secret.Value)
11031121
}
1122+
body.ExternalZoomEmailOptional = nullable.NewNullableWithValue(p.EmailOptional)
11041123
}
11051124
}
11061125
}
@@ -1119,6 +1138,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
11191138
if len(p.Secret.SHA256) > 0 {
11201139
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalAppleSecret, "")
11211140
}
1141+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalAppleEmailOptional, false)
11221142
}
11231143
p.Enabled = ValOrDefault(remoteConfig.ExternalAppleEnabled, false)
11241144
e["apple"] = p
@@ -1131,6 +1151,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
11311151
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalAzureSecret, "")
11321152
}
11331153
p.Url = ValOrDefault(remoteConfig.ExternalAzureUrl, "")
1154+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalAzureEmailOptional, false)
11341155
}
11351156
p.Enabled = ValOrDefault(remoteConfig.ExternalAzureEnabled, false)
11361157
e["azure"] = p
@@ -1142,6 +1163,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
11421163
if len(p.Secret.SHA256) > 0 {
11431164
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalBitbucketSecret, "")
11441165
}
1166+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalBitbucketEmailOptional, false)
11451167
}
11461168
p.Enabled = ValOrDefault(remoteConfig.ExternalBitbucketEnabled, false)
11471169
e["bitbucket"] = p
@@ -1153,6 +1175,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
11531175
if len(p.Secret.SHA256) > 0 {
11541176
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalDiscordSecret, "")
11551177
}
1178+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalDiscordEmailOptional, false)
11561179
}
11571180
p.Enabled = ValOrDefault(remoteConfig.ExternalDiscordEnabled, false)
11581181
e["discord"] = p
@@ -1164,6 +1187,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
11641187
if len(p.Secret.SHA256) > 0 {
11651188
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalFacebookSecret, "")
11661189
}
1190+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalFacebookEmailOptional, false)
11671191
}
11681192
p.Enabled = ValOrDefault(remoteConfig.ExternalFacebookEnabled, false)
11691193
e["facebook"] = p
@@ -1175,6 +1199,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
11751199
if len(p.Secret.SHA256) > 0 {
11761200
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalFigmaSecret, "")
11771201
}
1202+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalFigmaEmailOptional, false)
11781203
}
11791204
p.Enabled = ValOrDefault(remoteConfig.ExternalFigmaEnabled, false)
11801205
e["figma"] = p
@@ -1186,6 +1211,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
11861211
if len(p.Secret.SHA256) > 0 {
11871212
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalGithubSecret, "")
11881213
}
1214+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalGithubEmailOptional, false)
11891215
}
11901216
p.Enabled = ValOrDefault(remoteConfig.ExternalGithubEnabled, false)
11911217
e["github"] = p
@@ -1198,6 +1224,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
11981224
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalGitlabSecret, "")
11991225
}
12001226
p.Url = ValOrDefault(remoteConfig.ExternalGitlabUrl, "")
1227+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalGitlabEmailOptional, false)
12011228
}
12021229
p.Enabled = ValOrDefault(remoteConfig.ExternalGitlabEnabled, false)
12031230
e["gitlab"] = p
@@ -1213,6 +1240,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
12131240
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalGoogleSecret, "")
12141241
}
12151242
p.SkipNonceCheck = ValOrDefault(remoteConfig.ExternalGoogleSkipNonceCheck, false)
1243+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalGoogleEmailOptional, false)
12161244
}
12171245
p.Enabled = ValOrDefault(remoteConfig.ExternalGoogleEnabled, false)
12181246
e["google"] = p
@@ -1224,6 +1252,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
12241252
if len(p.Secret.SHA256) > 0 {
12251253
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalKakaoSecret, "")
12261254
}
1255+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalKakaoEmailOptional, false)
12271256
}
12281257
p.Enabled = ValOrDefault(remoteConfig.ExternalKakaoEnabled, false)
12291258
e["kakao"] = p
@@ -1236,6 +1265,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
12361265
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalKeycloakSecret, "")
12371266
}
12381267
p.Url = ValOrDefault(remoteConfig.ExternalKeycloakUrl, "")
1268+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalKeycloakEmailOptional, false)
12391269
}
12401270
p.Enabled = ValOrDefault(remoteConfig.ExternalKeycloakEnabled, false)
12411271
e["keycloak"] = p
@@ -1247,6 +1277,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
12471277
if len(p.Secret.SHA256) > 0 {
12481278
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalLinkedinOidcSecret, "")
12491279
}
1280+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalLinkedinOidcEmailOptional, false)
12501281
}
12511282
p.Enabled = ValOrDefault(remoteConfig.ExternalLinkedinOidcEnabled, false)
12521283
e["linkedin_oidc"] = p
@@ -1258,6 +1289,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
12581289
if len(p.Secret.SHA256) > 0 {
12591290
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalNotionSecret, "")
12601291
}
1292+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalNotionEmailOptional, false)
12611293
}
12621294
p.Enabled = ValOrDefault(remoteConfig.ExternalNotionEnabled, false)
12631295
e["notion"] = p
@@ -1269,6 +1301,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
12691301
if len(p.Secret.SHA256) > 0 {
12701302
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalSlackOidcSecret, "")
12711303
}
1304+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalSlackOidcEmailOptional, false)
12721305
}
12731306
p.Enabled = ValOrDefault(remoteConfig.ExternalSlackOidcEnabled, false)
12741307
e["slack_oidc"] = p
@@ -1280,6 +1313,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
12801313
if len(p.Secret.SHA256) > 0 {
12811314
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalSpotifySecret, "")
12821315
}
1316+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalSpotifyEmailOptional, false)
12831317
}
12841318
p.Enabled = ValOrDefault(remoteConfig.ExternalSpotifyEnabled, false)
12851319
e["spotify"] = p
@@ -1291,6 +1325,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
12911325
if len(p.Secret.SHA256) > 0 {
12921326
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalTwitchSecret, "")
12931327
}
1328+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalTwitchEmailOptional, false)
12941329
}
12951330
p.Enabled = ValOrDefault(remoteConfig.ExternalTwitchEnabled, false)
12961331
e["twitch"] = p
@@ -1302,6 +1337,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
13021337
if len(p.Secret.SHA256) > 0 {
13031338
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalTwitterSecret, "")
13041339
}
1340+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalTwitterEmailOptional, false)
13051341
}
13061342
p.Enabled = ValOrDefault(remoteConfig.ExternalTwitterEnabled, false)
13071343
e["twitter"] = p
@@ -1325,6 +1361,7 @@ func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
13251361
if len(p.Secret.SHA256) > 0 {
13261362
p.Secret.SHA256 = ValOrDefault(remoteConfig.ExternalZoomSecret, "")
13271363
}
1364+
p.EmailOptional = ValOrDefault(remoteConfig.ExternalZoomEmailOptional, false)
13281365
}
13291366
p.Enabled = ValOrDefault(remoteConfig.ExternalZoomEnabled, false)
13301367
e["zoom"] = p

pkg/config/templates/config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,8 @@ redirect_uri = ""
275275
url = ""
276276
# If enabled, the nonce check will be skipped. Required for local sign in with Google auth.
277277
skip_nonce_check = false
278+
# If enabled, it will allow the user to successfully authenticate when the provider does not return an email address.
279+
email_optional = false
278280

279281
# Allow Solana wallet holders to sign in to your project via the Sign in with Solana (SIWS, EIP-4361) standard.
280282
# You can configure "web3" rate limit in the [auth.rate_limit] section and set up [auth.captcha] if self-hosting.

pkg/config/testdata/config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ secret = "env(AZURE_SECRET)"
285285
url = "https://login.microsoftonline.com/tenant"
286286
# If enabled, the nonce check will be skipped. Required for local sign in with Google auth.
287287
skip_nonce_check = true
288+
# If enabled, it will allow the user to successfully authenticate when the provider does not return an email address.
289+
email_optional = true
288290

289291
# Allow Solana wallet holders to sign in to your project via the Sign in with Solana (SIWS, EIP-4361) standard.
290292
# You can configure "web3" rate limit in the [auth.rate_limit] section and set up [auth.captcha] if self-hosting.

0 commit comments

Comments
 (0)