@@ -11,6 +11,7 @@ import (
1111 "fmt"
1212 "io"
1313 "net/http"
14+ "net/url"
1415 "strings"
1516)
1617
@@ -41,9 +42,17 @@ func (m *mockSTS) Do(req *http.Request) (*http.Response, error) {
4142 }
4243 switch s := strings .Split (req .URL .Path , "/" ); s [len (s )- 1 ] {
4344 case "instance" :
44- res .Body = io .NopCloser (bytes .NewReader (instanceMetadata (tenant )))
45+ host := req .URL .Host
46+ if ae := req .URL .Query ().Get ("authorization_endpoint" ); ae != "" {
47+ u , err := url .Parse (ae )
48+ if err != nil {
49+ return nil , fmt .Errorf ("mockSTS failed to parse an authorization_endpoint query parameter: %w" , err )
50+ }
51+ host = u .Host
52+ }
53+ res .Body = io .NopCloser (bytes .NewReader (instanceMetadata (host , tenant )))
4554 case "openid-configuration" :
46- res .Body = io .NopCloser (bytes .NewReader (tenantMetadata (tenant )))
55+ res .Body = io .NopCloser (bytes .NewReader (tenantMetadata (req . URL . Host , tenant )))
4756 case "devicecode" :
4857 res .Body = io .NopCloser (strings .NewReader (`{"device_code":"...","expires_in":600,"interval":60}` ))
4958 case "token" :
@@ -53,7 +62,7 @@ func (m *mockSTS) Do(req *http.Request) (*http.Response, error) {
5362 if grant := req .FormValue ("grant_type" ); grant == "device_code" || grant == "password" {
5463 // include account info because we're authenticating a user
5564 res .Body = io .NopCloser (bytes .NewReader (
56- [] byte ( fmt .Sprintf ( `{"access_token":%q,"expires_in": 3600,"refresh_token":"rt","client_info":%q,"id_token":%q,"token_type":"Bearer"}` , tokenValue , mockClientInfo , mockIDT ) ),
65+ fmt .Appendf ( nil , `{"access_token":%q,"expires_in": 3600,"refresh_token":"rt","client_info":%q,"id_token":%q,"token_type":"Bearer"}` , tokenValue , mockClientInfo , mockIDT ),
5766 ))
5867 } else {
5968 res .Body = io .NopCloser (bytes .NewReader (accessTokenRespSuccess ))
@@ -77,91 +86,29 @@ func (m *mockSTS) Do(req *http.Request) (*http.Response, error) {
7786 return res , nil
7887}
7988
80- func instanceMetadata (tenant string ) []byte {
81- return []byte (strings .ReplaceAll (`{
82- "tenant_discovery_endpoint": "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration",
83- "api-version": "1.1",
84- "metadata": [
85- {
86- "preferred_network": "login.microsoftonline.com",
87- "preferred_cache": "login.windows.net",
88- "aliases": [
89- "login.microsoftonline.com",
90- "login.windows.net",
91- "login.microsoft.com",
92- "sts.windows.net"
93- ]
94- }
95- ]
96- }` , "{tenant}" , tenant ))
89+ func instanceMetadata (host , tenant string ) []byte {
90+ tmpl := `{
91+ "tenant_discovery_endpoint": "https://{host}/{tenant}/v2.0/.well-known/openid-configuration",
92+ "api-version": "1.1",
93+ "metadata": [
94+ {
95+ "preferred_network": "{host}",
96+ "preferred_cache": "{host}",
97+ "aliases": ["{host}"]
98+ }
99+ ]
100+ }`
101+ r := strings .NewReplacer ("{host}" , host , "{tenant}" , tenant )
102+ return []byte (r .Replace (tmpl ))
97103}
98104
99- func tenantMetadata (tenant string ) []byte {
100- return []byte (strings .ReplaceAll (`{
101- "token_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
102- "token_endpoint_auth_methods_supported": [
103- "client_secret_post",
104- "private_key_jwt",
105- "client_secret_basic"
106- ],
107- "jwks_uri": "https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys",
108- "response_modes_supported": [
109- "query",
110- "fragment",
111- "form_post"
112- ],
113- "subject_types_supported": [
114- "pairwise"
115- ],
116- "id_token_signing_alg_values_supported": [
117- "RS256"
118- ],
119- "response_types_supported": [
120- "code",
121- "id_token",
122- "code id_token",
123- "id_token token"
124- ],
125- "scopes_supported": [
126- "openid",
127- "profile",
128- "email",
129- "offline_access"
130- ],
131- "issuer": "https://login.microsoftonline.com/{tenant}/v2.0",
132- "request_uri_parameter_supported": false,
133- "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo",
134- "authorization_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize",
135- "device_authorization_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/devicecode",
136- "http_logout_supported": true,
137- "frontchannel_logout_supported": true,
138- "end_session_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/logout",
139- "claims_supported": [
140- "sub",
141- "iss",
142- "cloud_instance_name",
143- "cloud_instance_host_name",
144- "cloud_graph_host_name",
145- "msgraph_host",
146- "aud",
147- "exp",
148- "iat",
149- "auth_time",
150- "acr",
151- "nonce",
152- "preferred_username",
153- "name",
154- "tid",
155- "ver",
156- "at_hash",
157- "c_hash",
158- "email"
159- ],
160- "kerberos_endpoint": "https://login.microsoftonline.com/{tenant}/kerberos",
161- "tenant_region_scope": "NA",
162- "cloud_instance_name": "microsoftonline.com",
163- "cloud_graph_host_name": "graph.windows.net",
164- "msgraph_host": "graph.microsoft.com",
165- "rbac_url": "https://pas.windows.net"
166- }` , "{tenant}" , tenant ))
105+ func tenantMetadata (host , tenant string ) []byte {
106+ // real metadata has many more fields; these are the only ones MSAL uses
107+ tmpl := `{
108+ "token_endpoint": "{base}/oauth2/v2.0/token",
109+ "issuer": "{base}/v2.0",
110+ "authorization_endpoint": "{base}/oauth2/v2.0/authorize",
111+ "device_authorization_endpoint": "{base}/oauth2/v2.0/devicecode"
112+ }`
113+ return []byte (strings .ReplaceAll (tmpl , "{base}" , "https://" + host + "/" + tenant ))
167114}
0 commit comments