Skip to content

Commit dfe9b53

Browse files
tuunitjjlakis
authored andcommitted
add pagination for graph api
1 parent 8581613 commit dfe9b53

File tree

2 files changed

+45
-19
lines changed

2 files changed

+45
-19
lines changed

providers/ms_entra_id.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -117,29 +117,39 @@ func (p *MicrosoftEntraIDProvider) addGraphGroupsToSession(ctx context.Context,
117117
groupsHeaders := makeAuthorizationHeader(tokenTypeBearer, s.AccessToken, nil)
118118
groupsHeaders.Add("ConsistencyLevel", "eventual")
119119

120-
groupsURL := fmt.Sprintf("%s/transitiveMemberOf?$select=id&$top=999", p.microsoftGraphURL)
120+
var allGroups []string
121+
var nextLink string
121122

122-
jsonRequest, err := requests.New(groupsURL).
123-
WithContext(ctx).
124-
WithHeaders(groupsHeaders).
125-
Do().
126-
UnmarshalSimpleJSON()
123+
for {
124+
if nextLink == "" {
125+
nextLink = fmt.Sprintf("%s/transitiveMemberOf?$select=id&$top=100", p.microsoftGraphURL)
126+
}
127127

128-
if err != nil {
129-
logger.Errorf("invalid response from microsoft graph, no groups added to session: %v", err)
130-
return nil
131-
}
128+
response, err := requests.New(nextLink).
129+
WithContext(ctx).
130+
WithHeaders(groupsHeaders).
131+
Do().
132+
UnmarshalSimpleJSON()
132133

133-
reqGroups := jsonRequest.Get("value").MustArray()
134-
groups := make([]string, len(reqGroups))
134+
if err != nil {
135+
return fmt.Errorf("invalid response from microsoft graph, no groups added to session: %v", err)
136+
}
137+
reqGroups := response.Get("value").MustArray()
135138

136-
for i := range reqGroups {
137-
value := jsonRequest.Get("value").GetIndex(i).Get("id").MustString()
138-
groups = append(groups, value)
139-
}
139+
for i := range reqGroups {
140+
value := response.Get("value").GetIndex(i).Get("id").MustString()
141+
allGroups = append(allGroups, value)
142+
}
143+
144+
// https://learn.microsoft.com/en-us/graph/paging?view=graph-rest-1.0&tabs=http#how-paging-works
145+
nextLink = response.Get("@odata.nextLink").MustString()
140146

141-
s.Groups = util.RemoveDuplicateStr(append(s.Groups, groups...))
147+
if nextLink == "" {
148+
break
149+
}
150+
}
142151

152+
s.Groups = util.RemoveDuplicateStr(append(s.Groups, allGroups...))
143153
return nil
144154
}
145155

providers/ms_entra_id_test.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"crypto/rand"
66
"crypto/rsa"
7+
"fmt"
78
"net/http"
89
"net/http/httptest"
910
"net/url"
@@ -77,6 +78,7 @@ func TestAzureEntraOIDCProviderEnrichSessionGroupOverage(t *testing.T) {
7778
assert.NoError(t, err)
7879
assert.Contains(t, session.Groups, "85d7d600-7804-4d92-8d43-9c33c21c130c")
7980
assert.Contains(t, session.Groups, "916f0604-8a3b-4a69-bda9-06db11a8f0cd")
81+
assert.Contains(t, session.Groups, "b1aef995-6b55-4ac6-bbfe-e829810e9352", "Pagination using $skiptoken failed")
8082
}
8183

8284
func TestAzureEntraOIDCProviderValidateSessionAllowedTenants(t *testing.T) {
@@ -133,9 +135,23 @@ func mockGraphAPI(noGroupMemberPermissions bool) *httptest.Server {
133135
func(w http.ResponseWriter, r *http.Request) {
134136
if noGroupMemberPermissions {
135137
w.WriteHeader(401)
136-
} else if r.URL.Path == groupsPath && r.Method == http.MethodGet {
138+
} else if r.URL.Path == groupsPath && r.Method == http.MethodGet && len(r.URL.Query()["$skiptoken"]) > 0 {
139+
// Second page (pagination)
137140
w.Write([]byte(`{
138141
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#directoryObjects(id)",
142+
"value": [
143+
{
144+
"@odata.type": "#microsoft.graph.group",
145+
"id": "b1aef995-6b55-4ac6-bbfe-e829810e9352"
146+
}
147+
]
148+
}`))
149+
150+
} else if r.URL.Path == groupsPath && r.Method == http.MethodGet {
151+
// First page (pagination)
152+
w.Write([]byte(fmt.Sprintf(`{
153+
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#directoryObjects(id)",
154+
"@odata.nextLink": "http://%s/v1.0/me/transitiveMemberOf?$select=id&$top=2&$skiptoken=TEST_TOKEN",
139155
"value": [
140156
{
141157
"@odata.type": "#microsoft.graph.group",
@@ -146,7 +162,7 @@ func mockGraphAPI(noGroupMemberPermissions bool) *httptest.Server {
146162
"id": "916f0604-8a3b-4a69-bda9-06db11a8f0cd"
147163
}
148164
]
149-
}`))
165+
}`, r.Host)))
150166
}
151167
},
152168
))

0 commit comments

Comments
 (0)