Add microsoft oauth2 providers (#16544)
* Clean up oauth2 providers Signed-off-by: Andrew Thornton <art27@cantab.net> * Add AzureAD, AzureADv2, MicrosoftOnline OAuth2 providers Signed-off-by: Andrew Thornton <art27@cantab.net> * Apply suggestions from code review * remove unused Scopes Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
		
					parent
					
						
							
								7e7006e00d
							
						
					
				
			
			
				commit
				
					
						ab9bb54144
					
				
			
		
					 29 changed files with 2132 additions and 260 deletions
				
			
		
							
								
								
									
										1
									
								
								go.sum
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								go.sum
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -762,6 +762,7 @@ github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7
 | 
			
		|||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 | 
			
		||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 | 
			
		||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 | 
			
		||||
github.com/markbates/going v1.0.0 h1:DQw0ZP7NbNlFGcKbcE/IVSOAFzScxRtLpd0rLMzLhq0=
 | 
			
		||||
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
 | 
			
		||||
github.com/markbates/goth v1.68.0 h1:90sKvjRAKHcl9V2uC9x/PJXeD78cFPiBsyP1xVhoQfA=
 | 
			
		||||
github.com/markbates/goth v1.68.0/go.mod h1:V2VcDMzDiMHW+YmqYl7i0cMiAUeCkAe4QE6jRKBhXZw=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2441,6 +2441,7 @@ auths.oauth2_tokenURL = Token URL
 | 
			
		|||
auths.oauth2_authURL = Authorize URL
 | 
			
		||||
auths.oauth2_profileURL = Profile URL
 | 
			
		||||
auths.oauth2_emailURL = Email URL
 | 
			
		||||
auths.oauth2_tenant = Tenant
 | 
			
		||||
auths.enable_auto_register = Enable Auto Registration
 | 
			
		||||
auths.sspi_auto_create_users = Automatically create users
 | 
			
		||||
auths.sspi_auto_create_users_helper = Allow SSPI auth method to automatically create new accounts for users that login for the first time
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								public/img/auth/azuread.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/img/auth/azuread.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/img/auth/azureadv2.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/img/auth/azureadv2.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/img/auth/microsoftonline.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/img/auth/microsoftonline.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 792 B  | 
| 
						 | 
				
			
			@ -98,8 +98,8 @@ func NewAuthSource(ctx *context.Context) {
 | 
			
		|||
	ctx.Data["AuthSources"] = authSources
 | 
			
		||||
	ctx.Data["SecurityProtocols"] = securityProtocols
 | 
			
		||||
	ctx.Data["SMTPAuths"] = smtp.Authenticators
 | 
			
		||||
	ctx.Data["OAuth2Providers"] = oauth2.Providers
 | 
			
		||||
	ctx.Data["OAuth2DefaultCustomURLMappings"] = oauth2.DefaultCustomURLMappings
 | 
			
		||||
	oauth2providers := oauth2.GetOAuth2Providers()
 | 
			
		||||
	ctx.Data["OAuth2Providers"] = oauth2providers
 | 
			
		||||
 | 
			
		||||
	ctx.Data["SSPIAutoCreateUsers"] = true
 | 
			
		||||
	ctx.Data["SSPIAutoActivateUsers"] = true
 | 
			
		||||
| 
						 | 
				
			
			@ -108,10 +108,7 @@ func NewAuthSource(ctx *context.Context) {
 | 
			
		|||
	ctx.Data["SSPIDefaultLanguage"] = ""
 | 
			
		||||
 | 
			
		||||
	// only the first as default
 | 
			
		||||
	for key := range oauth2.Providers {
 | 
			
		||||
		ctx.Data["oauth2_provider"] = key
 | 
			
		||||
		break
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["oauth2_provider"] = oauth2providers[0]
 | 
			
		||||
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplAuthNew)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -170,6 +167,7 @@ func parseOAuth2Config(form forms.AuthenticationForm) *oauth2.Source {
 | 
			
		|||
			AuthURL:    form.Oauth2AuthURL,
 | 
			
		||||
			ProfileURL: form.Oauth2ProfileURL,
 | 
			
		||||
			EmailURL:   form.Oauth2EmailURL,
 | 
			
		||||
			Tenant:     form.Oauth2Tenant,
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		customURLMapping = nil
 | 
			
		||||
| 
						 | 
				
			
			@ -220,8 +218,8 @@ func NewAuthSourcePost(ctx *context.Context) {
 | 
			
		|||
	ctx.Data["AuthSources"] = authSources
 | 
			
		||||
	ctx.Data["SecurityProtocols"] = securityProtocols
 | 
			
		||||
	ctx.Data["SMTPAuths"] = smtp.Authenticators
 | 
			
		||||
	ctx.Data["OAuth2Providers"] = oauth2.Providers
 | 
			
		||||
	ctx.Data["OAuth2DefaultCustomURLMappings"] = oauth2.DefaultCustomURLMappings
 | 
			
		||||
	oauth2providers := oauth2.GetOAuth2Providers()
 | 
			
		||||
	ctx.Data["OAuth2Providers"] = oauth2providers
 | 
			
		||||
 | 
			
		||||
	ctx.Data["SSPIAutoCreateUsers"] = true
 | 
			
		||||
	ctx.Data["SSPIAutoActivateUsers"] = true
 | 
			
		||||
| 
						 | 
				
			
			@ -299,8 +297,8 @@ func EditAuthSource(ctx *context.Context) {
 | 
			
		|||
 | 
			
		||||
	ctx.Data["SecurityProtocols"] = securityProtocols
 | 
			
		||||
	ctx.Data["SMTPAuths"] = smtp.Authenticators
 | 
			
		||||
	ctx.Data["OAuth2Providers"] = oauth2.Providers
 | 
			
		||||
	ctx.Data["OAuth2DefaultCustomURLMappings"] = oauth2.DefaultCustomURLMappings
 | 
			
		||||
	oauth2providers := oauth2.GetOAuth2Providers()
 | 
			
		||||
	ctx.Data["OAuth2Providers"] = oauth2providers
 | 
			
		||||
 | 
			
		||||
	source, err := models.GetLoginSourceByID(ctx.ParamsInt64(":authid"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -311,7 +309,17 @@ func EditAuthSource(ctx *context.Context) {
 | 
			
		|||
	ctx.Data["HasTLS"] = source.HasTLS()
 | 
			
		||||
 | 
			
		||||
	if source.IsOAuth2() {
 | 
			
		||||
		ctx.Data["CurrentOAuth2Provider"] = oauth2.Providers[source.Cfg.(*oauth2.Source).Provider]
 | 
			
		||||
		type Named interface {
 | 
			
		||||
			Name() string
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, provider := range oauth2providers {
 | 
			
		||||
			if provider.Name() == source.Cfg.(Named).Name() {
 | 
			
		||||
				ctx.Data["CurrentOAuth2Provider"] = provider
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplAuthEdit)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -324,8 +332,8 @@ func EditAuthSourcePost(ctx *context.Context) {
 | 
			
		|||
	ctx.Data["PageIsAdminAuthentications"] = true
 | 
			
		||||
 | 
			
		||||
	ctx.Data["SMTPAuths"] = smtp.Authenticators
 | 
			
		||||
	ctx.Data["OAuth2Providers"] = oauth2.Providers
 | 
			
		||||
	ctx.Data["OAuth2DefaultCustomURLMappings"] = oauth2.DefaultCustomURLMappings
 | 
			
		||||
	oauth2providers := oauth2.GetOAuth2Providers()
 | 
			
		||||
	ctx.Data["OAuth2Providers"] = oauth2providers
 | 
			
		||||
 | 
			
		||||
	source, err := models.GetLoginSourceByID(ctx.ParamsInt64(":authid"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,6 @@ import (
 | 
			
		|||
	"code.gitea.io/gitea/modules/base"
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/services/auth/source/oauth2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
| 
						 | 
				
			
			@ -92,9 +91,19 @@ func loadSecurityData(ctx *context.Context) {
 | 
			
		|||
	for _, externalAccount := range accountLinks {
 | 
			
		||||
		if loginSource, err := models.GetLoginSourceByID(externalAccount.LoginSourceID); err == nil {
 | 
			
		||||
			var providerDisplayName string
 | 
			
		||||
			if loginSource.IsOAuth2() {
 | 
			
		||||
				providerTechnicalName := loginSource.Cfg.(*oauth2.Source).Provider
 | 
			
		||||
				providerDisplayName = oauth2.Providers[providerTechnicalName].DisplayName
 | 
			
		||||
 | 
			
		||||
			type DisplayNamed interface {
 | 
			
		||||
				DisplayName() string
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			type Named interface {
 | 
			
		||||
				Name() string
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if displayNamed, ok := loginSource.Cfg.(DisplayNamed); ok {
 | 
			
		||||
				providerDisplayName = displayNamed.DisplayName()
 | 
			
		||||
			} else if named, ok := loginSource.Cfg.(Named); ok {
 | 
			
		||||
				providerDisplayName = named.Name()
 | 
			
		||||
			} else {
 | 
			
		||||
				providerDisplayName = loginSource.Name
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,80 +13,72 @@ import (
 | 
			
		|||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
	"github.com/markbates/goth/providers/bitbucket"
 | 
			
		||||
	"github.com/markbates/goth/providers/discord"
 | 
			
		||||
	"github.com/markbates/goth/providers/dropbox"
 | 
			
		||||
	"github.com/markbates/goth/providers/facebook"
 | 
			
		||||
	"github.com/markbates/goth/providers/gitea"
 | 
			
		||||
	"github.com/markbates/goth/providers/github"
 | 
			
		||||
	"github.com/markbates/goth/providers/gitlab"
 | 
			
		||||
	"github.com/markbates/goth/providers/google"
 | 
			
		||||
	"github.com/markbates/goth/providers/mastodon"
 | 
			
		||||
	"github.com/markbates/goth/providers/nextcloud"
 | 
			
		||||
	"github.com/markbates/goth/providers/openidConnect"
 | 
			
		||||
	"github.com/markbates/goth/providers/twitter"
 | 
			
		||||
	"github.com/markbates/goth/providers/yandex"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Provider describes the display values of a single OAuth2 provider
 | 
			
		||||
type Provider struct {
 | 
			
		||||
	Name             string
 | 
			
		||||
	DisplayName      string
 | 
			
		||||
	Image            string
 | 
			
		||||
	CustomURLMapping *CustomURLMapping
 | 
			
		||||
// Provider is an interface for describing a single OAuth2 provider
 | 
			
		||||
type Provider interface {
 | 
			
		||||
	Name() string
 | 
			
		||||
	DisplayName() string
 | 
			
		||||
	Image() string
 | 
			
		||||
	CustomURLSettings() *CustomURLSettings
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GothProviderCreator provides a function to create a goth.Provider
 | 
			
		||||
type GothProviderCreator interface {
 | 
			
		||||
	CreateGothProvider(providerName, callbackURL string, source *Source) (goth.Provider, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GothProvider is an interface for describing a single OAuth2 provider
 | 
			
		||||
type GothProvider interface {
 | 
			
		||||
	Provider
 | 
			
		||||
	GothProviderCreator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ImagedProvider provide an overrided image setting for the provider
 | 
			
		||||
type ImagedProvider struct {
 | 
			
		||||
	GothProvider
 | 
			
		||||
	image string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Image returns the image path for this provider
 | 
			
		||||
func (i *ImagedProvider) Image() string {
 | 
			
		||||
	return i.image
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewImagedProvider is a constructor function for the ImagedProvider
 | 
			
		||||
func NewImagedProvider(image string, provider GothProvider) *ImagedProvider {
 | 
			
		||||
	return &ImagedProvider{
 | 
			
		||||
		GothProvider: provider,
 | 
			
		||||
		image:        image,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Providers contains the map of registered OAuth2 providers in Gitea (based on goth)
 | 
			
		||||
// key is used to map the OAuth2Provider with the goth provider type (also in LoginSource.OAuth2Config.Provider)
 | 
			
		||||
// value is used to store display data
 | 
			
		||||
var Providers = map[string]Provider{
 | 
			
		||||
	"bitbucket": {Name: "bitbucket", DisplayName: "Bitbucket", Image: "/assets/img/auth/bitbucket.png"},
 | 
			
		||||
	"dropbox":   {Name: "dropbox", DisplayName: "Dropbox", Image: "/assets/img/auth/dropbox.png"},
 | 
			
		||||
	"facebook":  {Name: "facebook", DisplayName: "Facebook", Image: "/assets/img/auth/facebook.png"},
 | 
			
		||||
	"github": {
 | 
			
		||||
		Name: "github", DisplayName: "GitHub", Image: "/assets/img/auth/github.png",
 | 
			
		||||
		CustomURLMapping: &CustomURLMapping{
 | 
			
		||||
			TokenURL:   github.TokenURL,
 | 
			
		||||
			AuthURL:    github.AuthURL,
 | 
			
		||||
			ProfileURL: github.ProfileURL,
 | 
			
		||||
			EmailURL:   github.EmailURL,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	"gitlab": {
 | 
			
		||||
		Name: "gitlab", DisplayName: "GitLab", Image: "/assets/img/auth/gitlab.png",
 | 
			
		||||
		CustomURLMapping: &CustomURLMapping{
 | 
			
		||||
			TokenURL:   gitlab.TokenURL,
 | 
			
		||||
			AuthURL:    gitlab.AuthURL,
 | 
			
		||||
			ProfileURL: gitlab.ProfileURL,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	"gplus":         {Name: "gplus", DisplayName: "Google", Image: "/assets/img/auth/google.png"},
 | 
			
		||||
	"openidConnect": {Name: "openidConnect", DisplayName: "OpenID Connect", Image: "/assets/img/auth/openid_connect.svg"},
 | 
			
		||||
	"twitter":       {Name: "twitter", DisplayName: "Twitter", Image: "/assets/img/auth/twitter.png"},
 | 
			
		||||
	"discord":       {Name: "discord", DisplayName: "Discord", Image: "/assets/img/auth/discord.png"},
 | 
			
		||||
	"gitea": {
 | 
			
		||||
		Name: "gitea", DisplayName: "Gitea", Image: "/assets/img/auth/gitea.png",
 | 
			
		||||
		CustomURLMapping: &CustomURLMapping{
 | 
			
		||||
			TokenURL:   gitea.TokenURL,
 | 
			
		||||
			AuthURL:    gitea.AuthURL,
 | 
			
		||||
			ProfileURL: gitea.ProfileURL,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	"nextcloud": {
 | 
			
		||||
		Name: "nextcloud", DisplayName: "Nextcloud", Image: "/assets/img/auth/nextcloud.png",
 | 
			
		||||
		CustomURLMapping: &CustomURLMapping{
 | 
			
		||||
			TokenURL:   nextcloud.TokenURL,
 | 
			
		||||
			AuthURL:    nextcloud.AuthURL,
 | 
			
		||||
			ProfileURL: nextcloud.ProfileURL,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	"yandex": {Name: "yandex", DisplayName: "Yandex", Image: "/assets/img/auth/yandex.png"},
 | 
			
		||||
	"mastodon": {
 | 
			
		||||
		Name: "mastodon", DisplayName: "Mastodon", Image: "/assets/img/auth/mastodon.png",
 | 
			
		||||
		CustomURLMapping: &CustomURLMapping{
 | 
			
		||||
			AuthURL: mastodon.InstanceURL,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
var gothProviders = map[string]GothProvider{}
 | 
			
		||||
 | 
			
		||||
// RegisterGothProvider registers a GothProvider
 | 
			
		||||
func RegisterGothProvider(provider GothProvider) {
 | 
			
		||||
	if _, has := gothProviders[provider.Name()]; has {
 | 
			
		||||
		log.Fatal("Duplicate oauth2provider type provided: %s", provider.Name())
 | 
			
		||||
	}
 | 
			
		||||
	gothProviders[provider.Name()] = provider
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetOAuth2Providers returns the map of unconfigured OAuth2 providers
 | 
			
		||||
// key is used as technical name (like in the callbackURL)
 | 
			
		||||
// values to display
 | 
			
		||||
func GetOAuth2Providers() []Provider {
 | 
			
		||||
	providers := make([]Provider, 0, len(gothProviders))
 | 
			
		||||
 | 
			
		||||
	for _, provider := range gothProviders {
 | 
			
		||||
		providers = append(providers, provider)
 | 
			
		||||
	}
 | 
			
		||||
	sort.Slice(providers, func(i, j int) bool {
 | 
			
		||||
		return providers[i].Name() < providers[j].Name()
 | 
			
		||||
	})
 | 
			
		||||
	return providers
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetActiveOAuth2Providers returns the map of configured active OAuth2 providers
 | 
			
		||||
| 
						 | 
				
			
			@ -103,9 +95,9 @@ func GetActiveOAuth2Providers() ([]string, map[string]Provider, error) {
 | 
			
		|||
	var orderedKeys []string
 | 
			
		||||
	providers := make(map[string]Provider)
 | 
			
		||||
	for _, source := range loginSources {
 | 
			
		||||
		prov := Providers[source.Cfg.(*Source).Provider]
 | 
			
		||||
		prov := gothProviders[source.Cfg.(*Source).Provider]
 | 
			
		||||
		if source.Cfg.(*Source).IconURL != "" {
 | 
			
		||||
			prov.Image = source.Cfg.(*Source).IconURL
 | 
			
		||||
			prov = &ImagedProvider{prov, source.Cfg.(*Source).IconURL}
 | 
			
		||||
		}
 | 
			
		||||
		providers[source.Name] = prov
 | 
			
		||||
		orderedKeys = append(orderedKeys, source.Name)
 | 
			
		||||
| 
						 | 
				
			
			@ -116,9 +108,9 @@ func GetActiveOAuth2Providers() ([]string, map[string]Provider, error) {
 | 
			
		|||
	return orderedKeys, providers, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterProvider register a OAuth2 provider in goth lib
 | 
			
		||||
func RegisterProvider(providerName, providerType, clientID, clientSecret, openIDConnectAutoDiscoveryURL string, customURLMapping *CustomURLMapping) error {
 | 
			
		||||
	provider, err := createProvider(providerName, providerType, clientID, clientSecret, openIDConnectAutoDiscoveryURL, customURLMapping)
 | 
			
		||||
// RegisterProviderWithGothic register a OAuth2 provider in goth lib
 | 
			
		||||
func RegisterProviderWithGothic(providerName string, source *Source) error {
 | 
			
		||||
	provider, err := createProvider(providerName, source)
 | 
			
		||||
 | 
			
		||||
	if err == nil && provider != nil {
 | 
			
		||||
		gothRWMutex.Lock()
 | 
			
		||||
| 
						 | 
				
			
			@ -130,8 +122,8 @@ func RegisterProvider(providerName, providerType, clientID, clientSecret, openID
 | 
			
		|||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveProvider removes the given OAuth2 provider from the goth lib
 | 
			
		||||
func RemoveProvider(providerName string) {
 | 
			
		||||
// RemoveProviderFromGothic removes the given OAuth2 provider from the goth lib
 | 
			
		||||
func RemoveProviderFromGothic(providerName string) {
 | 
			
		||||
	gothRWMutex.Lock()
 | 
			
		||||
	defer gothRWMutex.Unlock()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -147,114 +139,20 @@ func ClearProviders() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// used to create different types of goth providers
 | 
			
		||||
func createProvider(providerName, providerType, clientID, clientSecret, openIDConnectAutoDiscoveryURL string, customURLMapping *CustomURLMapping) (goth.Provider, error) {
 | 
			
		||||
func createProvider(providerName string, source *Source) (goth.Provider, error) {
 | 
			
		||||
	callbackURL := setting.AppURL + "user/oauth2/" + url.PathEscape(providerName) + "/callback"
 | 
			
		||||
 | 
			
		||||
	var provider goth.Provider
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	switch providerType {
 | 
			
		||||
	case "bitbucket":
 | 
			
		||||
		provider = bitbucket.New(clientID, clientSecret, callbackURL, "account")
 | 
			
		||||
	case "dropbox":
 | 
			
		||||
		provider = dropbox.New(clientID, clientSecret, callbackURL)
 | 
			
		||||
	case "facebook":
 | 
			
		||||
		provider = facebook.New(clientID, clientSecret, callbackURL, "email")
 | 
			
		||||
	case "github":
 | 
			
		||||
		authURL := github.AuthURL
 | 
			
		||||
		tokenURL := github.TokenURL
 | 
			
		||||
		profileURL := github.ProfileURL
 | 
			
		||||
		emailURL := github.EmailURL
 | 
			
		||||
		if customURLMapping != nil {
 | 
			
		||||
			if len(customURLMapping.AuthURL) > 0 {
 | 
			
		||||
				authURL = customURLMapping.AuthURL
 | 
			
		||||
			}
 | 
			
		||||
			if len(customURLMapping.TokenURL) > 0 {
 | 
			
		||||
				tokenURL = customURLMapping.TokenURL
 | 
			
		||||
			}
 | 
			
		||||
			if len(customURLMapping.ProfileURL) > 0 {
 | 
			
		||||
				profileURL = customURLMapping.ProfileURL
 | 
			
		||||
			}
 | 
			
		||||
			if len(customURLMapping.EmailURL) > 0 {
 | 
			
		||||
				emailURL = customURLMapping.EmailURL
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		scopes := []string{}
 | 
			
		||||
		if setting.OAuth2Client.EnableAutoRegistration {
 | 
			
		||||
			scopes = append(scopes, "user:email")
 | 
			
		||||
		}
 | 
			
		||||
		provider = github.NewCustomisedURL(clientID, clientSecret, callbackURL, authURL, tokenURL, profileURL, emailURL, scopes...)
 | 
			
		||||
	case "gitlab":
 | 
			
		||||
		authURL := gitlab.AuthURL
 | 
			
		||||
		tokenURL := gitlab.TokenURL
 | 
			
		||||
		profileURL := gitlab.ProfileURL
 | 
			
		||||
		if customURLMapping != nil {
 | 
			
		||||
			if len(customURLMapping.AuthURL) > 0 {
 | 
			
		||||
				authURL = customURLMapping.AuthURL
 | 
			
		||||
			}
 | 
			
		||||
			if len(customURLMapping.TokenURL) > 0 {
 | 
			
		||||
				tokenURL = customURLMapping.TokenURL
 | 
			
		||||
			}
 | 
			
		||||
			if len(customURLMapping.ProfileURL) > 0 {
 | 
			
		||||
				profileURL = customURLMapping.ProfileURL
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		provider = gitlab.NewCustomisedURL(clientID, clientSecret, callbackURL, authURL, tokenURL, profileURL, "read_user")
 | 
			
		||||
	case "gplus": // named gplus due to legacy gplus -> google migration (Google killed Google+). This ensures old connections still work
 | 
			
		||||
		scopes := []string{"email"}
 | 
			
		||||
		if setting.OAuth2Client.UpdateAvatar || setting.OAuth2Client.EnableAutoRegistration {
 | 
			
		||||
			scopes = append(scopes, "profile")
 | 
			
		||||
		}
 | 
			
		||||
		provider = google.New(clientID, clientSecret, callbackURL, scopes...)
 | 
			
		||||
	case "openidConnect":
 | 
			
		||||
		if provider, err = openidConnect.New(clientID, clientSecret, callbackURL, openIDConnectAutoDiscoveryURL, setting.OAuth2Client.OpenIDConnectScopes...); err != nil {
 | 
			
		||||
			log.Warn("Failed to create OpenID Connect Provider with name '%s' with url '%s': %v", providerName, openIDConnectAutoDiscoveryURL, err)
 | 
			
		||||
		}
 | 
			
		||||
	case "twitter":
 | 
			
		||||
		provider = twitter.NewAuthenticate(clientID, clientSecret, callbackURL)
 | 
			
		||||
	case "discord":
 | 
			
		||||
		provider = discord.New(clientID, clientSecret, callbackURL, discord.ScopeIdentify, discord.ScopeEmail)
 | 
			
		||||
	case "gitea":
 | 
			
		||||
		authURL := gitea.AuthURL
 | 
			
		||||
		tokenURL := gitea.TokenURL
 | 
			
		||||
		profileURL := gitea.ProfileURL
 | 
			
		||||
		if customURLMapping != nil {
 | 
			
		||||
			if len(customURLMapping.AuthURL) > 0 {
 | 
			
		||||
				authURL = customURLMapping.AuthURL
 | 
			
		||||
			}
 | 
			
		||||
			if len(customURLMapping.TokenURL) > 0 {
 | 
			
		||||
				tokenURL = customURLMapping.TokenURL
 | 
			
		||||
			}
 | 
			
		||||
			if len(customURLMapping.ProfileURL) > 0 {
 | 
			
		||||
				profileURL = customURLMapping.ProfileURL
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		provider = gitea.NewCustomisedURL(clientID, clientSecret, callbackURL, authURL, tokenURL, profileURL)
 | 
			
		||||
	case "nextcloud":
 | 
			
		||||
		authURL := nextcloud.AuthURL
 | 
			
		||||
		tokenURL := nextcloud.TokenURL
 | 
			
		||||
		profileURL := nextcloud.ProfileURL
 | 
			
		||||
		if customURLMapping != nil {
 | 
			
		||||
			if len(customURLMapping.AuthURL) > 0 {
 | 
			
		||||
				authURL = customURLMapping.AuthURL
 | 
			
		||||
			}
 | 
			
		||||
			if len(customURLMapping.TokenURL) > 0 {
 | 
			
		||||
				tokenURL = customURLMapping.TokenURL
 | 
			
		||||
			}
 | 
			
		||||
			if len(customURLMapping.ProfileURL) > 0 {
 | 
			
		||||
				profileURL = customURLMapping.ProfileURL
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		provider = nextcloud.NewCustomisedURL(clientID, clientSecret, callbackURL, authURL, tokenURL, profileURL)
 | 
			
		||||
	case "yandex":
 | 
			
		||||
		// See https://tech.yandex.com/passport/doc/dg/reference/response-docpage/
 | 
			
		||||
		provider = yandex.New(clientID, clientSecret, callbackURL, "login:email", "login:info", "login:avatar")
 | 
			
		||||
	case "mastodon":
 | 
			
		||||
		instanceURL := mastodon.InstanceURL
 | 
			
		||||
		if customURLMapping != nil && len(customURLMapping.AuthURL) > 0 {
 | 
			
		||||
			instanceURL = customURLMapping.AuthURL
 | 
			
		||||
		}
 | 
			
		||||
		provider = mastodon.NewCustomisedURL(clientID, clientSecret, callbackURL, instanceURL)
 | 
			
		||||
	p, ok := gothProviders[source.Provider]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, models.ErrLoginSourceNotActived
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	provider, err = p.CreateGothProvider(providerName, callbackURL, source)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return provider, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// always set the name if provider is created so we can support multiple setups of 1 provider
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								services/auth/source/oauth2/providers_base.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								services/auth/source/oauth2/providers_base.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
// Copyright 2021 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package oauth2
 | 
			
		||||
 | 
			
		||||
// BaseProvider represents a common base for Provider
 | 
			
		||||
type BaseProvider struct {
 | 
			
		||||
	name        string
 | 
			
		||||
	displayName string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name provides the technical name for this provider
 | 
			
		||||
func (b *BaseProvider) Name() string {
 | 
			
		||||
	return b.name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DisplayName returns the friendly name for this provider
 | 
			
		||||
func (b *BaseProvider) DisplayName() string {
 | 
			
		||||
	return b.displayName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Image returns an image path for this provider
 | 
			
		||||
func (b *BaseProvider) Image() string {
 | 
			
		||||
	return "/assets/img/auth/" + b.name + ".png"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CustomURLSettings returns the custom url settings for this provider
 | 
			
		||||
func (b *BaseProvider) CustomURLSettings() *CustomURLSettings {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ (Provider) = &BaseProvider{}
 | 
			
		||||
							
								
								
									
										118
									
								
								services/auth/source/oauth2/providers_custom.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								services/auth/source/oauth2/providers_custom.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,118 @@
 | 
			
		|||
// Copyright 2021 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package oauth2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
	"github.com/markbates/goth/providers/azureadv2"
 | 
			
		||||
	"github.com/markbates/goth/providers/gitea"
 | 
			
		||||
	"github.com/markbates/goth/providers/github"
 | 
			
		||||
	"github.com/markbates/goth/providers/gitlab"
 | 
			
		||||
	"github.com/markbates/goth/providers/mastodon"
 | 
			
		||||
	"github.com/markbates/goth/providers/nextcloud"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CustomProviderNewFn creates a goth.Provider using a custom url mapping
 | 
			
		||||
type CustomProviderNewFn func(clientID, secret, callbackURL string, custom *CustomURLMapping) (goth.Provider, error)
 | 
			
		||||
 | 
			
		||||
// CustomProvider is a GothProvider that has CustomURL features
 | 
			
		||||
type CustomProvider struct {
 | 
			
		||||
	BaseProvider
 | 
			
		||||
	customURLSettings *CustomURLSettings
 | 
			
		||||
	newFn             CustomProviderNewFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CustomURLSettings returns the CustomURLSettings for this provider
 | 
			
		||||
func (c *CustomProvider) CustomURLSettings() *CustomURLSettings {
 | 
			
		||||
	return c.customURLSettings
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateGothProvider creates a GothProvider from this Provider
 | 
			
		||||
func (c *CustomProvider) CreateGothProvider(providerName, callbackURL string, source *Source) (goth.Provider, error) {
 | 
			
		||||
	custom := c.customURLSettings.OverrideWith(source.CustomURLMapping)
 | 
			
		||||
 | 
			
		||||
	return c.newFn(source.ClientID, source.ClientSecret, callbackURL, custom)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCustomProvider is a constructor function for custom providers
 | 
			
		||||
func NewCustomProvider(name, displayName string, customURLSetting *CustomURLSettings, newFn CustomProviderNewFn) *CustomProvider {
 | 
			
		||||
	return &CustomProvider{
 | 
			
		||||
		BaseProvider: BaseProvider{
 | 
			
		||||
			name:        name,
 | 
			
		||||
			displayName: displayName,
 | 
			
		||||
		},
 | 
			
		||||
		customURLSettings: customURLSetting,
 | 
			
		||||
		newFn:             newFn,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ (GothProvider) = &CustomProvider{}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	RegisterGothProvider(NewCustomProvider(
 | 
			
		||||
		"github", "GitHub", &CustomURLSettings{
 | 
			
		||||
			TokenURL:   availableAttribute(gitea.TokenURL),
 | 
			
		||||
			AuthURL:    availableAttribute(github.AuthURL),
 | 
			
		||||
			ProfileURL: availableAttribute(github.ProfileURL),
 | 
			
		||||
			EmailURL:   availableAttribute(github.EmailURL),
 | 
			
		||||
		},
 | 
			
		||||
		func(clientID, secret, callbackURL string, custom *CustomURLMapping) (goth.Provider, error) {
 | 
			
		||||
			scopes := []string{}
 | 
			
		||||
			if setting.OAuth2Client.EnableAutoRegistration {
 | 
			
		||||
				scopes = append(scopes, "user:email")
 | 
			
		||||
			}
 | 
			
		||||
			return github.NewCustomisedURL(clientID, secret, callbackURL, custom.AuthURL, custom.TokenURL, custom.ProfileURL, custom.EmailURL, scopes...), nil
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewCustomProvider(
 | 
			
		||||
		"gitlab", "GitLab", &CustomURLSettings{
 | 
			
		||||
			AuthURL:    availableAttribute(gitlab.AuthURL),
 | 
			
		||||
			TokenURL:   availableAttribute(gitlab.TokenURL),
 | 
			
		||||
			ProfileURL: availableAttribute(gitlab.ProfileURL),
 | 
			
		||||
		}, func(clientID, secret, callbackURL string, custom *CustomURLMapping) (goth.Provider, error) {
 | 
			
		||||
			return gitlab.NewCustomisedURL(clientID, secret, callbackURL, custom.AuthURL, custom.TokenURL, custom.ProfileURL, "read_user"), nil
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewCustomProvider(
 | 
			
		||||
		"gitea", "Gitea", &CustomURLSettings{
 | 
			
		||||
			TokenURL:   requiredAttribute(gitea.TokenURL),
 | 
			
		||||
			AuthURL:    requiredAttribute(gitea.AuthURL),
 | 
			
		||||
			ProfileURL: requiredAttribute(gitea.ProfileURL),
 | 
			
		||||
		},
 | 
			
		||||
		func(clientID, secret, callbackURL string, custom *CustomURLMapping) (goth.Provider, error) {
 | 
			
		||||
			return gitea.NewCustomisedURL(clientID, secret, callbackURL, custom.AuthURL, custom.TokenURL, custom.ProfileURL), nil
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewCustomProvider(
 | 
			
		||||
		"nextcloud", "Nextcloud", &CustomURLSettings{
 | 
			
		||||
			TokenURL:   requiredAttribute(nextcloud.TokenURL),
 | 
			
		||||
			AuthURL:    requiredAttribute(nextcloud.AuthURL),
 | 
			
		||||
			ProfileURL: requiredAttribute(nextcloud.ProfileURL),
 | 
			
		||||
		},
 | 
			
		||||
		func(clientID, secret, callbackURL string, custom *CustomURLMapping) (goth.Provider, error) {
 | 
			
		||||
			return nextcloud.NewCustomisedURL(clientID, secret, callbackURL, custom.AuthURL, custom.TokenURL, custom.ProfileURL), nil
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewCustomProvider(
 | 
			
		||||
		"mastodon", "Mastodon", &CustomURLSettings{
 | 
			
		||||
			AuthURL: requiredAttribute(mastodon.InstanceURL),
 | 
			
		||||
		},
 | 
			
		||||
		func(clientID, secret, callbackURL string, custom *CustomURLMapping) (goth.Provider, error) {
 | 
			
		||||
			return mastodon.NewCustomisedURL(clientID, secret, callbackURL, custom.AuthURL), nil
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewCustomProvider(
 | 
			
		||||
		"azureadv2", "Azure AD v2", &CustomURLSettings{
 | 
			
		||||
			Tenant: requiredAttribute("organizations"),
 | 
			
		||||
		},
 | 
			
		||||
		func(clientID, secret, callbackURL string, custom *CustomURLMapping) (goth.Provider, error) {
 | 
			
		||||
			return azureadv2.New(clientID, secret, callbackURL, azureadv2.ProviderOptions{
 | 
			
		||||
				Tenant: azureadv2.TenantType(custom.Tenant),
 | 
			
		||||
			}), nil
 | 
			
		||||
		},
 | 
			
		||||
	))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								services/auth/source/oauth2/providers_openid.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								services/auth/source/oauth2/providers_openid.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
// Copyright 2021 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package oauth2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
	"github.com/markbates/goth/providers/openidConnect"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// OpenIDProvider is a GothProvider for OpenID
 | 
			
		||||
type OpenIDProvider struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name provides the technical name for this provider
 | 
			
		||||
func (o *OpenIDProvider) Name() string {
 | 
			
		||||
	return "openidconnect"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DisplayName returns the friendly name for this provider
 | 
			
		||||
func (o *OpenIDProvider) DisplayName() string {
 | 
			
		||||
	return "OpenID Connect"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Image returns an image path for this provider
 | 
			
		||||
func (o *OpenIDProvider) Image() string {
 | 
			
		||||
	return "/assets/img/auth/openid_connect.svg"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateGothProvider creates a GothProvider from this Provider
 | 
			
		||||
func (o *OpenIDProvider) CreateGothProvider(providerName, callbackURL string, source *Source) (goth.Provider, error) {
 | 
			
		||||
	provider, err := openidConnect.New(source.ClientID, source.ClientSecret, callbackURL, source.OpenIDConnectAutoDiscoveryURL, setting.OAuth2Client.OpenIDConnectScopes...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Warn("Failed to create OpenID Connect Provider with name '%s' with url '%s': %v", providerName, source.OpenIDConnectAutoDiscoveryURL, err)
 | 
			
		||||
	}
 | 
			
		||||
	return provider, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CustomURLSettings returns the custom url settings for this provider
 | 
			
		||||
func (o *OpenIDProvider) CustomURLSettings() *CustomURLSettings {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ (GothProvider) = &OpenIDProvider{}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	RegisterGothProvider(&OpenIDProvider{})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										108
									
								
								services/auth/source/oauth2/providers_simple.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								services/auth/source/oauth2/providers_simple.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,108 @@
 | 
			
		|||
// Copyright 2021 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package oauth2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
	"github.com/markbates/goth/providers/azuread"
 | 
			
		||||
	"github.com/markbates/goth/providers/bitbucket"
 | 
			
		||||
	"github.com/markbates/goth/providers/discord"
 | 
			
		||||
	"github.com/markbates/goth/providers/dropbox"
 | 
			
		||||
	"github.com/markbates/goth/providers/facebook"
 | 
			
		||||
	"github.com/markbates/goth/providers/google"
 | 
			
		||||
	"github.com/markbates/goth/providers/microsoftonline"
 | 
			
		||||
	"github.com/markbates/goth/providers/twitter"
 | 
			
		||||
	"github.com/markbates/goth/providers/yandex"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SimpleProviderNewFn create goth.Providers without custom url features
 | 
			
		||||
type SimpleProviderNewFn func(clientKey, secret, callbackURL string, scopes ...string) goth.Provider
 | 
			
		||||
 | 
			
		||||
// SimpleProvider is a GothProvider which does not have custom url features
 | 
			
		||||
type SimpleProvider struct {
 | 
			
		||||
	BaseProvider
 | 
			
		||||
	scopes []string
 | 
			
		||||
	newFn  SimpleProviderNewFn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateGothProvider creates a GothProvider from this Provider
 | 
			
		||||
func (c *SimpleProvider) CreateGothProvider(providerName, callbackURL string, source *Source) (goth.Provider, error) {
 | 
			
		||||
	return c.newFn(source.ClientID, source.ClientSecret, callbackURL, c.scopes...), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSimpleProvider is a constructor function for simple providers
 | 
			
		||||
func NewSimpleProvider(name, displayName string, scopes []string, newFn SimpleProviderNewFn) *SimpleProvider {
 | 
			
		||||
	return &SimpleProvider{
 | 
			
		||||
		BaseProvider: BaseProvider{
 | 
			
		||||
			name:        name,
 | 
			
		||||
			displayName: displayName,
 | 
			
		||||
		},
 | 
			
		||||
		scopes: scopes,
 | 
			
		||||
		newFn:  newFn,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ (GothProvider) = &SimpleProvider{}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	RegisterGothProvider(
 | 
			
		||||
		NewSimpleProvider("bitbucket", "Bitbucket", []string{"account"},
 | 
			
		||||
			func(clientKey, secret, callbackURL string, scopes ...string) goth.Provider {
 | 
			
		||||
				return bitbucket.New(clientKey, secret, callbackURL, scopes...)
 | 
			
		||||
			}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(
 | 
			
		||||
		NewSimpleProvider("dropbox", "Dropbox", nil,
 | 
			
		||||
			func(clientKey, secret, callbackURL string, scopes ...string) goth.Provider {
 | 
			
		||||
				return dropbox.New(clientKey, secret, callbackURL, scopes...)
 | 
			
		||||
			}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewSimpleProvider("facebook", "Facebook", nil,
 | 
			
		||||
		func(clientKey, secret, callbackURL string, scopes ...string) goth.Provider {
 | 
			
		||||
			return facebook.New(clientKey, secret, callbackURL, scopes...)
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	// named gplus due to legacy gplus -> google migration (Google killed Google+). This ensures old connections still work
 | 
			
		||||
	RegisterGothProvider(NewSimpleProvider("gplus", "Google", []string{"email"},
 | 
			
		||||
		func(clientKey, secret, callbackURL string, scopes ...string) goth.Provider {
 | 
			
		||||
			if setting.OAuth2Client.UpdateAvatar || setting.OAuth2Client.EnableAutoRegistration {
 | 
			
		||||
				scopes = append(scopes, "profile")
 | 
			
		||||
			}
 | 
			
		||||
			return google.New(clientKey, secret, callbackURL, scopes...)
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewSimpleProvider("twitter", "Twitter", nil,
 | 
			
		||||
		func(clientKey, secret, callbackURL string, scopes ...string) goth.Provider {
 | 
			
		||||
			return twitter.New(clientKey, secret, callbackURL)
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewSimpleProvider("discord", "Discord", []string{discord.ScopeIdentify, discord.ScopeEmail},
 | 
			
		||||
		func(clientKey, secret, callbackURL string, scopes ...string) goth.Provider {
 | 
			
		||||
			return discord.New(clientKey, secret, callbackURL, scopes...)
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	// See https://tech.yandex.com/passport/doc/dg/reference/response-docpage/
 | 
			
		||||
	RegisterGothProvider(NewSimpleProvider("yandex", "Yandex", []string{"login:email", "login:info", "login:avatar"},
 | 
			
		||||
		func(clientKey, secret, callbackURL string, scopes ...string) goth.Provider {
 | 
			
		||||
			return yandex.New(clientKey, secret, callbackURL, scopes...)
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewSimpleProvider(
 | 
			
		||||
		"azuread", "Azure AD", nil,
 | 
			
		||||
		func(clientID, secret, callbackURL string, scopes ...string) goth.Provider {
 | 
			
		||||
			return azuread.New(clientID, secret, callbackURL, nil, scopes...)
 | 
			
		||||
		},
 | 
			
		||||
	))
 | 
			
		||||
 | 
			
		||||
	RegisterGothProvider(NewSimpleProvider(
 | 
			
		||||
		"microsoftonline", "Microsoft Online", nil,
 | 
			
		||||
		func(clientID, secret, callbackURL string, scopes ...string) goth.Provider {
 | 
			
		||||
			return microsoftonline.New(clientID, secret, callbackURL, scopes...)
 | 
			
		||||
		},
 | 
			
		||||
	))
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								services/auth/source/oauth2/source_name.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								services/auth/source/oauth2/source_name.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
// Copyright 2021 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package oauth2
 | 
			
		||||
 | 
			
		||||
// Name returns the provider name of this source
 | 
			
		||||
func (source *Source) Name() string {
 | 
			
		||||
	return source.Provider
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DisplayName returns the display name of this source
 | 
			
		||||
func (source *Source) DisplayName() string {
 | 
			
		||||
	provider, has := gothProviders[source.Provider]
 | 
			
		||||
	if !has {
 | 
			
		||||
		return source.Provider
 | 
			
		||||
	}
 | 
			
		||||
	return provider.DisplayName()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,13 +10,13 @@ import (
 | 
			
		|||
 | 
			
		||||
// RegisterSource causes an OAuth2 configuration to be registered
 | 
			
		||||
func (source *Source) RegisterSource() error {
 | 
			
		||||
	err := RegisterProvider(source.loginSource.Name, source.Provider, source.ClientID, source.ClientSecret, source.OpenIDConnectAutoDiscoveryURL, source.CustomURLMapping)
 | 
			
		||||
	err := RegisterProviderWithGothic(source.loginSource.Name, source)
 | 
			
		||||
	return wrapOpenIDConnectInitializeError(err, source.loginSource.Name, source)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnregisterSource causes an OAuth2 configuration to be unregistered
 | 
			
		||||
func (source *Source) UnregisterSource() error {
 | 
			
		||||
	RemoveProvider(source.loginSource.Name)
 | 
			
		||||
	RemoveProviderFromGothic(source.loginSource.Name)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,19 +6,73 @@ package oauth2
 | 
			
		|||
 | 
			
		||||
// CustomURLMapping describes the urls values to use when customizing OAuth2 provider URLs
 | 
			
		||||
type CustomURLMapping struct {
 | 
			
		||||
	AuthURL    string
 | 
			
		||||
	TokenURL   string
 | 
			
		||||
	ProfileURL string
 | 
			
		||||
	EmailURL   string
 | 
			
		||||
	AuthURL    string `json:",omitempty"`
 | 
			
		||||
	TokenURL   string `json:",omitempty"`
 | 
			
		||||
	ProfileURL string `json:",omitempty"`
 | 
			
		||||
	EmailURL   string `json:",omitempty"`
 | 
			
		||||
	Tenant     string `json:",omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultCustomURLMappings contains the map of default URL's for OAuth2 providers that are allowed to have custom urls
 | 
			
		||||
// key is used to map the OAuth2Provider
 | 
			
		||||
// value is the mapping as defined for the OAuth2Provider
 | 
			
		||||
var DefaultCustomURLMappings = map[string]*CustomURLMapping{
 | 
			
		||||
	"github":    Providers["github"].CustomURLMapping,
 | 
			
		||||
	"gitlab":    Providers["gitlab"].CustomURLMapping,
 | 
			
		||||
	"gitea":     Providers["gitea"].CustomURLMapping,
 | 
			
		||||
	"nextcloud": Providers["nextcloud"].CustomURLMapping,
 | 
			
		||||
	"mastodon":  Providers["mastodon"].CustomURLMapping,
 | 
			
		||||
// CustomURLSettings describes the urls values and availability to use when customizing OAuth2 provider URLs
 | 
			
		||||
type CustomURLSettings struct {
 | 
			
		||||
	AuthURL    Attribute `json:",omitempty"`
 | 
			
		||||
	TokenURL   Attribute `json:",omitempty"`
 | 
			
		||||
	ProfileURL Attribute `json:",omitempty"`
 | 
			
		||||
	EmailURL   Attribute `json:",omitempty"`
 | 
			
		||||
	Tenant     Attribute `json:",omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Attribute describes the availability, and required status for a custom url configuration
 | 
			
		||||
type Attribute struct {
 | 
			
		||||
	Value     string
 | 
			
		||||
	Available bool
 | 
			
		||||
	Required  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func availableAttribute(value string) Attribute {
 | 
			
		||||
	return Attribute{Value: value, Available: true}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func requiredAttribute(value string) Attribute {
 | 
			
		||||
	return Attribute{Value: value, Available: true, Required: true}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Required is true if any attribute is required
 | 
			
		||||
func (c *CustomURLSettings) Required() bool {
 | 
			
		||||
	if c == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if c.AuthURL.Required || c.EmailURL.Required || c.ProfileURL.Required || c.TokenURL.Required || c.Tenant.Required {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OverrideWith copies the current customURLMapping and overrides it with values from the provided mapping
 | 
			
		||||
func (c *CustomURLSettings) OverrideWith(override *CustomURLMapping) *CustomURLMapping {
 | 
			
		||||
	custom := &CustomURLMapping{
 | 
			
		||||
		AuthURL:    c.AuthURL.Value,
 | 
			
		||||
		TokenURL:   c.TokenURL.Value,
 | 
			
		||||
		ProfileURL: c.ProfileURL.Value,
 | 
			
		||||
		EmailURL:   c.EmailURL.Value,
 | 
			
		||||
		Tenant:     c.Tenant.Value,
 | 
			
		||||
	}
 | 
			
		||||
	if override != nil {
 | 
			
		||||
		if len(override.AuthURL) > 0 && c.AuthURL.Available {
 | 
			
		||||
			custom.AuthURL = override.AuthURL
 | 
			
		||||
		}
 | 
			
		||||
		if len(override.TokenURL) > 0 && c.TokenURL.Available {
 | 
			
		||||
			custom.TokenURL = override.TokenURL
 | 
			
		||||
		}
 | 
			
		||||
		if len(override.ProfileURL) > 0 && c.ProfileURL.Available {
 | 
			
		||||
			custom.ProfileURL = override.ProfileURL
 | 
			
		||||
		}
 | 
			
		||||
		if len(override.EmailURL) > 0 && c.EmailURL.Available {
 | 
			
		||||
			custom.EmailURL = override.EmailURL
 | 
			
		||||
		}
 | 
			
		||||
		if len(override.Tenant) > 0 && c.Tenant.Available {
 | 
			
		||||
			custom.Tenant = override.Tenant
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return custom
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,6 +62,7 @@ type AuthenticationForm struct {
 | 
			
		|||
	Oauth2ProfileURL              string
 | 
			
		||||
	Oauth2EmailURL                string
 | 
			
		||||
	Oauth2IconURL                 string
 | 
			
		||||
	Oauth2Tenant                  string
 | 
			
		||||
	SSPIAutoCreateUsers           bool
 | 
			
		||||
	SSPIAutoActivateUsers         bool
 | 
			
		||||
	SSPIStripDomainNames          bool
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -203,8 +203,8 @@
 | 
			
		|||
							<div class="text">{{.CurrentOAuth2Provider.DisplayName}}</div>
 | 
			
		||||
							{{svg "octicon-triangle-down" 14 "dropdown icon"}}
 | 
			
		||||
							<div class="menu">
 | 
			
		||||
								{{range $key, $value := .OAuth2Providers}}
 | 
			
		||||
									<div class="item" data-value="{{$key}}">{{$value.DisplayName}}</div>
 | 
			
		||||
								{{range .OAuth2Providers}}
 | 
			
		||||
									<div class="item" data-value="{{.Name}}">{{.DisplayName}}</div>
 | 
			
		||||
								{{end}}
 | 
			
		||||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -248,11 +248,18 @@
 | 
			
		|||
						<label for="oauth2_email_url">{{.i18n.Tr "admin.auths.oauth2_emailURL"}}</label>
 | 
			
		||||
						<input id="oauth2_email_url" name="oauth2_email_url" value="{{if $cfg.CustomURLMapping}}{{$cfg.CustomURLMapping.EmailURL}}{{end}}">
 | 
			
		||||
					</div>
 | 
			
		||||
					{{if .OAuth2DefaultCustomURLMappings}}{{range $key, $value := .OAuth2DefaultCustomURLMappings}}
 | 
			
		||||
					<input id="{{$key}}_token_url" value="{{$value.TokenURL}}" type="hidden" />
 | 
			
		||||
					<input id="{{$key}}_auth_url" value="{{$value.AuthURL}}" type="hidden" />
 | 
			
		||||
					<input id="{{$key}}_profile_url" value="{{$value.ProfileURL}}" type="hidden" />
 | 
			
		||||
					<input id="{{$key}}_email_url" value="{{$value.EmailURL}}" type="hidden" />
 | 
			
		||||
					<div class="oauth2_use_custom_url_field oauth2_tenant required field">
 | 
			
		||||
						<label for="oauth2_tenant">{{.i18n.Tr "admin.auths.oauth2_tenant"}}</label>
 | 
			
		||||
						<input id="oauth2_tenant" name="oauth2_tenant" value="{{if $cfg.CustomURLMapping}}{{$cfg.CustomURLMapping.Tenant}}{{end}}">
 | 
			
		||||
					</div>
 | 
			
		||||
 | 
			
		||||
					{{range .OAuth2Providers}}{{if .CustomURLSettings}}
 | 
			
		||||
						<input id="{{.Name}}_customURLSettings" type="hidden" data-required="{{.CustomURLSettings.Required}}" data-available="true">
 | 
			
		||||
						<input id="{{.Name}}_token_url" value="{{.CustomURLSettings.TokenURL.Value}}" data-available="{{.CustomURLSettings.TokenURL.Available}}" data-required="{{.CustomURLSettings.TokenURL.Required}}" type="hidden" />
 | 
			
		||||
						<input id="{{.Name}}_auth_url" value="{{.CustomURLSettings.AuthURL.Value}}" data-available="{{.CustomURLSettings.AuthURL.Available}}" data-required="{{.CustomURLSettings.AuthURL.Required}}" type="hidden" />
 | 
			
		||||
						<input id="{{.Name}}_profile_url" value="{{.CustomURLSettings.ProfileURL.Value}}" data-available="{{.CustomURLSettings.ProfileURL.Available}}" data-required="{{.CustomURLSettings.ProfileURL.Required}}" type="hidden" />
 | 
			
		||||
						<input id="{{.Name}}_email_url" value="{{.CustomURLSettings.EmailURL.Value}}" data-available="{{.CustomURLSettings.EmailURL.Available}}" data-required="{{.CustomURLSettings.EmailURL.Required}}" type="hidden" />
 | 
			
		||||
						<input id="{{.Name}}_tenant" value="{{.CustomURLSettings.Tenant.Value}}" data-available="{{.CustomURLSettings.Tenant.Available}}" data-required="{{.CustomURLSettings.Tenant.Required}}" type="hidden" />
 | 
			
		||||
					{{end}}{{end}}
 | 
			
		||||
				{{end}}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,12 +2,12 @@
 | 
			
		|||
	<div class="inline required field">
 | 
			
		||||
		<label>{{.i18n.Tr "admin.auths.oauth2_provider"}}</label>
 | 
			
		||||
		<div class="ui selection type dropdown">
 | 
			
		||||
			<input type="hidden" id="oauth2_provider" name="oauth2_provider" value="{{.oauth2_provider}}">
 | 
			
		||||
			<div class="text">{{.oauth2_provider}}</div>
 | 
			
		||||
			<input type="hidden" id="oauth2_provider" name="oauth2_provider" value="{{.oauth2_provider.Name}}">
 | 
			
		||||
			<div class="text">{{.oauth2_provider.Name}}</div>
 | 
			
		||||
			{{svg "octicon-triangle-down" 14 "dropdown icon"}}
 | 
			
		||||
			<div class="menu">
 | 
			
		||||
				{{range $key, $value := .OAuth2Providers}}
 | 
			
		||||
					<div class="item" data-value="{{$key}}">{{$value.DisplayName}}</div>
 | 
			
		||||
				{{range .OAuth2Providers}}
 | 
			
		||||
					<div class="item" data-value="{{.Name}}">{{.DisplayName}}</div>
 | 
			
		||||
				{{end}}
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -51,12 +51,17 @@
 | 
			
		|||
		<label for="oauth2_email_url">{{.i18n.Tr "admin.auths.oauth2_emailURL"}}</label>
 | 
			
		||||
		<input id="oauth2_email_url" name="oauth2_email_url" value="{{.oauth2_email_url}}">
 | 
			
		||||
	</div>
 | 
			
		||||
	{{if .OAuth2DefaultCustomURLMappings}}
 | 
			
		||||
		{{range $key, $value := .OAuth2DefaultCustomURLMappings}}
 | 
			
		||||
			<input id="{{$key}}_token_url" value="{{$value.TokenURL}}" type="hidden" />
 | 
			
		||||
			<input id="{{$key}}_auth_url" value="{{$value.AuthURL}}" type="hidden" />
 | 
			
		||||
			<input id="{{$key}}_profile_url" value="{{$value.ProfileURL}}" type="hidden" />
 | 
			
		||||
			<input id="{{$key}}_email_url" value="{{$value.EmailURL}}" type="hidden" />
 | 
			
		||||
		{{end}}
 | 
			
		||||
	{{end}}
 | 
			
		||||
	<div class="oauth2_use_custom_url_field oauth2_tenant required field">
 | 
			
		||||
		<label for="oauth2_tenant">{{.i18n.Tr "admin.auths.oauth2_tenant"}}</label>
 | 
			
		||||
		<input id="oauth2_tenant" name="oauth2_tenant" value="{{.oauth2_tenant}}">
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
	{{range .OAuth2Providers}}{{if .CustomURLSettings}}
 | 
			
		||||
		<input id="{{.Name}}_customURLSettings" type="hidden" data-required="{{.CustomURLSettings.Required}}" data-available="true">
 | 
			
		||||
		<input id="{{.Name}}_token_url" value="{{.CustomURLSettings.TokenURL.Value}}" data-available="{{.CustomURLSettings.TokenURL.Available}}" data-required="{{.CustomURLSettings.TokenURL.Required}}" type="hidden" />
 | 
			
		||||
		<input id="{{.Name}}_auth_url" value="{{.CustomURLSettings.AuthURL.Value}}" data-available="{{.CustomURLSettings.AuthURL.Available}}" data-required="{{.CustomURLSettings.AuthURL.Required}}" type="hidden" />
 | 
			
		||||
		<input id="{{.Name}}_profile_url" value="{{.CustomURLSettings.ProfileURL.Value}}" data-available="{{.CustomURLSettings.ProfileURL.Available}}" data-required="{{.CustomURLSettings.ProfileURL.Required}}" type="hidden" />
 | 
			
		||||
		<input id="{{.Name}}_email_url" value="{{.CustomURLSettings.EmailURL.Value}}" data-available="{{.CustomURLSettings.EmailURL.Available}}" data-required="{{.CustomURLSettings.EmailURL.Required}}" type="hidden" />
 | 
			
		||||
		<input id="{{.Name}}_tenant" value="{{.CustomURLSettings.Tenant.Value}}" data-available="{{.CustomURLSettings.Tenant.Available}}" data-required="{{.CustomURLSettings.Tenant.Required}}" type="hidden" />
 | 
			
		||||
	{{end}}{{end}}
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								vendor/github.com/markbates/going/LICENSE.txt
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/markbates/going/LICENSE.txt
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
Copyright (c) 2014 Mark Bates
 | 
			
		||||
 | 
			
		||||
MIT License
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining
 | 
			
		||||
a copy of this software and associated documentation files (the
 | 
			
		||||
"Software"), to deal in the Software without restriction, including
 | 
			
		||||
without limitation the rights to use, copy, modify, merge, publish,
 | 
			
		||||
distribute, sublicense, and/or sell copies of the Software, and to
 | 
			
		||||
permit persons to whom the Software is furnished to do so, subject to
 | 
			
		||||
the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be
 | 
			
		||||
included in all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 | 
			
		||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | 
			
		||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | 
			
		||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										36
									
								
								vendor/github.com/markbates/going/defaults/defaults.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/markbates/going/defaults/defaults.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
package defaults
 | 
			
		||||
 | 
			
		||||
func String(s1, s2 string) string {
 | 
			
		||||
	if s1 == "" {
 | 
			
		||||
		return s2
 | 
			
		||||
	}
 | 
			
		||||
	return s1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Int(i1, i2 int) int {
 | 
			
		||||
	if i1 == 0 {
 | 
			
		||||
		return i2
 | 
			
		||||
	}
 | 
			
		||||
	return i1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Int64(i1, i2 int64) int64 {
 | 
			
		||||
	if i1 == 0 {
 | 
			
		||||
		return i2
 | 
			
		||||
	}
 | 
			
		||||
	return i1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Float32(i1, i2 float32) float32 {
 | 
			
		||||
	if i1 == 0.0 {
 | 
			
		||||
		return i2
 | 
			
		||||
	}
 | 
			
		||||
	return i1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Float64(i1, i2 float64) float64 {
 | 
			
		||||
	if i1 == 0.0 {
 | 
			
		||||
		return i2
 | 
			
		||||
	}
 | 
			
		||||
	return i1
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										187
									
								
								vendor/github.com/markbates/goth/providers/azuread/azuread.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								vendor/github.com/markbates/goth/providers/azuread/azuread.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,187 @@
 | 
			
		|||
// Package azuread implements the OAuth2 protocol for authenticating users through AzureAD.
 | 
			
		||||
// This package can be used as a reference implementation of an OAuth2 provider for Goth.
 | 
			
		||||
// To use microsoft personal account use microsoftonline provider
 | 
			
		||||
package azuread
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
	"golang.org/x/oauth2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	authURL          string = "https://login.microsoftonline.com/common/oauth2/authorize"
 | 
			
		||||
	tokenURL         string = "https://login.microsoftonline.com/common/oauth2/token"
 | 
			
		||||
	endpointProfile  string = "https://graph.windows.net/me?api-version=1.6"
 | 
			
		||||
	graphAPIResource string = "https://graph.windows.net/"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// New creates a new AzureAD provider, and sets up important connection details.
 | 
			
		||||
// You should always call `AzureAD.New` to get a new Provider. Never try to create
 | 
			
		||||
// one manually.
 | 
			
		||||
func New(clientKey, secret, callbackURL string, resources []string, scopes ...string) *Provider {
 | 
			
		||||
	p := &Provider{
 | 
			
		||||
		ClientKey:    clientKey,
 | 
			
		||||
		Secret:       secret,
 | 
			
		||||
		CallbackURL:  callbackURL,
 | 
			
		||||
		providerName: "azuread",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p.resources = make([]string, 0, 1+len(resources))
 | 
			
		||||
	p.resources = append(p.resources, graphAPIResource)
 | 
			
		||||
	p.resources = append(p.resources, resources...)
 | 
			
		||||
 | 
			
		||||
	p.config = newConfig(p, scopes)
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Provider is the implementation of `goth.Provider` for accessing AzureAD.
 | 
			
		||||
type Provider struct {
 | 
			
		||||
	ClientKey    string
 | 
			
		||||
	Secret       string
 | 
			
		||||
	CallbackURL  string
 | 
			
		||||
	HTTPClient   *http.Client
 | 
			
		||||
	config       *oauth2.Config
 | 
			
		||||
	providerName string
 | 
			
		||||
	resources    []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name is the name used to retrieve this provider later.
 | 
			
		||||
func (p *Provider) Name() string {
 | 
			
		||||
	return p.providerName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetName is to update the name of the provider (needed in case of multiple providers of 1 type)
 | 
			
		||||
func (p *Provider) SetName(name string) {
 | 
			
		||||
	p.providerName = name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Client is HTTP client to be used in all fetch operations.
 | 
			
		||||
func (p *Provider) Client() *http.Client {
 | 
			
		||||
	return goth.HTTPClientWithFallBack(p.HTTPClient)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Debug is a no-op for the package.
 | 
			
		||||
func (p *Provider) Debug(debug bool) {}
 | 
			
		||||
 | 
			
		||||
// BeginAuth asks AzureAD for an authentication end-point.
 | 
			
		||||
func (p *Provider) BeginAuth(state string) (goth.Session, error) {
 | 
			
		||||
	authURL := p.config.AuthCodeURL(state)
 | 
			
		||||
 | 
			
		||||
	// Azure ad requires at least one resource
 | 
			
		||||
	authURL += "&resource=" + url.QueryEscape(strings.Join(p.resources, " "))
 | 
			
		||||
 | 
			
		||||
	return &Session{
 | 
			
		||||
		AuthURL: authURL,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FetchUser will go to AzureAD and access basic information about the user.
 | 
			
		||||
func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
 | 
			
		||||
	msSession := session.(*Session)
 | 
			
		||||
	user := goth.User{
 | 
			
		||||
		AccessToken: msSession.AccessToken,
 | 
			
		||||
		Provider:    p.Name(),
 | 
			
		||||
		ExpiresAt:   msSession.ExpiresAt,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if user.AccessToken == "" {
 | 
			
		||||
		return user, fmt.Errorf("%s cannot get user information without accessToken", p.providerName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req, err := http.NewRequest("GET", endpointProfile, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return user, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req.Header.Set(authorizationHeader(msSession))
 | 
			
		||||
 | 
			
		||||
	response, err := p.Client().Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return user, err
 | 
			
		||||
	}
 | 
			
		||||
	defer response.Body.Close()
 | 
			
		||||
 | 
			
		||||
	if response.StatusCode != http.StatusOK {
 | 
			
		||||
		return user, fmt.Errorf("%s responded with a %d trying to fetch user information", p.providerName, response.StatusCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = userFromReader(response.Body, &user)
 | 
			
		||||
	return user, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//RefreshTokenAvailable refresh token is provided by auth provider or not
 | 
			
		||||
func (p *Provider) RefreshTokenAvailable() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//RefreshToken get new access token based on the refresh token
 | 
			
		||||
func (p *Provider) RefreshToken(refreshToken string) (*oauth2.Token, error) {
 | 
			
		||||
	token := &oauth2.Token{RefreshToken: refreshToken}
 | 
			
		||||
	ts := p.config.TokenSource(goth.ContextForClient(p.Client()), token)
 | 
			
		||||
	newToken, err := ts.Token()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return newToken, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newConfig(provider *Provider, scopes []string) *oauth2.Config {
 | 
			
		||||
	c := &oauth2.Config{
 | 
			
		||||
		ClientID:     provider.ClientKey,
 | 
			
		||||
		ClientSecret: provider.Secret,
 | 
			
		||||
		RedirectURL:  provider.CallbackURL,
 | 
			
		||||
		Endpoint: oauth2.Endpoint{
 | 
			
		||||
			AuthURL:  authURL,
 | 
			
		||||
			TokenURL: tokenURL,
 | 
			
		||||
		},
 | 
			
		||||
		Scopes: []string{},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(scopes) > 0 {
 | 
			
		||||
		for _, scope := range scopes {
 | 
			
		||||
			c.Scopes = append(c.Scopes, scope)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		c.Scopes = append(c.Scopes, "user_impersonation")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func userFromReader(r io.Reader, user *goth.User) error {
 | 
			
		||||
	u := struct {
 | 
			
		||||
		Name              string `json:"name"`
 | 
			
		||||
		Email             string `json:"mail"`
 | 
			
		||||
		FirstName         string `json:"givenName"`
 | 
			
		||||
		LastName          string `json:"surname"`
 | 
			
		||||
		NickName          string `json:"mailNickname"`
 | 
			
		||||
		UserPrincipalName string `json:"userPrincipalName"`
 | 
			
		||||
		Location          string `json:"usageLocation"`
 | 
			
		||||
	}{}
 | 
			
		||||
 | 
			
		||||
	err := json.NewDecoder(r).Decode(&u)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	user.Email = u.Email
 | 
			
		||||
	user.Name = u.Name
 | 
			
		||||
	user.FirstName = u.FirstName
 | 
			
		||||
	user.LastName = u.LastName
 | 
			
		||||
	user.NickName = u.Name
 | 
			
		||||
	user.Location = u.Location
 | 
			
		||||
	user.UserID = u.UserPrincipalName //AzureAD doesn't provide separate user_id
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func authorizationHeader(session *Session) (string, string) {
 | 
			
		||||
	return "Authorization", fmt.Sprintf("Bearer %s", session.AccessToken)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								vendor/github.com/markbates/goth/providers/azuread/session.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								vendor/github.com/markbates/goth/providers/azuread/session.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
package azuread
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Session is the implementation of `goth.Session` for accessing AzureAD.
 | 
			
		||||
type Session struct {
 | 
			
		||||
	AuthURL      string
 | 
			
		||||
	AccessToken  string
 | 
			
		||||
	RefreshToken string
 | 
			
		||||
	ExpiresAt    time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAuthURL will return the URL set by calling the `BeginAuth` function on the Facebook provider.
 | 
			
		||||
func (s Session) GetAuthURL() (string, error) {
 | 
			
		||||
	if s.AuthURL == "" {
 | 
			
		||||
		return "", errors.New(goth.NoAuthUrlErrorMessage)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s.AuthURL, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Authorize the session with AzureAD and return the access token to be stored for future use.
 | 
			
		||||
func (s *Session) Authorize(provider goth.Provider, params goth.Params) (string, error) {
 | 
			
		||||
	p := provider.(*Provider)
 | 
			
		||||
	token, err := p.config.Exchange(goth.ContextForClient(p.Client()), params.Get("code"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !token.Valid() {
 | 
			
		||||
		return "", errors.New("invalid token received from provider")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.AccessToken = token.AccessToken
 | 
			
		||||
	s.RefreshToken = token.RefreshToken
 | 
			
		||||
	s.ExpiresAt = token.Expiry
 | 
			
		||||
 | 
			
		||||
	return token.AccessToken, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Marshal the session into a string
 | 
			
		||||
func (s Session) Marshal() string {
 | 
			
		||||
	b, _ := json.Marshal(s)
 | 
			
		||||
	return string(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s Session) String() string {
 | 
			
		||||
	return s.Marshal()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalSession wil unmarshal a JSON string into a session.
 | 
			
		||||
func (p *Provider) UnmarshalSession(data string) (goth.Session, error) {
 | 
			
		||||
	session := &Session{}
 | 
			
		||||
	err := json.NewDecoder(strings.NewReader(data)).Decode(session)
 | 
			
		||||
	return session, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										233
									
								
								vendor/github.com/markbates/goth/providers/azureadv2/azureadv2.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								vendor/github.com/markbates/goth/providers/azureadv2/azureadv2.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,233 @@
 | 
			
		|||
package azureadv2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
	"golang.org/x/oauth2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// also https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints
 | 
			
		||||
const (
 | 
			
		||||
	authURLTemplate  string = "https://login.microsoftonline.com/%s/oauth2/v2.0/authorize"
 | 
			
		||||
	tokenURLTemplate string = "https://login.microsoftonline.com/%s/oauth2/v2.0/token"
 | 
			
		||||
	graphAPIResource string = "https://graph.microsoft.com/v1.0/"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type (
 | 
			
		||||
	// TenantType are the well known tenant types to scope the users that can authenticate. TenantType is not an
 | 
			
		||||
	// exclusive list of Azure Tenants which can be used. A consumer can also use their own Tenant ID to scope
 | 
			
		||||
	// authentication to their specific Tenant either through the Tenant ID or the friendly domain name.
 | 
			
		||||
	//
 | 
			
		||||
	// see also https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints
 | 
			
		||||
	TenantType string
 | 
			
		||||
 | 
			
		||||
	// Provider is the implementation of `goth.Provider` for accessing AzureAD V2.
 | 
			
		||||
	Provider struct {
 | 
			
		||||
		ClientKey    string
 | 
			
		||||
		Secret       string
 | 
			
		||||
		CallbackURL  string
 | 
			
		||||
		HTTPClient   *http.Client
 | 
			
		||||
		config       *oauth2.Config
 | 
			
		||||
		providerName string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ProviderOptions are the collection of optional configuration to provide when constructing a Provider
 | 
			
		||||
	ProviderOptions struct {
 | 
			
		||||
		Scopes []ScopeType
 | 
			
		||||
		Tenant TenantType
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// These are the well known Azure AD Tenants. These are not an exclusive list of all Tenants
 | 
			
		||||
//
 | 
			
		||||
// See also https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints
 | 
			
		||||
const (
 | 
			
		||||
	// CommonTenant allows users with both personal Microsoft accounts and work/school accounts from Azure Active
 | 
			
		||||
	// Directory to sign into the application.
 | 
			
		||||
	CommonTenant TenantType = "common"
 | 
			
		||||
 | 
			
		||||
	// OrganizationsTenant allows only users with work/school accounts from Azure Active Directory to sign into the application.
 | 
			
		||||
	OrganizationsTenant TenantType = "organizations"
 | 
			
		||||
 | 
			
		||||
	// ConsumersTenant allows only users with personal Microsoft accounts (MSA) to sign into the application.
 | 
			
		||||
	ConsumersTenant TenantType = "consumers"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// New creates a new AzureAD provider, and sets up important connection details.
 | 
			
		||||
// You should always call `AzureAD.New` to get a new Provider. Never try to create
 | 
			
		||||
// one manually.
 | 
			
		||||
func New(clientKey, secret, callbackURL string, opts ProviderOptions) *Provider {
 | 
			
		||||
	p := &Provider{
 | 
			
		||||
		ClientKey:    clientKey,
 | 
			
		||||
		Secret:       secret,
 | 
			
		||||
		CallbackURL:  callbackURL,
 | 
			
		||||
		providerName: "azureadv2",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p.config = newConfig(p, opts)
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newConfig(provider *Provider, opts ProviderOptions) *oauth2.Config {
 | 
			
		||||
	tenant := opts.Tenant
 | 
			
		||||
	if tenant == "" {
 | 
			
		||||
		tenant = CommonTenant
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c := &oauth2.Config{
 | 
			
		||||
		ClientID:     provider.ClientKey,
 | 
			
		||||
		ClientSecret: provider.Secret,
 | 
			
		||||
		RedirectURL:  provider.CallbackURL,
 | 
			
		||||
		Endpoint: oauth2.Endpoint{
 | 
			
		||||
			AuthURL:  fmt.Sprintf(authURLTemplate, tenant),
 | 
			
		||||
			TokenURL: fmt.Sprintf(tokenURLTemplate, tenant),
 | 
			
		||||
		},
 | 
			
		||||
		Scopes: []string{},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opts.Scopes) > 0 {
 | 
			
		||||
		c.Scopes = append(c.Scopes, scopesToStrings(opts.Scopes...)...)
 | 
			
		||||
	} else {
 | 
			
		||||
		defaultScopes := scopesToStrings(OpenIDScope, ProfileScope, EmailScope, UserReadScope)
 | 
			
		||||
		c.Scopes = append(c.Scopes, defaultScopes...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name is the name used to retrieve this provider later.
 | 
			
		||||
func (p *Provider) Name() string {
 | 
			
		||||
	return p.providerName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetName is to update the name of the provider (needed in case of multiple providers of 1 type)
 | 
			
		||||
func (p *Provider) SetName(name string) {
 | 
			
		||||
	p.providerName = name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Client is HTTP client to be used in all fetch operations.
 | 
			
		||||
func (p *Provider) Client() *http.Client {
 | 
			
		||||
	return goth.HTTPClientWithFallBack(p.HTTPClient)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Debug is a no-op for the package
 | 
			
		||||
func (p *Provider) Debug(debug bool) {}
 | 
			
		||||
 | 
			
		||||
// BeginAuth asks for an authentication end-point for AzureAD.
 | 
			
		||||
func (p *Provider) BeginAuth(state string) (goth.Session, error) {
 | 
			
		||||
	authURL := p.config.AuthCodeURL(state)
 | 
			
		||||
 | 
			
		||||
	return &Session{
 | 
			
		||||
		AuthURL: authURL,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FetchUser will go to AzureAD and access basic information about the user.
 | 
			
		||||
func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
 | 
			
		||||
	msSession := session.(*Session)
 | 
			
		||||
	user := goth.User{
 | 
			
		||||
		AccessToken: msSession.AccessToken,
 | 
			
		||||
		Provider:    p.Name(),
 | 
			
		||||
		ExpiresAt:   msSession.ExpiresAt,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if user.AccessToken == "" {
 | 
			
		||||
		return user, fmt.Errorf("%s cannot get user information without accessToken", p.providerName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req, err := http.NewRequest("GET", graphAPIResource+"me", nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return user, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req.Header.Set(authorizationHeader(msSession))
 | 
			
		||||
 | 
			
		||||
	response, err := p.Client().Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return user, err
 | 
			
		||||
	}
 | 
			
		||||
	defer response.Body.Close()
 | 
			
		||||
 | 
			
		||||
	if response.StatusCode != http.StatusOK {
 | 
			
		||||
		return user, fmt.Errorf("%s responded with a %d trying to fetch user information", p.providerName, response.StatusCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = userFromReader(response.Body, &user)
 | 
			
		||||
	user.AccessToken = msSession.AccessToken
 | 
			
		||||
	user.RefreshToken = msSession.RefreshToken
 | 
			
		||||
	user.ExpiresAt = msSession.ExpiresAt
 | 
			
		||||
	return user, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//RefreshTokenAvailable refresh token is provided by auth provider or not
 | 
			
		||||
func (p *Provider) RefreshTokenAvailable() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//RefreshToken get new access token based on the refresh token
 | 
			
		||||
func (p *Provider) RefreshToken(refreshToken string) (*oauth2.Token, error) {
 | 
			
		||||
	token := &oauth2.Token{RefreshToken: refreshToken}
 | 
			
		||||
	ts := p.config.TokenSource(goth.ContextForClient(p.Client()), token)
 | 
			
		||||
	newToken, err := ts.Token()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return newToken, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func authorizationHeader(session *Session) (string, string) {
 | 
			
		||||
	return "Authorization", fmt.Sprintf("Bearer %s", session.AccessToken)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func userFromReader(r io.Reader, user *goth.User) error {
 | 
			
		||||
	u := struct {
 | 
			
		||||
		ID                string   `json:"id"`                // The unique identifier for the user.
 | 
			
		||||
		BusinessPhones    []string `json:"businessPhones"`    // The user's phone numbers.
 | 
			
		||||
		DisplayName       string   `json:"displayName"`       // The name displayed in the address book for the user.
 | 
			
		||||
		FirstName         string   `json:"givenName"`         // The first name of the user.
 | 
			
		||||
		JobTitle          string   `json:"jobTitle"`          // The user's job title.
 | 
			
		||||
		Email             string   `json:"mail"`              // The user's email address.
 | 
			
		||||
		MobilePhone       string   `json:"mobilePhone"`       // The user's cellphone number.
 | 
			
		||||
		OfficeLocation    string   `json:"officeLocation"`    // The user's physical office location.
 | 
			
		||||
		PreferredLanguage string   `json:"preferredLanguage"` // The user's language of preference.
 | 
			
		||||
		LastName          string   `json:"surname"`           // The last name of the user.
 | 
			
		||||
		UserPrincipalName string   `json:"userPrincipalName"` // The user's principal name.
 | 
			
		||||
	}{}
 | 
			
		||||
 | 
			
		||||
	userBytes, err := ioutil.ReadAll(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := json.Unmarshal(userBytes, &u); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	user.Email = u.Email
 | 
			
		||||
	user.Name = u.DisplayName
 | 
			
		||||
	user.FirstName = u.FirstName
 | 
			
		||||
	user.LastName = u.LastName
 | 
			
		||||
	user.NickName = u.DisplayName
 | 
			
		||||
	user.Location = u.OfficeLocation
 | 
			
		||||
	user.UserID = u.ID
 | 
			
		||||
	user.AvatarURL = graphAPIResource + fmt.Sprintf("users/%s/photo/$value", u.ID)
 | 
			
		||||
	// Make sure all of the information returned is available via RawData
 | 
			
		||||
	if err := json.Unmarshal(userBytes, &user.RawData); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scopesToStrings(scopes ...ScopeType) []string {
 | 
			
		||||
	strs := make([]string, len(scopes))
 | 
			
		||||
	for i := 0; i < len(scopes); i++ {
 | 
			
		||||
		strs[i] = string(scopes[i])
 | 
			
		||||
	}
 | 
			
		||||
	return strs
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										714
									
								
								vendor/github.com/markbates/goth/providers/azureadv2/scopes.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										714
									
								
								vendor/github.com/markbates/goth/providers/azureadv2/scopes.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,714 @@
 | 
			
		|||
package azureadv2
 | 
			
		||||
 | 
			
		||||
type (
 | 
			
		||||
	// ScopeType are the well known scopes which can be requested
 | 
			
		||||
	ScopeType string
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// OpenID Permissions
 | 
			
		||||
//
 | 
			
		||||
// You can use these permissions to specify artifacts that you want returned in Azure AD authorization and token
 | 
			
		||||
// requests. They are supported differently by the Azure AD v1.0 and v2.0 endpoints.
 | 
			
		||||
//
 | 
			
		||||
// With the Azure AD (v1.0) endpoint, only the openid permission is used. You specify it in the scope parameter in an
 | 
			
		||||
// authorization request to return an ID token when you use the OpenID Connect protocol to sign in a user to your app.
 | 
			
		||||
// For more information, see Authorize access to web applications using OpenID Connect and Azure Active Directory. To
 | 
			
		||||
// successfully return an ID token, you must also make sure that the User.Read permission is configured when you
 | 
			
		||||
// register your app.
 | 
			
		||||
//
 | 
			
		||||
// With the Azure AD v2.0 endpoint, you specify the offline_access permission in the scope parameter to explicitly
 | 
			
		||||
// request a refresh token when using the OAuth 2.0 or OpenID Connect protocols. With OpenID Connect, you specify the
 | 
			
		||||
// openid permission to request an ID token. You can also specify the email permission, profile permission, or both to
 | 
			
		||||
// return additional claims in the ID token. You do not need to specify User.Read to return an ID token with the v2.0
 | 
			
		||||
// endpoint. For more information, see OpenID Connect scopes.
 | 
			
		||||
const (
 | 
			
		||||
	// OpenIDScope shows on the work account consent page as the "Sign you in" permission, and on the personal Microsoft
 | 
			
		||||
	// account consent page as the "View your profile and connect to apps and services using your Microsoft account"
 | 
			
		||||
	// permission. With this permission, an app can receive a unique identifier for the user in the form of the sub
 | 
			
		||||
	// claim. It also gives the app access to the UserInfo endpoint. The openid scope can be used at the v2.0 token
 | 
			
		||||
	// endpoint to acquire ID tokens, which can be used to secure HTTP calls between different components of an app.
 | 
			
		||||
	OpenIDScope ScopeType = "openid"
 | 
			
		||||
 | 
			
		||||
	// EmailScope can be used with the openid scope and any others. It gives the app access to the user's primary
 | 
			
		||||
	// email address in the form of the email claim. The email claim is included in a token only if an email address is
 | 
			
		||||
	// associated with the user account, which is not always the case. If it uses the email scope, your app should be
 | 
			
		||||
	// prepared to handle a case in which the email claim does not exist in the token.
 | 
			
		||||
	EmailScope ScopeType = "email"
 | 
			
		||||
 | 
			
		||||
	// ProfileScope can be used with the openid scope and any others. It gives the app access to a substantial
 | 
			
		||||
	// amount of information about the user. The information it can access includes, but is not limited to, the user's
 | 
			
		||||
	// given name, surname, preferred username, and object ID. For a complete list of the profile claims available in
 | 
			
		||||
	// the id_tokens parameter for a specific user, see the v2.0 tokens reference:
 | 
			
		||||
	// https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-id-and-access-tokens.
 | 
			
		||||
	ProfileScope ScopeType = "profile"
 | 
			
		||||
 | 
			
		||||
	// OfflineAccessScope gives your app access to resources on behalf of the user for an extended time. On the work
 | 
			
		||||
	// account consent page, this scope appears as the "Access your data anytime" permission. On the personal Microsoft
 | 
			
		||||
	// account consent page, it appears as the "Access your info anytime" permission. When a user approves the
 | 
			
		||||
	// offline_access scope, your app can receive refresh tokens from the v2.0 token endpoint. Refresh tokens are
 | 
			
		||||
	// long-lived. Your app can get new access tokens as older ones expire.
 | 
			
		||||
	//
 | 
			
		||||
	// If your app does not request the offline_access scope, it won't receive refresh tokens. This means that when you
 | 
			
		||||
	// redeem an authorization code in the OAuth 2.0 authorization code flow, you'll receive only an access token from
 | 
			
		||||
	// the /token endpoint. The access token is valid for a short time. The access token usually expires in one hour.
 | 
			
		||||
	// At that point, your app needs to redirect the user back to the /authorize endpoint to get a new authorization
 | 
			
		||||
	// code. During this redirect, depending on the type of app, the user might need to enter their credentials again
 | 
			
		||||
	// or consent again to permissions.
 | 
			
		||||
	OfflineAccessScope ScopeType = "offline_access"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Calendar Permissions
 | 
			
		||||
//
 | 
			
		||||
// Calendars.Read.Shared and Calendars.ReadWrite.Shared are only valid for work or school accounts. All other
 | 
			
		||||
// permissions are valid for both Microsoft accounts and work or school accounts.
 | 
			
		||||
//
 | 
			
		||||
// See also https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference
 | 
			
		||||
const (
 | 
			
		||||
	// CalendarsReadScope allows the app to read events in user calendars.
 | 
			
		||||
	CalendarsReadScope ScopeType = "Calendars.Read"
 | 
			
		||||
 | 
			
		||||
	// CalendarsReadSharedScope allows the app to read events in all calendars that the user can access, including
 | 
			
		||||
	// delegate and shared calendars.
 | 
			
		||||
	CalendarsReadSharedScope ScopeType = "Calendars.Read.Shared"
 | 
			
		||||
 | 
			
		||||
	// CalendarsReadWriteScope allows the app to create, read, update, and delete events in user calendars.
 | 
			
		||||
	CalendarsReadWriteScope ScopeType = "Calendars.ReadWrite"
 | 
			
		||||
 | 
			
		||||
	// CalendarsReadWriteSharedScope allows the app to create, read, update and delete events in all calendars the user
 | 
			
		||||
	// has permissions to access. This includes delegate and shared calendars.
 | 
			
		||||
	CalendarsReadWriteSharedScope ScopeType = "Calendars.ReadWrite.Shared"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Contacts Permissions
 | 
			
		||||
//
 | 
			
		||||
// Only the Contacts.Read and Contacts.ReadWrite delegated permissions are valid for Microsoft accounts.
 | 
			
		||||
//
 | 
			
		||||
// See also https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference
 | 
			
		||||
const (
 | 
			
		||||
	// ContactsReadScope allows the app to read contacts that the user has permissions to access, including the user's
 | 
			
		||||
	// own and shared contacts.
 | 
			
		||||
	ContactsReadScope ScopeType = "Contacts.Read"
 | 
			
		||||
 | 
			
		||||
	// ContactsReadSharedScope allows the app to read contacts that the user has permissions to access, including the
 | 
			
		||||
	// user's own and shared contacts.
 | 
			
		||||
	ContactsReadSharedScope ScopeType = "Contacts.Read.Shared"
 | 
			
		||||
 | 
			
		||||
	// ContactsReadWriteScope allows the app to create, read, update, and delete user contacts.
 | 
			
		||||
	ContactsReadWriteScope ScopeType = "Contacts.ReadWrite"
 | 
			
		||||
 | 
			
		||||
	// ContactsReadWriteSharedScope allows the app to create, read, update and delete contacts that the user has
 | 
			
		||||
	// permissions to, including the user's own and shared contacts.
 | 
			
		||||
	ContactsReadWriteSharedScope ScopeType = "Contacts.ReadWrite.Shared"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Device Permissions
 | 
			
		||||
//
 | 
			
		||||
// The Device.Read and Device.Command delegated permissions are valid only for personal Microsoft accounts.
 | 
			
		||||
//
 | 
			
		||||
// See also https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference
 | 
			
		||||
const (
 | 
			
		||||
	// DeviceReadScope allows the app to read a user's list of devices on behalf of the signed-in user.
 | 
			
		||||
	DeviceReadScope ScopeType = "Device.Read"
 | 
			
		||||
 | 
			
		||||
	// DeviceCommandScope allows the app to launch another app or communicate with another app on a user's device on
 | 
			
		||||
	// behalf of the signed-in user.
 | 
			
		||||
	DeviceCommandScope ScopeType = "Device.Command"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Directory Permissions
 | 
			
		||||
//
 | 
			
		||||
// Directory permissions are not supported on Microsoft accounts.
 | 
			
		||||
//
 | 
			
		||||
// Directory permissions provide the highest level of privilege for accessing directory resources such as User, Group,
 | 
			
		||||
// and Device in an organization.
 | 
			
		||||
//
 | 
			
		||||
// They also exclusively control access to other directory resources like: organizational contacts, schema extension
 | 
			
		||||
// APIs, Privileged Identity Management (PIM) APIs, as well as many of the resources and APIs listed under the Azure
 | 
			
		||||
// Active Directory node in the v1.0 and beta API reference documentation. These include administrative units, directory
 | 
			
		||||
// roles, directory settings, policy, and many more.
 | 
			
		||||
//
 | 
			
		||||
// The Directory.ReadWrite.All permission grants the following privileges:
 | 
			
		||||
//  - Full read of all directory resources (both declared properties and navigation properties)
 | 
			
		||||
//  - Create and update users
 | 
			
		||||
//  - Disable and enable users (but not company administrator)
 | 
			
		||||
//  - Set user alternative security id (but not administrators)
 | 
			
		||||
//  - Create and update groups
 | 
			
		||||
//  - Manage group memberships
 | 
			
		||||
//  - Update group owner
 | 
			
		||||
//  - Manage license assignments
 | 
			
		||||
//  - Define schema extensions on applications
 | 
			
		||||
//  - Note: No rights to reset user passwords
 | 
			
		||||
//  - Note: No rights to delete resources (including users or groups)
 | 
			
		||||
//  - Note: Specifically excludes create or update for resources not listed above. This includes: application,
 | 
			
		||||
//    oAauth2Permissiongrant, appRoleAssignment, device, servicePrincipal, organization, domains, and so on.
 | 
			
		||||
//
 | 
			
		||||
// See also https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference
 | 
			
		||||
const (
 | 
			
		||||
	// DirectoryReadAllScope allows the app to read data in your organization's directory, such as users, groups and
 | 
			
		||||
	// apps.
 | 
			
		||||
	//
 | 
			
		||||
	// Note: Users may consent to applications that require this permission if the application is registered in their
 | 
			
		||||
	// own organization’s tenant.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DirectoryReadAllScope ScopeType = "Directory.Read.All"
 | 
			
		||||
 | 
			
		||||
	// DirectoryReadWriteAllScope allows the app to read and write data in your organization's directory, such as users,
 | 
			
		||||
	// and groups. It does not allow the app to delete users or groups, or reset user passwords.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DirectoryReadWriteAllScope ScopeType = "Directory.ReadWrite.All"
 | 
			
		||||
 | 
			
		||||
	// DirectoryAccessAsUserAllScope allows the app to have the same access to information in the directory as the
 | 
			
		||||
	// signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DirectoryAccessAsUserAllScope ScopeType = "Directory.AccessAsUser.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Education Administration Permissions
 | 
			
		||||
const (
 | 
			
		||||
	// EduAdministrationReadScope allows the app to read education app settings on behalf of the user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	EduAdministrationReadScope ScopeType = "EduAdministration.Read"
 | 
			
		||||
 | 
			
		||||
	// EduAdministrationReadWriteScope allows the app to manage education app settings on behalf of the user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	EduAdministrationReadWriteScope ScopeType = "EduAdministration.ReadWrite"
 | 
			
		||||
 | 
			
		||||
	// EduAssignmentsReadBasicScope allows the app to read assignments without grades on behalf of the user
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	EduAssignmentsReadBasicScope ScopeType = "EduAssignments.ReadBasic"
 | 
			
		||||
 | 
			
		||||
	// EduAssignmentsReadWriteBasicScope allows the app to read and write assignments without grades on behalf of the
 | 
			
		||||
	// user
 | 
			
		||||
	EduAssignmentsReadWriteBasicScope ScopeType = "EduAssignments.ReadWriteBasic"
 | 
			
		||||
 | 
			
		||||
	// EduAssignmentsReadScope allows the app to read assignments and their grades on behalf of the user
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	EduAssignmentsReadScope ScopeType = "EduAssignments.Read"
 | 
			
		||||
 | 
			
		||||
	// EduAssignmentsReadWriteScope allows the app to read and write assignments and their grades on behalf of the user
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	EduAssignmentsReadWriteScope ScopeType = "EduAssignments.ReadWrite"
 | 
			
		||||
 | 
			
		||||
	// EduRosteringReadBasicScope allows the app to read a limited subset of the data from the  structure of schools and
 | 
			
		||||
	// classes in an organization's roster and  education-specific information about users to be read on behalf of the
 | 
			
		||||
	// user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	EduRosteringReadBasicScope ScopeType = "EduRostering.ReadBasic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Files Permissions
 | 
			
		||||
//
 | 
			
		||||
// The Files.Read, Files.ReadWrite, Files.Read.All, and Files.ReadWrite.All delegated permissions are valid on both
 | 
			
		||||
// personal Microsoft accounts and work or school accounts. Note that for personal accounts, Files.Read and
 | 
			
		||||
// Files.ReadWrite also grant access to files shared with the signed-in user.
 | 
			
		||||
//
 | 
			
		||||
// The Files.Read.Selected and Files.ReadWrite.Selected delegated permissions are only valid on work or school accounts
 | 
			
		||||
// and are only exposed for working with Office 365 file handlers (v1.0)
 | 
			
		||||
// https://msdn.microsoft.com/office/office365/howto/using-cross-suite-apps. They should not be used for directly
 | 
			
		||||
// calling Microsoft Graph APIs.
 | 
			
		||||
//
 | 
			
		||||
// The Files.ReadWrite.AppFolder delegated permission is only valid for personal accounts and is used for accessing the
 | 
			
		||||
// App Root special folder https://dev.onedrive.com/misc/appfolder.htm with the OneDrive Get special folder
 | 
			
		||||
// https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/drive_get_specialfolder Microsoft Graph API.
 | 
			
		||||
const (
 | 
			
		||||
	// FilesReadScope allows the app to read the signed-in user's files.
 | 
			
		||||
	FilesReadScope ScopeType = "Files.Read"
 | 
			
		||||
 | 
			
		||||
	// FilesReadAllScope allows the app to read all files the signed-in user can access.
 | 
			
		||||
	FilesReadAllScope ScopeType = "Files.Read.All"
 | 
			
		||||
 | 
			
		||||
	// FilesReadWrite allows the app to read, create, update, and delete the signed-in user's files.
 | 
			
		||||
	FilesReadWriteScope ScopeType = "Files.ReadWrite"
 | 
			
		||||
 | 
			
		||||
	// FilesReadWriteAllScope allows the app to read, create, update, and delete all files the signed-in user can access.
 | 
			
		||||
	FilesReadWriteAllScope ScopeType = "Files.ReadWrite.All"
 | 
			
		||||
 | 
			
		||||
	// FilesReadWriteAppFolderScope allows the app to read, create, update, and delete files in the application's folder.
 | 
			
		||||
	FilesReadWriteAppFolderScope ScopeType = "Files.ReadWrite.AppFolder"
 | 
			
		||||
 | 
			
		||||
	// FilesReadSelectedScope allows the app to read files that the user selects. The app has access for several hours
 | 
			
		||||
	// after the user selects a file.
 | 
			
		||||
	//
 | 
			
		||||
	// preview
 | 
			
		||||
	FilesReadSelectedScope ScopeType = "Files.Read.Selected"
 | 
			
		||||
 | 
			
		||||
	// FilesReadWriteSelectedScope allows the app to read and write files that the user selects. The app has access for
 | 
			
		||||
	// several hours after the user selects a file
 | 
			
		||||
	//
 | 
			
		||||
	// preview
 | 
			
		||||
	FilesReadWriteSelectedScope ScopeType = "Files.ReadWrite.Selected"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Group Permissions
 | 
			
		||||
//
 | 
			
		||||
// Group functionality is not supported on personal Microsoft accounts.
 | 
			
		||||
//
 | 
			
		||||
// For Office 365 groups, Group permissions grant the app access to the contents of the group; for example,
 | 
			
		||||
// conversations, files, notes, and so on.
 | 
			
		||||
//
 | 
			
		||||
// For application permissions, there are some limitations for the APIs that are supported. For more information, see
 | 
			
		||||
// known issues.
 | 
			
		||||
//
 | 
			
		||||
// In some cases, an app may need Directory permissions to read some group properties like member and memberOf. For
 | 
			
		||||
// example, if a group has a one or more servicePrincipals as members, the app will need effective permissions to read
 | 
			
		||||
// service principals through being granted one of the Directory.* permissions, otherwise Microsoft Graph will return an
 | 
			
		||||
// error. (In the case of delegated permissions, the signed-in user will also need sufficient privileges in the
 | 
			
		||||
// organization to read service principals.) The same guidance applies for the memberOf property, which can return
 | 
			
		||||
// administrativeUnits.
 | 
			
		||||
//
 | 
			
		||||
// Group permissions are also used to control access to Microsoft Planner resources and APIs. Only delegated permissions
 | 
			
		||||
// are supported for Microsoft Planner APIs; application permissions are not supported. Personal Microsoft accounts are
 | 
			
		||||
// not supported.
 | 
			
		||||
const (
 | 
			
		||||
	// GroupReadAllScope allows the app to list groups, and to read their properties and all group memberships on behalf
 | 
			
		||||
	// of the signed-in user.  Also allows the app to read calendar, conversations, files, and other group content for
 | 
			
		||||
	// all groups the signed-in user can access.
 | 
			
		||||
	GroupReadAllScope ScopeType = "Group.Read.All"
 | 
			
		||||
 | 
			
		||||
	// GroupReadWriteAllScope allows the app to create groups and read all group properties and memberships on behalf of
 | 
			
		||||
	// the signed-in user.  Additionally allows group owners to manage their groups and allows group members to update
 | 
			
		||||
	// group content.
 | 
			
		||||
	GroupReadWriteAllScope ScopeType = "Group.ReadWrite.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Identity Risk Event Permissions
 | 
			
		||||
//
 | 
			
		||||
// IdentityRiskEvent.Read.All is valid only for work or school accounts. For an app with delegated permissions to read
 | 
			
		||||
// identity risk information, the signed-in user must be a member of one of the following administrator roles: Global
 | 
			
		||||
// Administrator, Security Administrator, or Security Reader. For more information about administrator roles, see
 | 
			
		||||
// Assigning administrator roles in Azure Active Directory.
 | 
			
		||||
const (
 | 
			
		||||
	// IdentityRiskEventReadAllScope allows the app to read identity risk event information for all users in your
 | 
			
		||||
	// organization on behalf of the signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	IdentityRiskEventReadAllScope ScopeType = "IdentityRiskEvent.Read.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Identity Provider Permissions
 | 
			
		||||
//
 | 
			
		||||
// IdentityProvider.Read.All and IdentityProvider.ReadWrite.All are valid only for work or school accounts. For an app
 | 
			
		||||
// to read or write identity providers with delegated permissions, the signed-in user must be assigned the Global
 | 
			
		||||
// Administrator role. For more information about administrator roles, see Assigning administrator roles in Azure Active
 | 
			
		||||
// Directory.
 | 
			
		||||
const (
 | 
			
		||||
	// IdentityProviderReadAllScope allows the app to read identity providers configured in your Azure AD or Azure AD
 | 
			
		||||
	// B2C tenant on behalf of the signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	IdentityProviderReadAllScope ScopeType = "IdentityProvider.Read.All"
 | 
			
		||||
 | 
			
		||||
	// IdentityProviderReadWriteAllScope allows the app to read or write identity providers configured in your Azure AD
 | 
			
		||||
	// or Azure AD B2C tenant on behalf of the signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	IdentityProviderReadWriteAllScope ScopeType = "IdentityProvider.ReadWrite.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Device Management Permissions
 | 
			
		||||
//
 | 
			
		||||
// Using the Microsoft Graph APIs to configure Intune controls and policies still requires that the Intune service is
 | 
			
		||||
// correctly licensed by the customer.
 | 
			
		||||
//
 | 
			
		||||
// These permissions are only valid for work or school accounts.
 | 
			
		||||
const (
 | 
			
		||||
	// DeviceManagementAppsReadAllScope allows the app to read the properties, group assignments and status of apps, app
 | 
			
		||||
	// configurations and app protection policies managed by Microsoft Intune.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementAppsReadAllScope ScopeType = "DeviceManagementApps.Read.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementAppsReadWriteAllScope allows the app to read and write the properties, group assignments and
 | 
			
		||||
	// status of apps, app configurations and app protection policies managed by Microsoft Intune.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementAppsReadWriteAllScope ScopeType = "DeviceManagementApps.ReadWrite.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementConfigurationReadAllScope allows the app to read properties of Microsoft Intune-managed device
 | 
			
		||||
	// configuration and device compliance policies and their assignment to groups.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementConfigurationReadAllScope ScopeType = "DeviceManagementConfiguration.Read.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementConfigurationReadWriteAllScope allows the app to read and write properties of Microsoft
 | 
			
		||||
	// Intune-managed device configuration and device compliance policies and their assignment to groups.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementConfigurationReadWriteAllScope ScopeType = "DeviceManagementConfiguration.ReadWrite.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementManagedDevicesPrivilegedOperationsAllScope allows the app to perform remote high impact actions
 | 
			
		||||
	// such as wiping the device or resetting the passcode on devices managed by Microsoft Intune.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementManagedDevicesPrivilegedOperationsAllScope ScopeType = "DeviceManagementManagedDevices.PrivilegedOperations.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementManagedDevicesReadAllScope allows the app to read the properties of devices managed by Microsoft
 | 
			
		||||
	// Intune.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementManagedDevicesReadAllScope ScopeType = "DeviceManagementManagedDevices.Read.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementManagedDevicesReadWriteAllScope allows the app to read and write the properties of devices
 | 
			
		||||
	// managed by Microsoft Intune. Does not allow high impact operations such as remote wipe and password reset on the
 | 
			
		||||
	// device’s owner.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementManagedDevicesReadWriteAllScope ScopeType = "DeviceManagementManagedDevices.ReadWrite.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementRBACReadAllScope allows the app to read the properties relating to the Microsoft Intune
 | 
			
		||||
	// Role-Based Access Control (RBAC) settings.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementRBACReadAllScope ScopeType = "DeviceManagementRBAC.Read.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementRBACReadWriteAllScope allows the app to read and write the properties relating to the Microsoft
 | 
			
		||||
	// Intune Role-Based Access Control (RBAC) settings.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementRBACReadWriteAllScope ScopeType = "DeviceManagementRBAC.ReadWrite.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementServiceConfigReadAllScope allows the app to read Intune service properties including device
 | 
			
		||||
	// enrollment and third party service connection configuration.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementServiceConfigReadAllScope ScopeType = "DeviceManagementServiceConfig.Read.All"
 | 
			
		||||
 | 
			
		||||
	// DeviceManagementServiceConfigReadWriteAllScope allows the app to read and write Microsoft Intune service
 | 
			
		||||
	// properties including device enrollment and third party service connection configuration.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	DeviceManagementServiceConfigReadWriteAllScope ScopeType = "DeviceManagementServiceConfig.ReadWrite.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Mail Permissions
 | 
			
		||||
//
 | 
			
		||||
// Mail.Read.Shared, Mail.ReadWrite.Shared, and Mail.Send.Shared are only valid for work or school accounts. All other
 | 
			
		||||
// permissions are valid for both Microsoft accounts and work or school accounts.
 | 
			
		||||
//
 | 
			
		||||
// With the Mail.Send or Mail.Send.Shared permission, an app can send mail and save a copy to the user's Sent Items
 | 
			
		||||
// folder, even if the app does not use a corresponding Mail.ReadWrite or Mail.ReadWrite.Shared permission.
 | 
			
		||||
const (
 | 
			
		||||
	// MailReadScope allows the app to read email in user mailboxes.
 | 
			
		||||
	MailReadScope ScopeType = "Mail.Read"
 | 
			
		||||
 | 
			
		||||
	// MailReadWriteScope allows the app to create, read, update, and delete email in user mailboxes. Does not include
 | 
			
		||||
	// permission to send mail.
 | 
			
		||||
	MailReadWriteScope ScopeType = "Mail.ReadWrite"
 | 
			
		||||
 | 
			
		||||
	// MailReadSharedScope allows the app to read mail that the user can access, including the user's own and shared
 | 
			
		||||
	// mail.
 | 
			
		||||
	MailReadSharedScope ScopeType = "Mail.Read.Shared"
 | 
			
		||||
 | 
			
		||||
	// MailReadWriteSharedScope allows the app to create, read, update, and delete mail that the user has permission to
 | 
			
		||||
	// access, including the user's own and shared mail. Does not include permission to send mail.
 | 
			
		||||
	MailReadWriteSharedScope ScopeType = "Mail.ReadWrite.Shared"
 | 
			
		||||
 | 
			
		||||
	// MailSend allowsScope the app to send mail as users in the organization.
 | 
			
		||||
	MailSendScope ScopeType = "Mail.Send"
 | 
			
		||||
 | 
			
		||||
	// MailSendSharedScope allows the app to send mail as the signed-in user, including sending on-behalf of others.
 | 
			
		||||
	MailSendSharedScope ScopeType = "Mail.Send.Shared"
 | 
			
		||||
 | 
			
		||||
	// MailboxSettingsReadScope allows the app to the read user's mailbox settings. Does not include permission to send
 | 
			
		||||
	// mail.
 | 
			
		||||
	MailboxSettingsReadScope ScopeType = "Mailbox.Settings.Read"
 | 
			
		||||
 | 
			
		||||
	// MailboxSettingsReadWriteScope allows the app to create, read, update, and delete user's mailbox settings. Does
 | 
			
		||||
	// not include permission to directly send mail, but allows the app to create rules that can forward or redirect
 | 
			
		||||
	// messages.
 | 
			
		||||
	MailboxSettingsReadWriteScope ScopeType = "MailboxSettings.ReadWrite"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Member Permissions
 | 
			
		||||
//
 | 
			
		||||
// Member.Read.Hidden is valid only on work or school accounts.
 | 
			
		||||
//
 | 
			
		||||
// Membership in some Office 365 groups can be hidden. This means that only the members of the group can view its
 | 
			
		||||
// members. This feature can be used to help comply with regulations that require an organization to hide group
 | 
			
		||||
// membership from outsiders (for example, an Office 365 group that represents students enrolled in a class).
 | 
			
		||||
const (
 | 
			
		||||
	// MemberReadHiddenScope allows the app to read the memberships of hidden groups and administrative units on behalf
 | 
			
		||||
	// of the signed-in user, for those hidden groups and administrative units that the signed-in user has access to.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	MemberReadHiddenScope ScopeType = "Member.Read.Hidden"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Notes Permissions
 | 
			
		||||
//
 | 
			
		||||
// Notes.Read.All and Notes.ReadWrite.All are only valid for work or school accounts. All other permissions are valid
 | 
			
		||||
// for both Microsoft accounts and work or school accounts.
 | 
			
		||||
//
 | 
			
		||||
// With the Notes.Create permission, an app can view the OneNote notebook hierarchy of the signed-in user and create
 | 
			
		||||
// OneNote content (notebooks, section groups, sections, pages, etc.).
 | 
			
		||||
//
 | 
			
		||||
// Notes.ReadWrite and Notes.ReadWrite.All also allow the app to modify the permissions on the OneNote content that can
 | 
			
		||||
// be accessed by the signed-in user.
 | 
			
		||||
//
 | 
			
		||||
// For work or school accounts, Notes.Read.All and Notes.ReadWrite.All allow the app to access other users' OneNote
 | 
			
		||||
// content that the signed-in user has permission to within the organization.
 | 
			
		||||
const (
 | 
			
		||||
	// NotesReadScope allows the app to read OneNote notebooks on behalf of the signed-in user.
 | 
			
		||||
	NotesReadScope ScopeType = "Notes.Read"
 | 
			
		||||
 | 
			
		||||
	// NotesCreateScope allows the app to read the titles of OneNote notebooks and sections and to create new pages,
 | 
			
		||||
	// notebooks, and sections on behalf of the signed-in user.
 | 
			
		||||
	NotesCreateScope ScopeType = "Notes.Create"
 | 
			
		||||
 | 
			
		||||
	// NotesReadWriteScope allows the app to read, share, and modify OneNote notebooks on behalf of the signed-in user.
 | 
			
		||||
	NotesReadWriteScope ScopeType = "Notes.ReadWrite"
 | 
			
		||||
 | 
			
		||||
	// NotesReadAllScope allows the app to read OneNote notebooks that the signed-in user has access to in the
 | 
			
		||||
	// organization.
 | 
			
		||||
	NotesReadAllScope ScopeType = "Notes.Read.All"
 | 
			
		||||
 | 
			
		||||
	// NotesReadWriteAllScope allows the app to read, share, and modify OneNote notebooks that the signed-in user has
 | 
			
		||||
	// access to in the organization.
 | 
			
		||||
	NotesReadWriteAllScope ScopeType = "Notes.ReadWrite.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// People Permissions
 | 
			
		||||
//
 | 
			
		||||
// The People.Read.All permission is only valid for work and school accounts.
 | 
			
		||||
const (
 | 
			
		||||
	// PeopleReadScope allows the app to read a scored list of people relevant to the signed-in user. The list can
 | 
			
		||||
	// include local contacts, contacts from social networking or your organization's directory, and people from recent
 | 
			
		||||
	// communications (such as email and Skype).
 | 
			
		||||
	PeopleReadScope ScopeType = "People.Read"
 | 
			
		||||
 | 
			
		||||
	// PeopleReadAllScope allows the app to read a scored list of people relevant to the signed-in user or other users
 | 
			
		||||
	// in the signed-in user's organization. The list can include local contacts, contacts from social networking or
 | 
			
		||||
	// your organization's directory, and people from recent communications (such as email and Skype). Also allows the
 | 
			
		||||
	// app to search the entire directory of the signed-in user's organization.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	PeopleReadAllScope ScopeType = "People.Read.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Report Permissions
 | 
			
		||||
//
 | 
			
		||||
// Reports permissions are only valid for work or school accounts.
 | 
			
		||||
const (
 | 
			
		||||
	// ReportsReadAllScope allows an app to read all service usage reports without a signed-in user. Services that
 | 
			
		||||
	// provide usage reports include Office 365 and Azure Active Directory.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	ReportsReadAllScope ScopeType = "Reports.Read.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Security Permissions
 | 
			
		||||
//
 | 
			
		||||
// Security permissions are valid only on work or school accounts.
 | 
			
		||||
const (
 | 
			
		||||
	// SecurityEventsReadAllScope allows the app to read your organization’s security events on behalf of the signed-in
 | 
			
		||||
	// user.
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	SecurityEventsReadAllScope ScopeType = "SecurityEvents.Read.All"
 | 
			
		||||
 | 
			
		||||
	// SecurityEventsReadWriteAllScope allows the app to read your organization’s security events on behalf of the
 | 
			
		||||
	// signed-in user. Also allows the app to update editable properties in security events on behalf of the signed-in
 | 
			
		||||
	// user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	SecurityEventsReadWriteAllScope ScopeType = "SecurityEvents.ReadWrite.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Sites Permissions
 | 
			
		||||
//
 | 
			
		||||
// Sites permissions are valid only on work or school accounts.
 | 
			
		||||
const (
 | 
			
		||||
	// SitesReadAllScope allows the app to read documents and list items in all site collections on behalf of the
 | 
			
		||||
	// signed-in user.
 | 
			
		||||
	SitesReadAllScope ScopeType = "Sites.Read.All"
 | 
			
		||||
 | 
			
		||||
	// SitesReadWriteAllScope allows the app to edit or delete documents and list items in all site collections on
 | 
			
		||||
	// behalf of the signed-in user.
 | 
			
		||||
	SitesReadWriteAllScope ScopeType = "Sites.ReadWrite.All"
 | 
			
		||||
 | 
			
		||||
	// SitesManageAllScope allows the app to manage and create lists, documents, and list items in all site collections
 | 
			
		||||
	// on behalf of the signed-in user.
 | 
			
		||||
	SitesManageAllScope ScopeType = "Sites.Manage.All"
 | 
			
		||||
 | 
			
		||||
	// SitesFullControlAllScope allows the app to have full control to SharePoint sites in all site collections on
 | 
			
		||||
	// behalf of the signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	SitesFullControlAllScope ScopeType = "Sites.FullControl.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Tasks Permissions
 | 
			
		||||
//
 | 
			
		||||
// Tasks permissions are used to control access for Outlook tasks. Access for Microsoft Planner tasks is controlled by
 | 
			
		||||
// Group permissions.
 | 
			
		||||
//
 | 
			
		||||
// Shared permissions are currently only supported for work or school accounts. Even with Shared permissions, reads and
 | 
			
		||||
// writes may fail if the user who owns the shared content has not granted the accessing user permissions to modify
 | 
			
		||||
// content within the folder.
 | 
			
		||||
const (
 | 
			
		||||
	// TasksReadScope allows the app to read user tasks.
 | 
			
		||||
	TasksReadScope ScopeType = "Tasks.Read"
 | 
			
		||||
 | 
			
		||||
	// TasksReadSharedScope allows the app to read tasks a user has permissions to access, including their own and
 | 
			
		||||
	// shared tasks.
 | 
			
		||||
	TasksReadSharedScope ScopeType = "Tasks.Read.Shared"
 | 
			
		||||
 | 
			
		||||
	// TasksReadWriteScope allows the app to create, read, update and delete tasks and containers (and tasks in them)
 | 
			
		||||
	// that are assigned to or shared with the signed-in user.
 | 
			
		||||
	TasksReadWriteScope ScopeType = "Tasks.ReadWrite"
 | 
			
		||||
 | 
			
		||||
	// TasksReadWriteSharedScope allows the app to create, read, update, and delete tasks a user has permissions to,
 | 
			
		||||
	// including their own and shared tasks.
 | 
			
		||||
	TasksReadWriteSharedScope ScopeType = "Tasks.ReadWrite.Shared"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Terms of Use Permissions
 | 
			
		||||
//
 | 
			
		||||
// All the permissions above are valid only for work or school accounts.
 | 
			
		||||
//
 | 
			
		||||
// For an app to read or write all agreements or agreement acceptances with delegated permissions, the signed-in user
 | 
			
		||||
// must be assigned the Global Administrator, Conditional Access Administrator or Security Administrator role. For more
 | 
			
		||||
// information about administrator roles, see Assigning administrator roles in Azure Active Directory
 | 
			
		||||
// https://docs.microsoft.com/azure/active-directory/active-directory-assign-admin-roles.
 | 
			
		||||
const (
 | 
			
		||||
	// AgreementReadAllScope allows the app to read terms of use agreements on behalf of the signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	AgreementReadAllScope ScopeType = "Agreement.Read.All"
 | 
			
		||||
 | 
			
		||||
	// AgreementReadWriteAllScope allows the app to read and write terms of use agreements on behalf of the signed-in
 | 
			
		||||
	// user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	AgreementReadWriteAllScope ScopeType = "Agreement.ReadWrite.All"
 | 
			
		||||
 | 
			
		||||
	// AgreementAcceptanceReadScope allows the app to read terms of use acceptance statuses on behalf of the signed-in
 | 
			
		||||
	// user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	AgreementAcceptanceReadScope ScopeType = "AgreementAcceptance.Read"
 | 
			
		||||
 | 
			
		||||
	// AgreementAcceptanceReadAllScope allows the app to read terms of use acceptance statuses on behalf of the
 | 
			
		||||
	// signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	AgreementAcceptanceReadAllScope ScopeType = "AgreementAcceptance.Read.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// User Permissions
 | 
			
		||||
//
 | 
			
		||||
// The only permissions valid for Microsoft accounts are User.Read and User.ReadWrite. For work or school accounts, all
 | 
			
		||||
// permissions are valid.
 | 
			
		||||
//
 | 
			
		||||
// With the User.Read permission, an app can also read the basic company information of the signed-in user for a work or
 | 
			
		||||
// school account through the organization resource. The following properties are available: id, displayName, and
 | 
			
		||||
// verifiedDomains.
 | 
			
		||||
//
 | 
			
		||||
// For work or school accounts, the full profile includes all of the declared properties of the User resource. On reads,
 | 
			
		||||
// only a limited number of properties are returned by default. To read properties that are not in the default set, use
 | 
			
		||||
// $select. The default properties are:
 | 
			
		||||
//  displayName
 | 
			
		||||
//  givenName
 | 
			
		||||
//  jobTitle
 | 
			
		||||
//  mail
 | 
			
		||||
//  mobilePhone
 | 
			
		||||
//  officeLocation
 | 
			
		||||
//  preferredLanguage
 | 
			
		||||
//  surname
 | 
			
		||||
//  userPrincipalName
 | 
			
		||||
//
 | 
			
		||||
// User.ReadWrite and User.Readwrite.All delegated permissions allow the app to update the following profile properties
 | 
			
		||||
// for work or school accounts:
 | 
			
		||||
//  aboutMe
 | 
			
		||||
//  birthday
 | 
			
		||||
//  hireDate
 | 
			
		||||
//  interests
 | 
			
		||||
//  mobilePhone
 | 
			
		||||
//  mySite
 | 
			
		||||
//  pastProjects
 | 
			
		||||
//  photo
 | 
			
		||||
//  preferredName
 | 
			
		||||
//  responsibilities
 | 
			
		||||
//  schools
 | 
			
		||||
//  skills
 | 
			
		||||
//
 | 
			
		||||
// With the User.ReadWrite.All application permission, the app can update all of the declared properties of work or
 | 
			
		||||
// school accounts except for password.
 | 
			
		||||
//
 | 
			
		||||
// To read or write direct reports (directReports) or the manager (manager) of a work or school account, the app must
 | 
			
		||||
// have either User.Read.All (read only) or User.ReadWrite.All.
 | 
			
		||||
//
 | 
			
		||||
// The User.ReadBasic.All permission constrains app access to a limited set of properties known as the basic profile.
 | 
			
		||||
// This is because the full profile might contain sensitive directory information. The basic profile includes only the
 | 
			
		||||
// following properties:
 | 
			
		||||
//  displayName
 | 
			
		||||
//  givenName
 | 
			
		||||
//  mail
 | 
			
		||||
//  photo
 | 
			
		||||
//  surname
 | 
			
		||||
//  userPrincipalName
 | 
			
		||||
//
 | 
			
		||||
// To read the group memberships of a user (memberOf), the app must have either Group.Read.All or Group.ReadWrite.All.
 | 
			
		||||
// However, if the user also has membership in a directoryRole or an administrativeUnit, the app will need effective
 | 
			
		||||
// permissions to read those resources too, or Microsoft Graph will return an error. This means the app will also need
 | 
			
		||||
// Directory permissions, and, for delegated permissions, the signed-in user will also need sufficient privileges in the
 | 
			
		||||
// organization to access directory roles and administrative units.
 | 
			
		||||
const (
 | 
			
		||||
	// UserReadScope allows users to sign-in to the app, and allows the app to read the profile of signed-in users. It
 | 
			
		||||
	// also allows the app to read basic company information of signed-in users.
 | 
			
		||||
	UserReadScope ScopeType = "User.Read"
 | 
			
		||||
 | 
			
		||||
	// UserReadWriteScope allows the app to read the signed-in user's full profile. It also allows the app to update the
 | 
			
		||||
	// signed-in user's profile information on their behalf.
 | 
			
		||||
	UserReadWriteScope ScopeType = "User.ReadWrite"
 | 
			
		||||
 | 
			
		||||
	// UserReadBasicAllScope allows the app to read a basic set of profile properties of other users in your
 | 
			
		||||
	// organization on behalf of the signed-in user. This includes display name, first and last name, email address,
 | 
			
		||||
	// open extensions and photo. Also allows the app to read the full profile of the signed-in user.
 | 
			
		||||
	UserReadBasicAllScope ScopeType = "User.ReadBasic.All"
 | 
			
		||||
 | 
			
		||||
	// UserReadAllScope allows the app to read the full set of profile properties, reports, and managers of other users
 | 
			
		||||
	// in your organization, on behalf of the signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	UserReadAllScope ScopeType = "User.Read.All"
 | 
			
		||||
 | 
			
		||||
	// UserReadWriteAllScope allows the app to read and write the full set of profile properties, reports, and managers
 | 
			
		||||
	// of other users in your organization, on behalf of the signed-in user. Also allows the app to create and delete
 | 
			
		||||
	// users as well as reset user passwords on behalf of the signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	UserReadWriteAllScope ScopeType = "User.ReadWrite.All"
 | 
			
		||||
 | 
			
		||||
	// UserInviteAllScope allows the app to invite guest users to your organization, on behalf of the signed-in user.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	UserInviteAllScope ScopeType = "User.Invite.All"
 | 
			
		||||
 | 
			
		||||
	// UserExportAllScope allows the app to export an organizational user's data, when performed by a Company
 | 
			
		||||
	// Administrator.
 | 
			
		||||
	//
 | 
			
		||||
	// requires admin consent
 | 
			
		||||
	UserExportAllScope ScopeType = "User.Export.All"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// User Activity Permissions
 | 
			
		||||
//
 | 
			
		||||
// UserActivity.ReadWrite.CreatedByApp is valid for both Microsoft accounts and work or school accounts.
 | 
			
		||||
//
 | 
			
		||||
// The CreatedByApp constraint associated with this permission indicates the service will apply implicit filtering to
 | 
			
		||||
// results based on the identity of the calling app, either the MSA app id or a set of app ids configured for a
 | 
			
		||||
// cross-platform application identity.
 | 
			
		||||
const (
 | 
			
		||||
	// UserActivityReadWriteCreatedByAppScope allows the app to read and report the signed-in user's activity in the
 | 
			
		||||
	// app.
 | 
			
		||||
	UserActivityReadWriteCreatedByAppScope ScopeType = "UserActivity.ReadWrite.CreatedByApp"
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										63
									
								
								vendor/github.com/markbates/goth/providers/azureadv2/session.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								vendor/github.com/markbates/goth/providers/azureadv2/session.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
package azureadv2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Session is the implementation of `goth.Session`
 | 
			
		||||
type Session struct {
 | 
			
		||||
	AuthURL      string    `json:"au"`
 | 
			
		||||
	AccessToken  string    `json:"at"`
 | 
			
		||||
	RefreshToken string    `json:"rt"`
 | 
			
		||||
	ExpiresAt    time.Time `json:"exp"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAuthURL will return the URL set by calling the `BeginAuth` func
 | 
			
		||||
func (s Session) GetAuthURL() (string, error) {
 | 
			
		||||
	if s.AuthURL == "" {
 | 
			
		||||
		return "", errors.New(goth.NoAuthUrlErrorMessage)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s.AuthURL, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Authorize the session with AzureAD and return the access token to be stored for future use.
 | 
			
		||||
func (s *Session) Authorize(provider goth.Provider, params goth.Params) (string, error) {
 | 
			
		||||
	p := provider.(*Provider)
 | 
			
		||||
	token, err := p.config.Exchange(goth.ContextForClient(p.Client()), params.Get("code"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !token.Valid() {
 | 
			
		||||
		return "", errors.New("invalid token received from provider")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.AccessToken = token.AccessToken
 | 
			
		||||
	s.RefreshToken = token.RefreshToken
 | 
			
		||||
	s.ExpiresAt = token.Expiry
 | 
			
		||||
 | 
			
		||||
	return token.AccessToken, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Marshal the session into a string
 | 
			
		||||
func (s Session) Marshal() string {
 | 
			
		||||
	b, _ := json.Marshal(s)
 | 
			
		||||
	return string(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s Session) String() string {
 | 
			
		||||
	return s.Marshal()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalSession wil unmarshal a JSON string into a session.
 | 
			
		||||
func (p *Provider) UnmarshalSession(data string) (goth.Session, error) {
 | 
			
		||||
	session := &Session{}
 | 
			
		||||
	err := json.NewDecoder(strings.NewReader(data)).Decode(session)
 | 
			
		||||
	return session, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										190
									
								
								vendor/github.com/markbates/goth/providers/microsoftonline/microsoftonline.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								vendor/github.com/markbates/goth/providers/microsoftonline/microsoftonline.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,190 @@
 | 
			
		|||
// Package microsoftonline implements the OAuth2 protocol for authenticating users through microsoftonline.
 | 
			
		||||
// This package can be used as a reference implementation of an OAuth2 provider for Goth.
 | 
			
		||||
// To use this package, your application need to be registered in [Application Registration Portal](https://apps.dev.microsoft.com/)
 | 
			
		||||
package microsoftonline
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/going/defaults"
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
	"golang.org/x/oauth2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	authURL         string = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
 | 
			
		||||
	tokenURL        string = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
 | 
			
		||||
	endpointProfile string = "https://graph.microsoft.com/v1.0/me"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var defaultScopes = []string{"openid", "offline_access", "user.read"}
 | 
			
		||||
 | 
			
		||||
// New creates a new microsoftonline provider, and sets up important connection details.
 | 
			
		||||
// You should always call `microsoftonline.New` to get a new Provider. Never try to create
 | 
			
		||||
// one manually.
 | 
			
		||||
func New(clientKey, secret, callbackURL string, scopes ...string) *Provider {
 | 
			
		||||
	p := &Provider{
 | 
			
		||||
		ClientKey:    clientKey,
 | 
			
		||||
		Secret:       secret,
 | 
			
		||||
		CallbackURL:  callbackURL,
 | 
			
		||||
		providerName: "microsoftonline",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p.config = newConfig(p, scopes)
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Provider is the implementation of `goth.Provider` for accessing microsoftonline.
 | 
			
		||||
type Provider struct {
 | 
			
		||||
	ClientKey    string
 | 
			
		||||
	Secret       string
 | 
			
		||||
	CallbackURL  string
 | 
			
		||||
	HTTPClient   *http.Client
 | 
			
		||||
	config       *oauth2.Config
 | 
			
		||||
	providerName string
 | 
			
		||||
	tenant       string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name is the name used to retrieve this provider later.
 | 
			
		||||
func (p *Provider) Name() string {
 | 
			
		||||
	return p.providerName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetName is to update the name of the provider (needed in case of multiple providers of 1 type)
 | 
			
		||||
func (p *Provider) SetName(name string) {
 | 
			
		||||
	p.providerName = name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Client is HTTP client to be used in all fetch operations.
 | 
			
		||||
func (p *Provider) Client() *http.Client {
 | 
			
		||||
	return goth.HTTPClientWithFallBack(p.HTTPClient)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Debug is a no-op for the facebook package.
 | 
			
		||||
func (p *Provider) Debug(debug bool) {}
 | 
			
		||||
 | 
			
		||||
// BeginAuth asks MicrosoftOnline for an authentication end-point.
 | 
			
		||||
func (p *Provider) BeginAuth(state string) (goth.Session, error) {
 | 
			
		||||
	authURL := p.config.AuthCodeURL(state)
 | 
			
		||||
	return &Session{
 | 
			
		||||
		AuthURL: authURL,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FetchUser will go to MicrosoftOnline and access basic information about the user.
 | 
			
		||||
func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
 | 
			
		||||
	msSession := session.(*Session)
 | 
			
		||||
	user := goth.User{
 | 
			
		||||
		AccessToken: msSession.AccessToken,
 | 
			
		||||
		Provider:    p.Name(),
 | 
			
		||||
		ExpiresAt:   msSession.ExpiresAt,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if user.AccessToken == "" {
 | 
			
		||||
		return user, fmt.Errorf("%s cannot get user information without accessToken", p.providerName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req, err := http.NewRequest("GET", endpointProfile, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return user, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req.Header.Set(authorizationHeader(msSession))
 | 
			
		||||
 | 
			
		||||
	response, err := p.Client().Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return user, err
 | 
			
		||||
	}
 | 
			
		||||
	defer response.Body.Close()
 | 
			
		||||
 | 
			
		||||
	if response.StatusCode != http.StatusOK {
 | 
			
		||||
		return user, fmt.Errorf("%s responded with a %d trying to fetch user information", p.providerName, response.StatusCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	user.AccessToken = msSession.AccessToken
 | 
			
		||||
 | 
			
		||||
	err = userFromReader(response.Body, &user)
 | 
			
		||||
	return user, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RefreshTokenAvailable refresh token is provided by auth provider or not
 | 
			
		||||
// not available for microsoft online as session size hit the limit of max cookie size
 | 
			
		||||
func (p *Provider) RefreshTokenAvailable() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//RefreshToken get new access token based on the refresh token
 | 
			
		||||
func (p *Provider) RefreshToken(refreshToken string) (*oauth2.Token, error) {
 | 
			
		||||
	if refreshToken == "" {
 | 
			
		||||
		return nil, fmt.Errorf("No refresh token provided")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	token := &oauth2.Token{RefreshToken: refreshToken}
 | 
			
		||||
	ts := p.config.TokenSource(goth.ContextForClient(p.Client()), token)
 | 
			
		||||
	newToken, err := ts.Token()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return newToken, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newConfig(provider *Provider, scopes []string) *oauth2.Config {
 | 
			
		||||
	c := &oauth2.Config{
 | 
			
		||||
		ClientID:     provider.ClientKey,
 | 
			
		||||
		ClientSecret: provider.Secret,
 | 
			
		||||
		RedirectURL:  provider.CallbackURL,
 | 
			
		||||
		Endpoint: oauth2.Endpoint{
 | 
			
		||||
			AuthURL:  authURL,
 | 
			
		||||
			TokenURL: tokenURL,
 | 
			
		||||
		},
 | 
			
		||||
		Scopes: []string{},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.Scopes = append(c.Scopes, scopes...)
 | 
			
		||||
	if len(scopes) == 0 {
 | 
			
		||||
		c.Scopes = append(c.Scopes, defaultScopes...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func userFromReader(r io.Reader, user *goth.User) error {
 | 
			
		||||
	buf := &bytes.Buffer{}
 | 
			
		||||
	tee := io.TeeReader(r, buf)
 | 
			
		||||
 | 
			
		||||
	u := struct {
 | 
			
		||||
		ID                string `json:"id"`
 | 
			
		||||
		Name              string `json:"displayName"`
 | 
			
		||||
		Email             string `json:"mail"`
 | 
			
		||||
		FirstName         string `json:"givenName"`
 | 
			
		||||
		LastName          string `json:"surname"`
 | 
			
		||||
		UserPrincipalName string `json:"userPrincipalName"`
 | 
			
		||||
	}{}
 | 
			
		||||
 | 
			
		||||
	if err := json.NewDecoder(tee).Decode(&u); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	raw := map[string]interface{}{}
 | 
			
		||||
	if err := json.NewDecoder(buf).Decode(&raw); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	user.UserID = u.ID
 | 
			
		||||
	user.Email = defaults.String(u.Email, u.UserPrincipalName)
 | 
			
		||||
	user.Name = u.Name
 | 
			
		||||
	user.NickName = u.Name
 | 
			
		||||
	user.FirstName = u.FirstName
 | 
			
		||||
	user.LastName = u.LastName
 | 
			
		||||
	user.RawData = raw
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func authorizationHeader(session *Session) (string, string) {
 | 
			
		||||
	return "Authorization", fmt.Sprintf("Bearer %s", session.AccessToken)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								vendor/github.com/markbates/goth/providers/microsoftonline/session.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/markbates/goth/providers/microsoftonline/session.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,62 @@
 | 
			
		|||
package microsoftonline
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/markbates/goth"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Session is the implementation of `goth.Session` for accessing microsoftonline.
 | 
			
		||||
// Refresh token not available for microsoft online: session size hit the limit of max cookie size
 | 
			
		||||
type Session struct {
 | 
			
		||||
	AuthURL     string
 | 
			
		||||
	AccessToken string
 | 
			
		||||
	ExpiresAt   time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAuthURL will return the URL set by calling the `BeginAuth` function on the Facebook provider.
 | 
			
		||||
func (s Session) GetAuthURL() (string, error) {
 | 
			
		||||
	if s.AuthURL == "" {
 | 
			
		||||
		return "", errors.New(goth.NoAuthUrlErrorMessage)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s.AuthURL, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Authorize the session with Facebook and return the access token to be stored for future use.
 | 
			
		||||
func (s *Session) Authorize(provider goth.Provider, params goth.Params) (string, error) {
 | 
			
		||||
	p := provider.(*Provider)
 | 
			
		||||
	token, err := p.config.Exchange(goth.ContextForClient(p.Client()), params.Get("code"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !token.Valid() {
 | 
			
		||||
		return "", errors.New("Invalid token received from provider")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.AccessToken = token.AccessToken
 | 
			
		||||
	s.ExpiresAt = token.Expiry
 | 
			
		||||
 | 
			
		||||
	return token.AccessToken, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Marshal the session into a string
 | 
			
		||||
func (s Session) Marshal() string {
 | 
			
		||||
	b, _ := json.Marshal(s)
 | 
			
		||||
	return string(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s Session) String() string {
 | 
			
		||||
	return s.Marshal()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalSession wil unmarshal a JSON string into a session.
 | 
			
		||||
func (p *Provider) UnmarshalSession(data string) (goth.Session, error) {
 | 
			
		||||
	session := &Session{}
 | 
			
		||||
	err := json.NewDecoder(strings.NewReader(data)).Decode(session)
 | 
			
		||||
	return session, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/modules.txt
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/modules.txt
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -570,10 +570,14 @@ github.com/mailru/easyjson
 | 
			
		|||
github.com/mailru/easyjson/buffer
 | 
			
		||||
github.com/mailru/easyjson/jlexer
 | 
			
		||||
github.com/mailru/easyjson/jwriter
 | 
			
		||||
# github.com/markbates/going v1.0.0
 | 
			
		||||
github.com/markbates/going/defaults
 | 
			
		||||
# github.com/markbates/goth v1.68.0
 | 
			
		||||
## explicit
 | 
			
		||||
github.com/markbates/goth
 | 
			
		||||
github.com/markbates/goth/gothic
 | 
			
		||||
github.com/markbates/goth/providers/azuread
 | 
			
		||||
github.com/markbates/goth/providers/azureadv2
 | 
			
		||||
github.com/markbates/goth/providers/bitbucket
 | 
			
		||||
github.com/markbates/goth/providers/discord
 | 
			
		||||
github.com/markbates/goth/providers/dropbox
 | 
			
		||||
| 
						 | 
				
			
			@ -583,6 +587,7 @@ github.com/markbates/goth/providers/github
 | 
			
		|||
github.com/markbates/goth/providers/gitlab
 | 
			
		||||
github.com/markbates/goth/providers/google
 | 
			
		||||
github.com/markbates/goth/providers/mastodon
 | 
			
		||||
github.com/markbates/goth/providers/microsoftonline
 | 
			
		||||
github.com/markbates/goth/providers/nextcloud
 | 
			
		||||
github.com/markbates/goth/providers/openidConnect
 | 
			
		||||
github.com/markbates/goth/providers/twitter
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2027,19 +2027,17 @@ function initAdmin() {
 | 
			
		|||
 | 
			
		||||
    const provider = $('#oauth2_provider').val();
 | 
			
		||||
    switch (provider) {
 | 
			
		||||
      case 'gitea':
 | 
			
		||||
      case 'nextcloud':
 | 
			
		||||
      case 'mastodon':
 | 
			
		||||
        $('#oauth2_use_custom_url').attr('checked', 'checked');
 | 
			
		||||
        // fallthrough intentional
 | 
			
		||||
      case 'github':
 | 
			
		||||
      case 'gitlab':
 | 
			
		||||
        $('.oauth2_use_custom_url').show();
 | 
			
		||||
        break;
 | 
			
		||||
      case 'openidConnect':
 | 
			
		||||
        $('.open_id_connect_auto_discovery_url input').attr('required', 'required');
 | 
			
		||||
        $('.open_id_connect_auto_discovery_url').show();
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        if ($(`#${provider}_customURLSettings`).data('required')) {
 | 
			
		||||
          $('#oauth2_use_custom_url').attr('checked', 'checked');
 | 
			
		||||
        }
 | 
			
		||||
        if ($(`#${provider}_customURLSettings`).data('available')) {
 | 
			
		||||
          $('.oauth2_use_custom_url').show();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    onOAuth2UseCustomURLChange(applyDefaultValues);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -2050,29 +2048,14 @@ function initAdmin() {
 | 
			
		|||
    $('.oauth2_use_custom_url_field input[required]').removeAttr('required');
 | 
			
		||||
 | 
			
		||||
    if ($('#oauth2_use_custom_url').is(':checked')) {
 | 
			
		||||
      if (applyDefaultValues) {
 | 
			
		||||
        $('#oauth2_token_url').val($(`#${provider}_token_url`).val());
 | 
			
		||||
        $('#oauth2_auth_url').val($(`#${provider}_auth_url`).val());
 | 
			
		||||
        $('#oauth2_profile_url').val($(`#${provider}_profile_url`).val());
 | 
			
		||||
        $('#oauth2_email_url').val($(`#${provider}_email_url`).val());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      switch (provider) {
 | 
			
		||||
        case 'github':
 | 
			
		||||
          $('.oauth2_token_url input, .oauth2_auth_url input, .oauth2_profile_url input, .oauth2_email_url input').attr('required', 'required');
 | 
			
		||||
          $('.oauth2_token_url, .oauth2_auth_url, .oauth2_profile_url, .oauth2_email_url').show();
 | 
			
		||||
          break;
 | 
			
		||||
        case 'nextcloud':
 | 
			
		||||
        case 'gitea':
 | 
			
		||||
        case 'gitlab':
 | 
			
		||||
          $('.oauth2_token_url input, .oauth2_auth_url input, .oauth2_profile_url input').attr('required', 'required');
 | 
			
		||||
          $('.oauth2_token_url, .oauth2_auth_url, .oauth2_profile_url').show();
 | 
			
		||||
          $('#oauth2_email_url').val('');
 | 
			
		||||
          break;
 | 
			
		||||
        case 'mastodon':
 | 
			
		||||
          $('.oauth2_auth_url input').attr('required', 'required');
 | 
			
		||||
          $('.oauth2_auth_url').show();
 | 
			
		||||
          break;
 | 
			
		||||
      for (const custom of ['token_url', 'auth_url', 'profile_url', 'email_url', 'tenant']) {
 | 
			
		||||
        if (applyDefaultValues) {
 | 
			
		||||
          $(`#oauth2_${custom}`).val($(`#${provider}_${custom}`).val());
 | 
			
		||||
        }
 | 
			
		||||
        if ($(`#${provider}_${custom}`).data('available')) {
 | 
			
		||||
          $(`.oauth2_${custom} input`).attr('required', 'required');
 | 
			
		||||
          $(`.oauth2_${custom}`).show();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue