1package autorest 2 3// Copyright 2017 Microsoft Corporation 4// 5// Licensed under the Apache License, Version 2.0 (the "License"); 6// you may not use this file except in compliance with the License. 7// You may obtain a copy of the License at 8// 9// http://www.apache.org/licenses/LICENSE-2.0 10// 11// Unless required by applicable law or agreed to in writing, software 12// distributed under the License is distributed on an "AS IS" BASIS, 13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14// See the License for the specific language governing permissions and 15// limitations under the License. 16 17import ( 18 "fmt" 19 "net/http" 20 "reflect" 21 "strings" 22 "testing" 23 24 "github.com/Azure/go-autorest/autorest/adal" 25 "github.com/Azure/go-autorest/autorest/mocks" 26) 27 28const ( 29 TestTenantID = "TestTenantID" 30 TestAuxTenent1 = "aux1" 31 TestAuxTenent2 = "aux2" 32 TestAuxTenent3 = "aux3" 33 TestActiveDirectoryEndpoint = "https://login/test.com/" 34) 35 36func TestWithAuthorizer(t *testing.T) { 37 r1 := mocks.NewRequest() 38 39 na := &NullAuthorizer{} 40 r2, err := Prepare(r1, 41 na.WithAuthorization()) 42 if err != nil { 43 t.Fatalf("autorest: NullAuthorizer#WithAuthorization returned an unexpected error (%v)", err) 44 } else if !reflect.DeepEqual(r1, r2) { 45 t.Fatalf("autorest: NullAuthorizer#WithAuthorization modified the request -- received %v, expected %v", r2, r1) 46 } 47} 48 49func TestTokenWithAuthorization(t *testing.T) { 50 token := &adal.Token{ 51 AccessToken: "TestToken", 52 Resource: "https://azure.microsoft.com/", 53 Type: "Bearer", 54 } 55 56 ba := NewBearerAuthorizer(token) 57 req, err := Prepare(&http.Request{}, ba.WithAuthorization()) 58 if err != nil { 59 t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) 60 } else if req.Header.Get(http.CanonicalHeaderKey("Authorization")) != fmt.Sprintf("Bearer %s", token.AccessToken) { 61 t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to set Authorization header") 62 } 63} 64 65func TestServicePrincipalTokenWithAuthorizationNoRefresh(t *testing.T) { 66 oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) 67 if err != nil { 68 t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) 69 } 70 spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", "resource", nil) 71 if err != nil { 72 t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) 73 } 74 spt.SetAutoRefresh(false) 75 s := mocks.NewSender() 76 spt.SetSender(s) 77 78 ba := NewBearerAuthorizer(spt) 79 req, err := Prepare(mocks.NewRequest(), ba.WithAuthorization()) 80 if err != nil { 81 t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) 82 } else if req.Header.Get(http.CanonicalHeaderKey("Authorization")) != fmt.Sprintf("Bearer %s", spt.OAuthToken()) { 83 t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to set Authorization header") 84 } 85} 86 87func TestServicePrincipalTokenWithAuthorizationRefresh(t *testing.T) { 88 89 oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) 90 if err != nil { 91 t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) 92 } 93 refreshed := false 94 spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", "resource", func(t adal.Token) error { 95 refreshed = true 96 return nil 97 }) 98 if err != nil { 99 t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) 100 } 101 102 jwt := `{ 103 "access_token" : "accessToken", 104 "expires_in" : "3600", 105 "expires_on" : "12345", 106 "not_before" : "67890", 107 "resource" : "test", 108 "token_type" : "Bearer" 109 }` 110 body := mocks.NewBody(jwt) 111 resp := mocks.NewResponseWithBodyAndStatus(body, http.StatusOK, "OK") 112 c := mocks.NewSender() 113 s := DecorateSender(c, 114 (func() SendDecorator { 115 return func(s Sender) Sender { 116 return SenderFunc(func(r *http.Request) (*http.Response, error) { 117 return resp, nil 118 }) 119 } 120 })()) 121 spt.SetSender(s) 122 123 ba := NewBearerAuthorizer(spt) 124 req, err := Prepare(mocks.NewRequest(), ba.WithAuthorization()) 125 if err != nil { 126 t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) 127 } else if req.Header.Get(http.CanonicalHeaderKey("Authorization")) != fmt.Sprintf("Bearer %s", spt.OAuthToken()) { 128 t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to set Authorization header") 129 } 130 131 if !refreshed { 132 t.Fatal("azure: BearerAuthorizer#WithAuthorization must refresh the token") 133 } 134} 135 136func TestServicePrincipalTokenWithAuthorizationReturnsErrorIfConnotRefresh(t *testing.T) { 137 oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID) 138 if err != nil { 139 t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) 140 } 141 spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", "resource", nil) 142 if err != nil { 143 t.Fatalf("azure: BearerAuthorizer#WithAuthorization returned an error (%v)", err) 144 } 145 146 s := mocks.NewSender() 147 s.AppendResponse(mocks.NewResponseWithStatus("400 Bad Request", http.StatusBadRequest)) 148 spt.SetSender(s) 149 150 ba := NewBearerAuthorizer(spt) 151 _, err = Prepare(mocks.NewRequest(), ba.WithAuthorization()) 152 if err == nil { 153 t.Fatal("azure: BearerAuthorizer#WithAuthorization failed to return an error when refresh fails") 154 } 155} 156 157func TestBearerAuthorizerCallback(t *testing.T) { 158 tenantString := "123-tenantID-456" 159 resourceString := "https://fake.resource.net" 160 161 s := mocks.NewSender() 162 resp := mocks.NewResponseWithStatus("401 Unauthorized", http.StatusUnauthorized) 163 mocks.SetResponseHeader(resp, bearerChallengeHeader, bearer+" \"authorization\"=\"https://fake.net/"+tenantString+"\",\"resource\"=\""+resourceString+"\"") 164 s.AppendResponse(resp) 165 166 auth := NewBearerAuthorizerCallback(s, func(tenantID, resource string) (*BearerAuthorizer, error) { 167 if tenantID != tenantString { 168 t.Fatal("BearerAuthorizerCallback: bad tenant ID") 169 } 170 if resource != resourceString { 171 t.Fatal("BearerAuthorizerCallback: bad resource") 172 } 173 174 oauthConfig, err := adal.NewOAuthConfig(TestActiveDirectoryEndpoint, tenantID) 175 if err != nil { 176 t.Fatalf("azure: NewOAuthConfig returned an error (%v)", err) 177 } 178 179 spt, err := adal.NewServicePrincipalToken(*oauthConfig, "id", "secret", resource) 180 if err != nil { 181 t.Fatalf("azure: NewServicePrincipalToken returned an error (%v)", err) 182 } 183 184 spt.SetSender(s) 185 return NewBearerAuthorizer(spt), nil 186 }) 187 188 _, err := Prepare(mocks.NewRequest(), auth.WithAuthorization()) 189 if err == nil { 190 t.Fatal("azure: BearerAuthorizerCallback#WithAuthorization failed to return an error when refresh fails") 191 } 192} 193 194func TestApiKeyAuthorization(t *testing.T) { 195 196 headers := make(map[string]interface{}) 197 queryParameters := make(map[string]interface{}) 198 199 dummyAuthHeader := "dummyAuthHeader" 200 dummyAuthHeaderValue := "dummyAuthHeaderValue" 201 202 dummyAuthQueryParameter := "dummyAuthQueryParameter" 203 dummyAuthQueryParameterValue := "dummyAuthQueryParameterValue" 204 205 headers[dummyAuthHeader] = dummyAuthHeaderValue 206 queryParameters[dummyAuthQueryParameter] = dummyAuthQueryParameterValue 207 208 aka := NewAPIKeyAuthorizer(headers, queryParameters) 209 210 req, err := Prepare(mocks.NewRequest(), aka.WithAuthorization()) 211 212 if err != nil { 213 t.Fatalf("azure: APIKeyAuthorizer#WithAuthorization returned an error (%v)", err) 214 } else if req.Header.Get(http.CanonicalHeaderKey(dummyAuthHeader)) != dummyAuthHeaderValue { 215 t.Fatalf("azure: APIKeyAuthorizer#WithAuthorization failed to set %s header", dummyAuthHeader) 216 217 } else if req.URL.Query().Get(dummyAuthQueryParameter) != dummyAuthQueryParameterValue { 218 t.Fatalf("azure: APIKeyAuthorizer#WithAuthorization failed to set %s query parameter", dummyAuthQueryParameterValue) 219 } 220} 221 222func TestCognitivesServicesAuthorization(t *testing.T) { 223 subscriptionKey := "dummyKey" 224 csa := NewCognitiveServicesAuthorizer(subscriptionKey) 225 req, err := Prepare(mocks.NewRequest(), csa.WithAuthorization()) 226 227 if err != nil { 228 t.Fatalf("azure: CognitiveServicesAuthorizer#WithAuthorization returned an error (%v)", err) 229 } else if req.Header.Get(http.CanonicalHeaderKey(bingAPISdkHeader)) != golangBingAPISdkHeaderValue { 230 t.Fatalf("azure: CognitiveServicesAuthorizer#WithAuthorization failed to set %s header", bingAPISdkHeader) 231 } else if req.Header.Get(http.CanonicalHeaderKey(apiKeyAuthorizerHeader)) != subscriptionKey { 232 t.Fatalf("azure: CognitiveServicesAuthorizer#WithAuthorization failed to set %s header", apiKeyAuthorizerHeader) 233 } 234} 235 236func TestBasicAuthorization(t *testing.T) { 237 ba := NewBasicAuthorizer("Aladdin", "open sesame") 238 req, err := Prepare(mocks.NewRequest(), ba.WithAuthorization()) 239 240 if err != nil { 241 t.Fatalf("BasicAuthorizer#WithAuthorization returned an error (%v)", err) 242 } else if req.Header.Get(http.CanonicalHeaderKey(authorization)) != basic+" QWxhZGRpbjpvcGVuIHNlc2FtZQ==" { 243 t.Fatalf("BasicAuthorizer#WithAuthorization failed to set %s header", authorization) 244 } 245} 246 247func TestBasicAuthorizationPasswordOnly(t *testing.T) { 248 ba := NewBasicAuthorizer("", "dummyKey") 249 req, err := Prepare(mocks.NewRequest(), ba.WithAuthorization()) 250 251 if err != nil { 252 t.Fatalf("BasicAuthorizer#WithAuthorization returned an error (%v)", err) 253 } else if req.Header.Get(http.CanonicalHeaderKey(authorization)) != basic+" OmR1bW15S2V5" { 254 t.Fatalf("BasicAuthorizer#WithAuthorization failed to set %s header", authorization) 255 } 256} 257 258type mockMTSPTProvider struct { 259 p string 260 a []string 261} 262 263func (m mockMTSPTProvider) PrimaryOAuthToken() string { 264 return m.p 265} 266 267func (m mockMTSPTProvider) AuxiliaryOAuthTokens() []string { 268 return m.a 269} 270 271func TestMultitenantAuthorizationOne(t *testing.T) { 272 mtSPTProvider := mockMTSPTProvider{ 273 p: "primary", 274 a: []string{TestAuxTenent1}, 275 } 276 mt := NewMultiTenantServicePrincipalTokenAuthorizer(mtSPTProvider) 277 req, err := Prepare(mocks.NewRequest(), mt.WithAuthorization()) 278 if err != nil { 279 t.Fatalf("unexpected error: %v", err) 280 } 281 if primary := req.Header.Get(headerAuthorization); primary != "Bearer primary" { 282 t.Fatalf("bad primary authorization header %s", primary) 283 } 284 if aux := req.Header.Get(headerAuxAuthorization); aux != "Bearer aux1" { 285 t.Fatalf("bad auxiliary authorization header %s", aux) 286 } 287} 288 289func TestMultitenantAuthorizationThree(t *testing.T) { 290 mtSPTProvider := mockMTSPTProvider{ 291 p: "primary", 292 a: []string{TestAuxTenent1, TestAuxTenent2, TestAuxTenent3}, 293 } 294 mt := NewMultiTenantBearerAuthorizer(mtSPTProvider) 295 req, err := Prepare(mocks.NewRequest(), mt.WithAuthorization()) 296 if err != nil { 297 t.Fatalf("unexpected error: %v", err) 298 } 299 if primary := mt.TokenProvider().PrimaryOAuthToken(); primary != mtSPTProvider.p { 300 t.Fatalf("bad primary authorization token %s", primary) 301 } 302 if aux := strings.Join(mt.TokenProvider().AuxiliaryOAuthTokens(), ","); aux != strings.Join(mtSPTProvider.a, ",") { 303 t.Fatalf("bad auxiliary authorization tokens %s", aux) 304 } 305 if primary := req.Header.Get(headerAuthorization); primary != "Bearer primary" { 306 t.Fatalf("bad primary authorization header %s", primary) 307 } 308 if aux := req.Header.Get(headerAuxAuthorization); aux != "Bearer aux1, Bearer aux2, Bearer aux3" { 309 t.Fatalf("bad auxiliary authorization header %s", aux) 310 } 311} 312 313func TestMultiTenantServicePrincipalTokenWithAuthorizationRefresh(t *testing.T) { 314 multiTenantCfg, err := adal.NewMultiTenantOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID, []string{TestAuxTenent1, TestAuxTenent2, TestAuxTenent3}, adal.OAuthOptions{}) 315 if err != nil { 316 t.Fatalf("azure: adal#NewMultiTenantOAuthConfig returned an error (%v)", err) 317 } 318 mtSpt, err := adal.NewMultiTenantServicePrincipalToken(multiTenantCfg, "id", "secret", "resource") 319 if err != nil { 320 t.Fatalf("azure: adal#NewMultiTenantServicePrincipalToken returned an error (%v)", err) 321 } 322 323 primaryToken := `{ 324 "access_token" : "primary token refreshed", 325 "expires_in" : "3600", 326 "expires_on" : "12345", 327 "not_before" : "67890", 328 "resource" : "test", 329 "token_type" : "Bearer" 330 }` 331 332 auxToken1 := `{ 333 "access_token" : "aux token 1 refreshed", 334 "expires_in" : "3600", 335 "expires_on" : "12345", 336 "not_before" : "67890", 337 "resource" : "test", 338 "token_type" : "Bearer" 339 }` 340 341 auxToken2 := `{ 342 "access_token" : "aux token 2 refreshed", 343 "expires_in" : "3600", 344 "expires_on" : "12345", 345 "not_before" : "67890", 346 "resource" : "test", 347 "token_type" : "Bearer" 348 }` 349 350 auxToken3 := `{ 351 "access_token" : "aux token 3 refreshed", 352 "expires_in" : "3600", 353 "expires_on" : "12345", 354 "not_before" : "67890", 355 "resource" : "test", 356 "token_type" : "Bearer" 357 }` 358 359 s := mocks.NewSender() 360 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(primaryToken), http.StatusOK, "OK")) 361 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(auxToken1), http.StatusOK, "OK")) 362 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(auxToken2), http.StatusOK, "OK")) 363 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(auxToken3), http.StatusOK, "OK")) 364 365 mtSpt.PrimaryToken.SetSender(s) 366 for _, aux := range mtSpt.AuxiliaryTokens { 367 aux.SetSender(s) 368 } 369 370 mta := NewMultiTenantServicePrincipalTokenAuthorizer(mtSpt) 371 req, err := Prepare(mocks.NewRequest(), mta.WithAuthorization()) 372 if err != nil { 373 t.Fatalf("azure: multiTenantSPTAuthorizer#WithAuthorization returned an error (%v)", err) 374 } 375 if ah := req.Header.Get(http.CanonicalHeaderKey("Authorization")); ah != fmt.Sprintf("Bearer %s", mtSpt.PrimaryOAuthToken()) { 376 t.Fatal("azure: multiTenantSPTAuthorizer#WithAuthorization failed to set Authorization header for primary token") 377 } else if ah != "Bearer primary token refreshed" { 378 t.Fatal("azure: multiTenantSPTAuthorizer#WithAuthorization primary token value doesn't match") 379 } 380 auxTokens := mtSpt.AuxiliaryOAuthTokens() 381 for i := range auxTokens { 382 auxTokens[i] = fmt.Sprintf("Bearer %s", auxTokens[i]) 383 } 384 auxHeader := req.Header.Get(http.CanonicalHeaderKey(headerAuxAuthorization)) 385 if auxHeader != strings.Join(auxTokens, ", ") { 386 t.Fatal("azure: multiTenantSPTAuthorizer#WithAuthorization failed to set Authorization header for auxiliary tokens") 387 } 388 for i := range auxTokens { 389 if auxTokens[i] != fmt.Sprintf("Bearer aux token %d refreshed", i+1) { 390 t.Fatal("azure: multiTenantSPTAuthorizer#WithAuthorization auxiliary token value doesn't match") 391 } 392 } 393} 394 395func TestMultiTenantServicePrincipalTokenWithAuthorizationRefreshFail1(t *testing.T) { 396 multiTenantCfg, err := adal.NewMultiTenantOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID, []string{TestAuxTenent1, TestAuxTenent2, TestAuxTenent3}, adal.OAuthOptions{}) 397 if err != nil { 398 t.Fatalf("azure: adal#NewMultiTenantOAuthConfig returned an error (%v)", err) 399 } 400 mtSpt, err := adal.NewMultiTenantServicePrincipalToken(multiTenantCfg, "id", "secret", "resource") 401 if err != nil { 402 t.Fatalf("azure: adal#NewMultiTenantServicePrincipalToken returned an error (%v)", err) 403 } 404 405 s := mocks.NewSender() 406 s.AppendResponse(mocks.NewResponseWithStatus("access denied", http.StatusForbidden)) 407 408 mtSpt.PrimaryToken.SetSender(s) 409 for _, aux := range mtSpt.AuxiliaryTokens { 410 aux.SetSender(s) 411 } 412 413 mta := NewMultiTenantServicePrincipalTokenAuthorizer(mtSpt) 414 _, err = Prepare(mocks.NewRequest(), mta.WithAuthorization()) 415 if err == nil { 416 t.Fatalf("azure: multiTenantSPTAuthorizer#WithAuthorization unexpected nil error") 417 } 418} 419 420func TestMultiTenantServicePrincipalTokenWithAuthorizationRefreshFail2(t *testing.T) { 421 multiTenantCfg, err := adal.NewMultiTenantOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID, []string{TestAuxTenent1, TestAuxTenent2, TestAuxTenent3}, adal.OAuthOptions{}) 422 if err != nil { 423 t.Fatalf("azure: adal#NewMultiTenantOAuthConfig returned an error (%v)", err) 424 } 425 mtSpt, err := adal.NewMultiTenantServicePrincipalToken(multiTenantCfg, "id", "secret", "resource") 426 if err != nil { 427 t.Fatalf("azure: adal#NewMultiTenantServicePrincipalToken returned an error (%v)", err) 428 } 429 430 primaryToken := `{ 431 "access_token" : "primary token refreshed", 432 "expires_in" : "3600", 433 "expires_on" : "test", 434 "not_before" : "test", 435 "resource" : "test", 436 "token_type" : "Bearer" 437 }` 438 439 s := mocks.NewSender() 440 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(primaryToken), http.StatusOK, "OK")) 441 s.AppendResponse(mocks.NewResponseWithStatus("access denied", http.StatusForbidden)) 442 443 mtSpt.PrimaryToken.SetSender(s) 444 for _, aux := range mtSpt.AuxiliaryTokens { 445 aux.SetSender(s) 446 } 447 448 mta := NewMultiTenantServicePrincipalTokenAuthorizer(mtSpt) 449 _, err = Prepare(mocks.NewRequest(), mta.WithAuthorization()) 450 if err == nil { 451 t.Fatalf("azure: multiTenantSPTAuthorizer#WithAuthorization unexpected nil error") 452 } 453} 454