From ebb8c93eb1fa2d3e84fcc3f8788d7adffd8df97a Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 13 Aug 2025 16:04:11 -0400 Subject: [PATCH 1/6] Remove deprecated auth sources Entra ID users should use the OIDC oauth2 provider --- routers/web/admin/auths.go | 8 +++-- services/auth/source/oauth2/providers.go | 42 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go index 56c384b97097a..60ca7f0048efb 100644 --- a/routers/web/admin/auths.go +++ b/routers/web/admin/auths.go @@ -97,7 +97,7 @@ func NewAuthSource(ctx *context.Context) { ctx.Data["AuthSources"] = authSources ctx.Data["SecurityProtocols"] = securityProtocols ctx.Data["SMTPAuths"] = smtp.Authenticators - oauth2providers := oauth2.GetSupportedOAuth2Providers() + oauth2providers := oauth2.GetSupportedOAuth2ProvidersWithContext(ctx) ctx.Data["OAuth2Providers"] = oauth2providers ctx.Data["SSPIAutoCreateUsers"] = true @@ -107,7 +107,9 @@ func NewAuthSource(ctx *context.Context) { ctx.Data["SSPIDefaultLanguage"] = "" // only the first as default - ctx.Data["oauth2_provider"] = oauth2providers[0].Name() + if len(oauth2providers) > 0 { + ctx.Data["oauth2_provider"] = oauth2providers[0].Name() + } ctx.HTML(http.StatusOK, tplAuthNew) } @@ -240,7 +242,7 @@ func NewAuthSourcePost(ctx *context.Context) { ctx.Data["AuthSources"] = authSources ctx.Data["SecurityProtocols"] = securityProtocols ctx.Data["SMTPAuths"] = smtp.Authenticators - oauth2providers := oauth2.GetSupportedOAuth2Providers() + oauth2providers := oauth2.GetSupportedOAuth2ProvidersWithContext(ctx) ctx.Data["OAuth2Providers"] = oauth2providers ctx.Data["SSPIAutoCreateUsers"] = true diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index 75ed41ba66896..cebf2fb6a878c 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -83,13 +83,55 @@ func RegisterGothProvider(provider GothProvider) { gothProviders[provider.Name()] = provider } +// hasExistingAzureADAuthSources checks if there are any existing Azure AD auth sources configured +func hasExistingAzureADAuthSources(ctx context.Context) bool { + azureProviders := map[string]bool{ + "azuread": true, + "microsoftonline": true, + "azureadv2": true, + } + + authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ + LoginType: auth.OAuth2, + }) + if err != nil { + return false + } + + for _, source := range authSources { + if oauth2Cfg, ok := source.Cfg.(*Source); ok { + if azureProviders[oauth2Cfg.Provider] { + return true + } + } + } + return false +} + // GetSupportedOAuth2Providers returns the map of unconfigured OAuth2 providers // key is used as technical name (like in the callbackURL) // values to display +// Note: Azure AD providers (azuread, microsoftonline, azureadv2) are filtered out +// unless they already exist in the system to encourage use of OpenID Connect func GetSupportedOAuth2Providers() []Provider { + return GetSupportedOAuth2ProvidersWithContext(context.Background()) +} + +// GetSupportedOAuth2ProvidersWithContext returns the list of supported OAuth2 providers with context for filtering +func GetSupportedOAuth2ProvidersWithContext(ctx context.Context) []Provider { providers := make([]Provider, 0, len(gothProviders)) + hasExistingAzure := hasExistingAzureADAuthSources(ctx) + + azureProviders := map[string]bool{ + "azuread": true, + "microsoftonline": true, + "azureadv2": true, + } for _, provider := range gothProviders { + if azureProviders[provider.Name()] && !hasExistingAzure { + continue + } providers = append(providers, provider) } sort.Slice(providers, func(i, j int) bool { From 931044c38f289cc9e5698b707f41ef91394989f5 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Fri, 15 Aug 2025 14:15:36 -0400 Subject: [PATCH 2/6] reduce duplication --- services/auth/source/oauth2/providers.go | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index cebf2fb6a878c..0bfc7c4ba2702 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -75,6 +75,12 @@ func (p *AuthSourceProvider) IconHTML(size int) template.HTML { // value is used to store display data var gothProviders = map[string]GothProvider{} +var azureProviders = map[string]bool{ + "azuread": true, + "microsoftonline": true, + "azureadv2": true, +} + // RegisterGothProvider registers a GothProvider func RegisterGothProvider(provider GothProvider) { if _, has := gothProviders[provider.Name()]; has { @@ -85,12 +91,6 @@ func RegisterGothProvider(provider GothProvider) { // hasExistingAzureADAuthSources checks if there are any existing Azure AD auth sources configured func hasExistingAzureADAuthSources(ctx context.Context) bool { - azureProviders := map[string]bool{ - "azuread": true, - "microsoftonline": true, - "azureadv2": true, - } - authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ LoginType: auth.OAuth2, }) @@ -122,12 +122,6 @@ func GetSupportedOAuth2ProvidersWithContext(ctx context.Context) []Provider { providers := make([]Provider, 0, len(gothProviders)) hasExistingAzure := hasExistingAzureADAuthSources(ctx) - azureProviders := map[string]bool{ - "azuread": true, - "microsoftonline": true, - "azureadv2": true, - } - for _, provider := range gothProviders { if azureProviders[provider.Name()] && !hasExistingAzure { continue From 6d34f626bac04931d3920c1141cd5d3334cf1385 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Sun, 17 Aug 2025 19:20:46 -0400 Subject: [PATCH 3/6] dont use map per feedback --- services/auth/source/oauth2/providers.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index 0bfc7c4ba2702..b385835a13f98 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -75,10 +75,19 @@ func (p *AuthSourceProvider) IconHTML(size int) template.HTML { // value is used to store display data var gothProviders = map[string]GothProvider{} -var azureProviders = map[string]bool{ - "azuread": true, - "microsoftonline": true, - "azureadv2": true, +var azureProviders = []string{ + "azuread", + "microsoftonline", + "azureadv2", +} + +func isAzureProvider(providerName string) bool { + for _, azureProvider := range azureProviders { + if providerName == azureProvider { + return true + } + } + return false } // RegisterGothProvider registers a GothProvider @@ -100,7 +109,7 @@ func hasExistingAzureADAuthSources(ctx context.Context) bool { for _, source := range authSources { if oauth2Cfg, ok := source.Cfg.(*Source); ok { - if azureProviders[oauth2Cfg.Provider] { + if isAzureProvider(oauth2Cfg.Provider) { return true } } @@ -123,7 +132,7 @@ func GetSupportedOAuth2ProvidersWithContext(ctx context.Context) []Provider { hasExistingAzure := hasExistingAzureADAuthSources(ctx) for _, provider := range gothProviders { - if azureProviders[provider.Name()] && !hasExistingAzure { + if isAzureProvider(provider.Name()) && !hasExistingAzure { continue } providers = append(providers, provider) From c9feca8bbb395404bcef2d5c82c16d4a67d3d9dd Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Sun, 17 Aug 2025 22:19:29 -0400 Subject: [PATCH 4/6] fix lint --- services/auth/source/oauth2/providers.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index b385835a13f98..009e6d32e0436 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -10,6 +10,7 @@ import ( "html" "html/template" "net/url" + "slices" "sort" "code.gitea.io/gitea/models/auth" @@ -82,12 +83,7 @@ var azureProviders = []string{ } func isAzureProvider(providerName string) bool { - for _, azureProvider := range azureProviders { - if providerName == azureProvider { - return true - } - } - return false + return slices.Contains(azureProviders, providerName) } // RegisterGothProvider registers a GothProvider From 8d9790b27f3cace1b22f3c05d4ebc8c6791cf6b4 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Mon, 18 Aug 2025 10:27:27 -0400 Subject: [PATCH 5/6] more specific --- services/auth/source/oauth2/providers.go | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index 009e6d32e0436..50a76740e8dac 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -82,10 +82,6 @@ var azureProviders = []string{ "azureadv2", } -func isAzureProvider(providerName string) bool { - return slices.Contains(azureProviders, providerName) -} - // RegisterGothProvider registers a GothProvider func RegisterGothProvider(provider GothProvider) { if _, has := gothProviders[provider.Name()]; has { @@ -94,23 +90,24 @@ func RegisterGothProvider(provider GothProvider) { gothProviders[provider.Name()] = provider } -// hasExistingAzureADAuthSources checks if there are any existing Azure AD auth sources configured -func hasExistingAzureADAuthSources(ctx context.Context) bool { +// getExistingAzureADAuthSources returns a list of Azure AD provider names that are already configured +func getExistingAzureADAuthSources(ctx context.Context) []string { authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ LoginType: auth.OAuth2, }) if err != nil { - return false + return nil } + var existingAzureProviders []string for _, source := range authSources { if oauth2Cfg, ok := source.Cfg.(*Source); ok { - if isAzureProvider(oauth2Cfg.Provider) { - return true + if slices.Contains(azureProviders, oauth2Cfg.Provider) { + existingAzureProviders = append(existingAzureProviders, oauth2Cfg.Provider) } } } - return false + return existingAzureProviders } // GetSupportedOAuth2Providers returns the map of unconfigured OAuth2 providers @@ -125,10 +122,10 @@ func GetSupportedOAuth2Providers() []Provider { // GetSupportedOAuth2ProvidersWithContext returns the list of supported OAuth2 providers with context for filtering func GetSupportedOAuth2ProvidersWithContext(ctx context.Context) []Provider { providers := make([]Provider, 0, len(gothProviders)) - hasExistingAzure := hasExistingAzureADAuthSources(ctx) + existAuthSources := getExistingAzureADAuthSources(ctx) for _, provider := range gothProviders { - if isAzureProvider(provider.Name()) && !hasExistingAzure { + if slices.Contains(azureProviders, provider.Name()) && !slices.Contains(existAuthSources, provider.Name()) { continue } providers = append(providers, provider) From 2847ed3864cf0c3e12f532aaedddcfc95bb39552 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 23 Aug 2025 11:37:59 -0700 Subject: [PATCH 6/6] some improvements --- services/auth/source/oauth2/providers.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index 50a76740e8dac..c97b8c8e1c89a 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -76,10 +76,8 @@ func (p *AuthSourceProvider) IconHTML(size int) template.HTML { // value is used to store display data var gothProviders = map[string]GothProvider{} -var azureProviders = []string{ - "azuread", - "microsoftonline", - "azureadv2", +func isAzureProvider(name string) bool { + return name == "azuread" || name == "microsoftonline" || name == "azureadv2" } // RegisterGothProvider registers a GothProvider @@ -91,23 +89,23 @@ func RegisterGothProvider(provider GothProvider) { } // getExistingAzureADAuthSources returns a list of Azure AD provider names that are already configured -func getExistingAzureADAuthSources(ctx context.Context) []string { +func getExistingAzureADAuthSources(ctx context.Context) ([]string, error) { authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ LoginType: auth.OAuth2, }) if err != nil { - return nil + return nil, err } var existingAzureProviders []string for _, source := range authSources { if oauth2Cfg, ok := source.Cfg.(*Source); ok { - if slices.Contains(azureProviders, oauth2Cfg.Provider) { + if isAzureProvider(oauth2Cfg.Provider) { existingAzureProviders = append(existingAzureProviders, oauth2Cfg.Provider) } } } - return existingAzureProviders + return existingAzureProviders, nil } // GetSupportedOAuth2Providers returns the map of unconfigured OAuth2 providers @@ -122,10 +120,13 @@ func GetSupportedOAuth2Providers() []Provider { // GetSupportedOAuth2ProvidersWithContext returns the list of supported OAuth2 providers with context for filtering func GetSupportedOAuth2ProvidersWithContext(ctx context.Context) []Provider { providers := make([]Provider, 0, len(gothProviders)) - existAuthSources := getExistingAzureADAuthSources(ctx) + existingAzureSources, err := getExistingAzureADAuthSources(ctx) + if err != nil { + log.Error("Failed to get existing OAuth2 auth sources: %v", err) + } for _, provider := range gothProviders { - if slices.Contains(azureProviders, provider.Name()) && !slices.Contains(existAuthSources, provider.Name()) { + if isAzureProvider(provider.Name()) && !slices.Contains(existingAzureSources, provider.Name()) { continue } providers = append(providers, provider)