@@ -12,6 +12,7 @@ import (
12 "golang.org/x/exp/slices"
12 "golang.org/x/exp/slices"
14 "github.com/bitly/go-simplejson"
14 "github.com/bitly/go-simplejson"
15 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
16 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
16 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
17 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
17 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
18 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
@@ -33,7 +34,6 @@ const (
33 azureProviderName = "Azure"
34 azureProviderName = "Azure"
34 azureDefaultScope = "openid"
35 azureDefaultScope = "openid"
35 azureDefaultGraphGroupField = "id"
36 azureDefaultGraphGroupField = "id"
36− azureV2Scope = "https://graph.microsoft.com/.default"
@@ -90,15 +90,16 @@ func NewAzureProvider(p *ProviderData, opts options.AzureOptions) *AzureProvider
90 isV2Endpoint := false
90 isV2Endpoint := false
91 if strings.Contains(p.LoginURL.String(), "v2.0") {
91 if strings.Contains(p.LoginURL.String(), "v2.0") {
92 isV2Endpoint = true
92 isV2Endpoint = true
93+ azureV2GraphScope := fmt.Sprintf("https://%s/.default", p.ProfileURL.Host)
94 if strings.Contains(p.Scope, " groups") {
95 if strings.Contains(p.Scope, " groups") {
95 logger.Print("WARNING: `groups` scope is not an accepted scope when using Azure OAuth V2 endpoint. Removing it from the scope list")
96 logger.Print("WARNING: `groups` scope is not an accepted scope when using Azure OAuth V2 endpoint. Removing it from the scope list")
96 p.Scope = strings.ReplaceAll(p.Scope, " groups", "")
97 p.Scope = strings.ReplaceAll(p.Scope, " groups", "")
99− if !strings.Contains(p.Scope, " "+azureV2Scope) {
100+ if !strings.Contains(p.Scope, " "+azureV2GraphScope) {
100 // In order to be able to query MS Graph we must pass the ms graph default endpoint
101 // In order to be able to query MS Graph we must pass the ms graph default endpoint
101− p.Scope += " " + azureV2Scope
102+ p.Scope += " " + azureV2GraphScope
104 if p.ProtectedResource != nil && p.ProtectedResource.String() != "" {
105 if p.ProtectedResource != nil && p.ProtectedResource.String() != "" {
@@ -118,12 +119,12 @@ func overrideTenantURL(current, defaultURL *url.URL, tenant, path string) {
118 if current == nil || current.String() == "" || current.String() == defaultURL.String() {
119 if current == nil || current.String() == "" || current.String() == defaultURL.String() {
119 *current = url.URL{
120 *current = url.URL{
120 Scheme: "https",
121 Scheme: "https",
121− Host: "login.microsoftonline.com",
122+ Host: current.Host,
122 Path: "/" + tenant + "/oauth2/" + path}
123 Path: "/" + tenant + "/oauth2/" + path}
126−func getMicrosoftGraphGroupsURL(graphGroupField string) *url.URL {
127+func getMicrosoftGraphGroupsURL(profileURL *url.URL, graphGroupField string) *url.URL {
128 selectStatement := "$select=displayName,id"
129 selectStatement := "$select=displayName,id"
129 if !slices.Contains([]string{"displayName", "id"}, graphGroupField) {
130 if !slices.Contains([]string{"displayName", "id"}, graphGroupField) {
@@ -133,7 +134,7 @@ func getMicrosoftGraphGroupsURL(graphGroupField string) *url.URL {
133 // Select only security groups. Due to the filter option, count param is mandatory even if unused otherwise
134 // Select only security groups. Due to the filter option, count param is mandatory even if unused otherwise
134 return &url.URL{
135 return &url.URL{
135 Scheme: "https",
136 Scheme: "https",
136− Host: "graph.microsoft.com",
137+ Host: profileURL.Host,
137 Path: "/v1.0/me/transitiveMemberOf",
138 Path: "/v1.0/me/transitiveMemberOf",
138 RawQuery: "$count=true&$filter=securityEnabled+eq+true&" + selectStatement,
139 RawQuery: "$count=true&$filter=securityEnabled+eq+true&" + selectStatement,
@@ -368,7 +369,7 @@ func (p *AzureProvider) getGroupsFromProfileAPI(ctx context.Context, s *sessions
368 return nil, fmt.Errorf("missing access token")
369 return nil, fmt.Errorf("missing access token")
371− groupsURL := getMicrosoftGraphGroupsURL(p.GraphGroupField).String()
372+ groupsURL := getMicrosoftGraphGroupsURL(p.ProfileURL, p.GraphGroupField).String()
373 // Need and extra header while talking with MS Graph. For more context see
374 // Need and extra header while talking with MS Graph. For more context see
374 // https://docs.microsoft.com/en-us/graph/api/group-list-transitivememberof?view=graph-rest-1.0&tabs=http#request-headers
375 // https://docs.microsoft.com/en-us/graph/api/group-list-transitivememberof?view=graph-rest-1.0&tabs=http#request-headers