@@ -10,6 +10,7 @@ import (
1010 "html"
1111 "html/template"
1212 "net/url"
13+ "slices"
1314 "sort"
1415
1516 "code.gitea.io/gitea/models/auth"
@@ -75,6 +76,10 @@ func (p *AuthSourceProvider) IconHTML(size int) template.HTML {
7576// value is used to store display data
7677var gothProviders = map [string ]GothProvider {}
7778
79+ func isAzureProvider (name string ) bool {
80+ return name == "azuread" || name == "microsoftonline" || name == "azureadv2"
81+ }
82+
7883// RegisterGothProvider registers a GothProvider
7984func RegisterGothProvider (provider GothProvider ) {
8085 if _ , has := gothProviders [provider .Name ()]; has {
@@ -83,13 +88,47 @@ func RegisterGothProvider(provider GothProvider) {
8388 gothProviders [provider .Name ()] = provider
8489}
8590
91+ // getExistingAzureADAuthSources returns a list of Azure AD provider names that are already configured
92+ func getExistingAzureADAuthSources (ctx context.Context ) ([]string , error ) {
93+ authSources , err := db .Find [auth.Source ](ctx , auth.FindSourcesOptions {
94+ LoginType : auth .OAuth2 ,
95+ })
96+ if err != nil {
97+ return nil , err
98+ }
99+
100+ var existingAzureProviders []string
101+ for _ , source := range authSources {
102+ if oauth2Cfg , ok := source .Cfg .(* Source ); ok {
103+ if isAzureProvider (oauth2Cfg .Provider ) {
104+ existingAzureProviders = append (existingAzureProviders , oauth2Cfg .Provider )
105+ }
106+ }
107+ }
108+ return existingAzureProviders , nil
109+ }
110+
86111// GetSupportedOAuth2Providers returns the map of unconfigured OAuth2 providers
87112// key is used as technical name (like in the callbackURL)
88113// values to display
114+ // Note: Azure AD providers (azuread, microsoftonline, azureadv2) are filtered out
115+ // unless they already exist in the system to encourage use of OpenID Connect
89116func GetSupportedOAuth2Providers () []Provider {
117+ return GetSupportedOAuth2ProvidersWithContext (context .Background ())
118+ }
119+
120+ // GetSupportedOAuth2ProvidersWithContext returns the list of supported OAuth2 providers with context for filtering
121+ func GetSupportedOAuth2ProvidersWithContext (ctx context.Context ) []Provider {
90122 providers := make ([]Provider , 0 , len (gothProviders ))
123+ existingAzureSources , err := getExistingAzureADAuthSources (ctx )
124+ if err != nil {
125+ log .Error ("Failed to get existing OAuth2 auth sources: %v" , err )
126+ }
91127
92128 for _ , provider := range gothProviders {
129+ if isAzureProvider (provider .Name ()) && ! slices .Contains (existingAzureSources , provider .Name ()) {
130+ continue
131+ }
93132 providers = append (providers , provider )
94133 }
95134 sort .Slice (providers , func (i , j int ) bool {
0 commit comments