diff --git a/README.md b/README.md index c7935dac..893b1568 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Acquiring tokens with MSAL Go follows this general three step pattern. There mig * Initializing a public client: ```go - publicClientApp, err := public.New("client_id", public.WithAuthority("https://login.microsoftonline.com/Enter_The_Tenant_Name_Here")) + publicClientApp, err := public.New("client_id", public.WithAuthority("https://login.microsoft.com/Enter_The_Tenant_Name_Here")) ``` * Initializing a confidential client: @@ -54,7 +54,7 @@ Acquiring tokens with MSAL Go follows this general three step pattern. There mig if err != nil { return nil, fmt.Errorf("could not create a cred from a secret: %w", err) } - confidentialClientApp, err := confidential.New("client_id", cred, confidential.WithAuthority("https://login.microsoftonline.com/Enter_The_Tenant_Name_Here")) + confidentialClientApp, err := confidential.New("client_id", cred, confidential.WithAuthority("https://login.microsoft.com/Enter_The_Tenant_Name_Here")) ``` 1. MSAL comes packaged with an in-memory cache. Utilizing the cache is optional, but we would highly recommend it. diff --git a/apps/internal/oauth/ops/authority/authority.go b/apps/internal/oauth/ops/authority/authority.go index 5bebdb8e..7b2ccb4f 100644 --- a/apps/internal/oauth/ops/authority/authority.go +++ b/apps/internal/oauth/ops/authority/authority.go @@ -28,10 +28,19 @@ const ( regionName = "REGION_NAME" defaultAPIVersion = "2021-10-01" imdsEndpoint = "http://169.254.169.254/metadata/instance/compute/location?format=text&api-version=" + defaultAPIVersion - defaultHost = "login.microsoftonline.com" autoDetectRegion = "TryAutoDetect" ) +// These are various hosts that host AAD Instance discovery endpoints. +const ( + defaultHost = "login.microsoftonline.com" + loginMicrosoft = "login.microsoft.com" + loginWindows = "login.windows.net" + loginSTSWindows = "sts.windows.net" + loginMicrosoftOnline = defaultHost +) + +// jsonCaller is an interface that allows us to mock the JSONCall method. type jsonCaller interface { JSONCall(ctx context.Context, endpoint string, headers http.Header, qv url.Values, body, resp interface{}) error } @@ -54,6 +63,8 @@ func TrustedHost(host string) bool { return false } +// OAuthResponseBase is the base JSON return message for an OAuth call. +// This is embedded in other calls to get the base fields from every response. type OAuthResponseBase struct { Error string `json:"error"` SubError string `json:"suberror"` @@ -442,6 +453,8 @@ func (c Client) GetTenantDiscoveryResponse(ctx context.Context, openIDConfigurat return resp, err } +// AADInstanceDiscovery attempts to discover a tenant endpoint (used in OIDC auth with an authorization endpoint). +// This is done by AAD which allows for aliasing of tenants (windows.sts.net is the same as login.windows.com). func (c Client) AADInstanceDiscovery(ctx context.Context, authorityInfo Info) (InstanceDiscoveryResponse, error) { region := "" var err error @@ -454,9 +467,10 @@ func (c Client) AADInstanceDiscovery(ctx context.Context, authorityInfo Info) (I if region != "" { environment := authorityInfo.Host switch environment { - case "login.microsoft.com", "login.windows.net", "sts.windows.net", defaultHost: - environment = "r." + defaultHost + case loginMicrosoft, loginWindows, loginSTSWindows, defaultHost: + environment = loginMicrosoft } + resp.TenantDiscoveryEndpoint = fmt.Sprintf(tenantDiscoveryEndpointWithRegion, region, environment, authorityInfo.Tenant) metadata := InstanceDiscoveryMetadata{ PreferredNetwork: fmt.Sprintf("%v.%v", region, authorityInfo.Host), diff --git a/apps/internal/oauth/ops/authority/authority_test.go b/apps/internal/oauth/ops/authority/authority_test.go index d33b3677..0ce103fc 100644 --- a/apps/internal/oauth/ops/authority/authority_test.go +++ b/apps/internal/oauth/ops/authority/authority_test.go @@ -267,7 +267,7 @@ func TestAADInstanceDiscoveryWithRegion(t *testing.T) { client := Client{&fakeJSONCaller{}} region := "region" discoveryPath := "tenant/v2.0/.well-known/openid-configuration" - publicCloudEndpoint := fmt.Sprintf("https://%s.r.login.microsoftonline.com/%s", region, discoveryPath) + publicCloudEndpoint := fmt.Sprintf("https://%s.login.microsoft.com/%s", region, discoveryPath) for _, test := range []struct{ host, expectedEndpoint string }{ {"login.chinacloudapi.cn", fmt.Sprintf("https://%s.login.chinacloudapi.cn/%s", region, discoveryPath)}, {"login.microsoft.com", publicCloudEndpoint},