...

Source file src/github.com/Azure/go-autorest/autorest/adal/config.go

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

     1  package adal
     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  	"errors"
    19  	"fmt"
    20  	"net/url"
    21  )
    22  
    23  const (
    24  	activeDirectoryEndpointTemplate = "%s/oauth2/%s%s"
    25  )
    26  
    27  // OAuthConfig represents the endpoints needed
    28  // in OAuth operations
    29  type OAuthConfig struct {
    30  	AuthorityEndpoint  url.URL `json:"authorityEndpoint"`
    31  	AuthorizeEndpoint  url.URL `json:"authorizeEndpoint"`
    32  	TokenEndpoint      url.URL `json:"tokenEndpoint"`
    33  	DeviceCodeEndpoint url.URL `json:"deviceCodeEndpoint"`
    34  }
    35  
    36  // IsZero returns true if the OAuthConfig object is zero-initialized.
    37  func (oac OAuthConfig) IsZero() bool {
    38  	return oac == OAuthConfig{}
    39  }
    40  
    41  func validateStringParam(param, name string) error {
    42  	if len(param) == 0 {
    43  		return fmt.Errorf("parameter '" + name + "' cannot be empty")
    44  	}
    45  	return nil
    46  }
    47  
    48  // NewOAuthConfig returns an OAuthConfig with tenant specific urls
    49  func NewOAuthConfig(activeDirectoryEndpoint, tenantID string) (*OAuthConfig, error) {
    50  	apiVer := "1.0"
    51  	return NewOAuthConfigWithAPIVersion(activeDirectoryEndpoint, tenantID, &apiVer)
    52  }
    53  
    54  // NewOAuthConfigWithAPIVersion returns an OAuthConfig with tenant specific urls.
    55  // If apiVersion is not nil the "api-version" query parameter will be appended to the endpoint URLs with the specified value.
    56  func NewOAuthConfigWithAPIVersion(activeDirectoryEndpoint, tenantID string, apiVersion *string) (*OAuthConfig, error) {
    57  	if err := validateStringParam(activeDirectoryEndpoint, "activeDirectoryEndpoint"); err != nil {
    58  		return nil, err
    59  	}
    60  	api := ""
    61  	// it's legal for tenantID to be empty so don't validate it
    62  	if apiVersion != nil {
    63  		if err := validateStringParam(*apiVersion, "apiVersion"); err != nil {
    64  			return nil, err
    65  		}
    66  		api = fmt.Sprintf("?api-version=%s", *apiVersion)
    67  	}
    68  	u, err := url.Parse(activeDirectoryEndpoint)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	authorityURL, err := u.Parse(tenantID)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	authorizeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "authorize", api))
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	tokenURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "token", api))
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  	deviceCodeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "devicecode", api))
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	return &OAuthConfig{
    90  		AuthorityEndpoint:  *authorityURL,
    91  		AuthorizeEndpoint:  *authorizeURL,
    92  		TokenEndpoint:      *tokenURL,
    93  		DeviceCodeEndpoint: *deviceCodeURL,
    94  	}, nil
    95  }
    96  
    97  // MultiTenantOAuthConfig provides endpoints for primary and aulixiary tenant IDs.
    98  type MultiTenantOAuthConfig interface {
    99  	PrimaryTenant() *OAuthConfig
   100  	AuxiliaryTenants() []*OAuthConfig
   101  }
   102  
   103  // OAuthOptions contains optional OAuthConfig creation arguments.
   104  type OAuthOptions struct {
   105  	APIVersion string
   106  }
   107  
   108  func (c OAuthOptions) apiVersion() string {
   109  	if c.APIVersion != "" {
   110  		return fmt.Sprintf("?api-version=%s", c.APIVersion)
   111  	}
   112  	return "1.0"
   113  }
   114  
   115  // NewMultiTenantOAuthConfig creates an object that support multitenant OAuth configuration.
   116  // See https://docs.microsoft.com/en-us/azure/azure-resource-manager/authenticate-multi-tenant for more information.
   117  func NewMultiTenantOAuthConfig(activeDirectoryEndpoint, primaryTenantID string, auxiliaryTenantIDs []string, options OAuthOptions) (MultiTenantOAuthConfig, error) {
   118  	if len(auxiliaryTenantIDs) == 0 || len(auxiliaryTenantIDs) > 3 {
   119  		return nil, errors.New("must specify one to three auxiliary tenants")
   120  	}
   121  	mtCfg := multiTenantOAuthConfig{
   122  		cfgs: make([]*OAuthConfig, len(auxiliaryTenantIDs)+1),
   123  	}
   124  	apiVer := options.apiVersion()
   125  	pri, err := NewOAuthConfigWithAPIVersion(activeDirectoryEndpoint, primaryTenantID, &apiVer)
   126  	if err != nil {
   127  		return nil, fmt.Errorf("failed to create OAuthConfig for primary tenant: %v", err)
   128  	}
   129  	mtCfg.cfgs[0] = pri
   130  	for i := range auxiliaryTenantIDs {
   131  		aux, err := NewOAuthConfig(activeDirectoryEndpoint, auxiliaryTenantIDs[i])
   132  		if err != nil {
   133  			return nil, fmt.Errorf("failed to create OAuthConfig for tenant '%s': %v", auxiliaryTenantIDs[i], err)
   134  		}
   135  		mtCfg.cfgs[i+1] = aux
   136  	}
   137  	return mtCfg, nil
   138  }
   139  
   140  type multiTenantOAuthConfig struct {
   141  	// first config in the slice is the primary tenant
   142  	cfgs []*OAuthConfig
   143  }
   144  
   145  func (m multiTenantOAuthConfig) PrimaryTenant() *OAuthConfig {
   146  	return m.cfgs[0]
   147  }
   148  
   149  func (m multiTenantOAuthConfig) AuxiliaryTenants() []*OAuthConfig {
   150  	return m.cfgs[1:]
   151  }
   152  

View as plain text