Skip to content

Commit d00ce0d

Browse files
committed
Fix invalid authority uri
1 parent 06d3fb2 commit d00ce0d

File tree

2 files changed

+51
-9
lines changed

2 files changed

+51
-9
lines changed

apps/internal/oauth/ops/authority/authority.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ type jsonCaller interface {
4747
}
4848

4949
var aadTrustedHostList = map[string]bool{
50-
"login.windows.net": true, // Microsoft Azure Worldwide - Used in validation scenarios where host is not this list
51-
"login.partner.microsoftonline.cn": true, // Microsoft Azure China
52-
"login.microsoftonline.de": true, // Microsoft Azure Blackforest
53-
"login-us.microsoftonline.com": true, // Microsoft Azure US Government - Legacy
54-
"login.microsoftonline.us": true, // Microsoft Azure US Government
55-
"login.microsoftonline.com": true, // Microsoft Azure Worldwide
50+
"login.windows.net": true, // Microsoft Azure Worldwide - Used in validation scenarios where host is not this list
51+
"login.partner.microsoftonline.cn": true, // Microsoft Azure China
52+
"login.microsoftonline.de": true, // Microsoft Azure Blackforest
53+
"login-us.microsoftonline.com": true, // Microsoft Azure US Government - Legacy
54+
"login.microsoftonline.us": true, // Microsoft Azure US Government
55+
"login.microsoftonline.com": true, // Microsoft Azure Worldwide
5656
}
5757

5858
// TrustedHost checks if an AAD host is trusted/valid.
@@ -358,7 +358,16 @@ type Info struct {
358358

359359
// NewInfoFromAuthorityURI creates an AuthorityInfo instance from the authority URL provided.
360360
func NewInfoFromAuthorityURI(authority string, validateAuthority bool, instanceDiscoveryDisabled bool) (Info, error) {
361-
u, err := url.Parse(strings.ToLower(authority))
361+
362+
cannonicalAuthority := authority
363+
364+
// suffix authority with / if it doesn't have one
365+
if !strings.HasSuffix(authority, "/") {
366+
cannonicalAuthority += "/"
367+
}
368+
369+
u, err := url.Parse(strings.ToLower(cannonicalAuthority))
370+
362371
if err != nil {
363372
return Info{}, fmt.Errorf("couldn't parse authority url: %w", err)
364373
}
@@ -376,7 +385,7 @@ func NewInfoFromAuthorityURI(authority string, validateAuthority bool, instanceD
376385
case "adfs":
377386
authorityType = ADFS
378387
case "dstsv2":
379-
if len(pathParts) != 3 {
388+
if len(pathParts) != 4 {
380389
return Info{}, fmt.Errorf("dSTS authority must be an https URL such as https://<authority>/dstsv2/%s", DSTSTenant)
381390
}
382391
if pathParts[2] != DSTSTenant {
@@ -392,7 +401,7 @@ func NewInfoFromAuthorityURI(authority string, validateAuthority bool, instanceD
392401
// u.Host includes the port, if any, which is required for private cloud deployments
393402
return Info{
394403
Host: u.Host,
395-
CanonicalAuthorityURI: authority,
404+
CanonicalAuthorityURI: cannonicalAuthority,
396405
AuthorityType: authorityType,
397406
ValidateAuthority: validateAuthority,
398407
Tenant: tenant,

apps/internal/oauth/ops/authority/authority_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,39 @@ func TestCreateAuthorityInfoFromAuthorityUri(t *testing.T) {
320320
}
321321
}
322322

323+
func TestAuthorityParsing(t *testing.T) {
324+
325+
dSTSWithSlash := fmt.Sprintf("https://dstsv2.example.com/dstsv2/%s/", DSTSTenant)
326+
dSTSNoSlash := fmt.Sprintf("https://dstsv2.example.com/dstsv2/%s", DSTSTenant)
327+
328+
tests := map[string]struct {
329+
authority, expectedType, expectedCannonical, expectedTenant string
330+
}{
331+
"AAD with slash": {"https://login.microsoftonline.com/common/", "MSSTS", "https://login.microsoftonline.com/common/", "common"},
332+
"AAD without slash": {"https://login.microsoftonline.com/common", "MSSTS", "https://login.microsoftonline.com/common/", "common"},
333+
"ADFS with slash": {"https://adfs.example.com/adfs/", "ADFS", "https://adfs.example.com/adfs/", ""},
334+
"ADFS without slash": {"https://adfs.example.com/adfs", "ADFS", "https://adfs.example.com/adfs/", ""},
335+
"dSTS with slash": {dSTSWithSlash, "DSTS", dSTSWithSlash, DSTSTenant},
336+
"dSTS without slash": {dSTSNoSlash, "DSTS", dSTSWithSlash, DSTSTenant},
337+
}
338+
339+
for name, test := range tests {
340+
actual, err := NewInfoFromAuthorityURI(test.authority, false, false)
341+
if err != nil {
342+
t.Fatal(err)
343+
}
344+
if actual.AuthorityType != test.expectedType {
345+
t.Fatalf("%s: unexpected authority type %s", name, actual.AuthorityType)
346+
}
347+
if actual.CanonicalAuthorityURI != test.expectedCannonical {
348+
t.Fatalf("%s: unexpected canonical authority %s", name, actual.CanonicalAuthorityURI)
349+
}
350+
if actual.Tenant != test.expectedTenant {
351+
t.Fatalf("%s: unexpected tenant %s", name, actual.Tenant)
352+
}
353+
}
354+
}
355+
323356
func TestAuthParamsWithTenant(t *testing.T) {
324357
uuid1 := uuid.New().String()
325358
uuid2 := uuid.New().String()

0 commit comments

Comments
 (0)