...

Source file src/github.com/Azure/go-autorest/autorest/authorization_test.go

Documentation: github.com/Azure/go-autorest/autorest

     1  package 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  
    17  import (
    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  
    28  const (
    29  	TestTenantID                = "TestTenantID"
    30  	TestAuxTenent1              = "aux1"
    31  	TestAuxTenent2              = "aux2"
    32  	TestAuxTenent3              = "aux3"
    33  	TestActiveDirectoryEndpoint = "https://login/test.com/"
    34  )
    35  
    36  func 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  
    49  func 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  
    65  func 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  
    87  func 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  
   136  func 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  
   157  func 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  
   194  func 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  
   222  func 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  
   236  func 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  
   247  func 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  
   258  type mockMTSPTProvider struct {
   259  	p string
   260  	a []string
   261  }
   262  
   263  func (m mockMTSPTProvider) PrimaryOAuthToken() string {
   264  	return m.p
   265  }
   266  
   267  func (m mockMTSPTProvider) AuxiliaryOAuthTokens() []string {
   268  	return m.a
   269  }
   270  
   271  func 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  
   289  func 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  
   313  func 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  
   395  func 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  
   420  func 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  

View as plain text