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" : "test", 106 "not_before" : "test", 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 := NewMultiTenantServicePrincipalTokenAuthorizer(mtSPTProvider) 295 req, err := Prepare(mocks.NewRequest(), mt.WithAuthorization()) 296 if err != nil { 297 t.Fatalf("unexpected error: %v", err) 298 } 299 if primary := req.Header.Get(headerAuthorization); primary != "Bearer primary" { 300 t.Fatalf("bad primary authorization header %s", primary) 301 } 302 if aux := req.Header.Get(headerAuxAuthorization); aux != "Bearer aux1; Bearer aux2; Bearer aux3" { 303 t.Fatalf("bad auxiliary authorization header %s", aux) 304 } 305} 306 307func TestMultiTenantServicePrincipalTokenWithAuthorizationRefresh(t *testing.T) { 308 multiTenantCfg, err := adal.NewMultiTenantOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID, []string{TestAuxTenent1, TestAuxTenent2, TestAuxTenent3}, adal.OAuthOptions{}) 309 if err != nil { 310 t.Fatalf("azure: adal#NewMultiTenantOAuthConfig returned an error (%v)", err) 311 } 312 mtSpt, err := adal.NewMultiTenantServicePrincipalToken(multiTenantCfg, "id", "secret", "resource") 313 if err != nil { 314 t.Fatalf("azure: adal#NewMultiTenantServicePrincipalToken returned an error (%v)", err) 315 } 316 317 primaryToken := `{ 318 "access_token" : "primary token refreshed", 319 "expires_in" : "3600", 320 "expires_on" : "test", 321 "not_before" : "test", 322 "resource" : "test", 323 "token_type" : "Bearer" 324 }` 325 326 auxToken1 := `{ 327 "access_token" : "aux token 1 refreshed", 328 "expires_in" : "3600", 329 "expires_on" : "test", 330 "not_before" : "test", 331 "resource" : "test", 332 "token_type" : "Bearer" 333 }` 334 335 auxToken2 := `{ 336 "access_token" : "aux token 2 refreshed", 337 "expires_in" : "3600", 338 "expires_on" : "test", 339 "not_before" : "test", 340 "resource" : "test", 341 "token_type" : "Bearer" 342 }` 343 344 auxToken3 := `{ 345 "access_token" : "aux token 3 refreshed", 346 "expires_in" : "3600", 347 "expires_on" : "test", 348 "not_before" : "test", 349 "resource" : "test", 350 "token_type" : "Bearer" 351 }` 352 353 s := mocks.NewSender() 354 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(primaryToken), http.StatusOK, "OK")) 355 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(auxToken1), http.StatusOK, "OK")) 356 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(auxToken2), http.StatusOK, "OK")) 357 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(auxToken3), http.StatusOK, "OK")) 358 359 mtSpt.PrimaryToken.SetSender(s) 360 for _, aux := range mtSpt.AuxiliaryTokens { 361 aux.SetSender(s) 362 } 363 364 mta := NewMultiTenantServicePrincipalTokenAuthorizer(mtSpt) 365 req, err := Prepare(mocks.NewRequest(), mta.WithAuthorization()) 366 if err != nil { 367 t.Fatalf("azure: multiTenantSPTAuthorizer#WithAuthorization returned an error (%v)", err) 368 } 369 if ah := req.Header.Get(http.CanonicalHeaderKey("Authorization")); ah != fmt.Sprintf("Bearer %s", mtSpt.PrimaryOAuthToken()) { 370 t.Fatal("azure: multiTenantSPTAuthorizer#WithAuthorization failed to set Authorization header for primary token") 371 } else if ah != "Bearer primary token refreshed" { 372 t.Fatal("azure: multiTenantSPTAuthorizer#WithAuthorization primary token value doesn't match") 373 } 374 auxTokens := mtSpt.AuxiliaryOAuthTokens() 375 for i := range auxTokens { 376 auxTokens[i] = fmt.Sprintf("Bearer %s", auxTokens[i]) 377 } 378 auxHeader := req.Header.Get(http.CanonicalHeaderKey(headerAuxAuthorization)) 379 if auxHeader != strings.Join(auxTokens, "; ") { 380 t.Fatal("azure: multiTenantSPTAuthorizer#WithAuthorization failed to set Authorization header for auxiliary tokens") 381 } 382 for i := range auxTokens { 383 if auxTokens[i] != fmt.Sprintf("Bearer aux token %d refreshed", i+1) { 384 t.Fatal("azure: multiTenantSPTAuthorizer#WithAuthorization auxiliary token value doesn't match") 385 } 386 } 387} 388 389func TestMultiTenantServicePrincipalTokenWithAuthorizationRefreshFail1(t *testing.T) { 390 multiTenantCfg, err := adal.NewMultiTenantOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID, []string{TestAuxTenent1, TestAuxTenent2, TestAuxTenent3}, adal.OAuthOptions{}) 391 if err != nil { 392 t.Fatalf("azure: adal#NewMultiTenantOAuthConfig returned an error (%v)", err) 393 } 394 mtSpt, err := adal.NewMultiTenantServicePrincipalToken(multiTenantCfg, "id", "secret", "resource") 395 if err != nil { 396 t.Fatalf("azure: adal#NewMultiTenantServicePrincipalToken returned an error (%v)", err) 397 } 398 399 s := mocks.NewSender() 400 s.AppendResponse(mocks.NewResponseWithStatus("access denied", http.StatusForbidden)) 401 402 mtSpt.PrimaryToken.SetSender(s) 403 for _, aux := range mtSpt.AuxiliaryTokens { 404 aux.SetSender(s) 405 } 406 407 mta := NewMultiTenantServicePrincipalTokenAuthorizer(mtSpt) 408 _, err = Prepare(mocks.NewRequest(), mta.WithAuthorization()) 409 if err == nil { 410 t.Fatalf("azure: multiTenantSPTAuthorizer#WithAuthorization unexpected nil error") 411 } 412} 413 414func TestMultiTenantServicePrincipalTokenWithAuthorizationRefreshFail2(t *testing.T) { 415 multiTenantCfg, err := adal.NewMultiTenantOAuthConfig(TestActiveDirectoryEndpoint, TestTenantID, []string{TestAuxTenent1, TestAuxTenent2, TestAuxTenent3}, adal.OAuthOptions{}) 416 if err != nil { 417 t.Fatalf("azure: adal#NewMultiTenantOAuthConfig returned an error (%v)", err) 418 } 419 mtSpt, err := adal.NewMultiTenantServicePrincipalToken(multiTenantCfg, "id", "secret", "resource") 420 if err != nil { 421 t.Fatalf("azure: adal#NewMultiTenantServicePrincipalToken returned an error (%v)", err) 422 } 423 424 primaryToken := `{ 425 "access_token" : "primary token refreshed", 426 "expires_in" : "3600", 427 "expires_on" : "test", 428 "not_before" : "test", 429 "resource" : "test", 430 "token_type" : "Bearer" 431 }` 432 433 s := mocks.NewSender() 434 s.AppendResponse(mocks.NewResponseWithBodyAndStatus(mocks.NewBody(primaryToken), http.StatusOK, "OK")) 435 s.AppendResponse(mocks.NewResponseWithStatus("access denied", http.StatusForbidden)) 436 437 mtSpt.PrimaryToken.SetSender(s) 438 for _, aux := range mtSpt.AuxiliaryTokens { 439 aux.SetSender(s) 440 } 441 442 mta := NewMultiTenantServicePrincipalTokenAuthorizer(mtSpt) 443 _, err = Prepare(mocks.NewRequest(), mta.WithAuthorization()) 444 if err == nil { 445 t.Fatalf("azure: multiTenantSPTAuthorizer#WithAuthorization unexpected nil error") 446 } 447} 448