github.com/Axway/agent-sdk@v1.1.101/pkg/config/externalidpconfig.go (about)

     1  package config
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strconv"
     7  
     8  	"github.com/Axway/agent-sdk/pkg/cmd/properties"
     9  	"github.com/Axway/agent-sdk/pkg/util/exception"
    10  )
    11  
    12  const (
    13  	AccessToken             = "accessToken"
    14  	Client                  = "client"
    15  	ClientSecretBasic       = "client_secret_basic"
    16  	ClientSecretPost        = "client_secret_post"
    17  	ClientSecretJWT         = "client_secret_jwt"
    18  	PrivateKeyJWT           = "private_key_jwt"
    19  	TLSClientAuth           = "tls_client_auth"
    20  	SelfSignedTLSClientAuth = "self_signed_tls_client_auth"
    21  
    22  	propInsecureSkipVerify      = "insecureSkipVerify"
    23  	propUseCachedToken          = "useCachedToken"
    24  	propUseRegistrationToken    = "useRegistrationToken"
    25  	pathExternalIDP             = "agentFeatures.idp"
    26  	fldName                     = "name"
    27  	fldTitle                    = "title"
    28  	fldType                     = "type"
    29  	fldMetadataURL              = "metadataUrl"
    30  	fldExtraProperties          = "extraProperties"
    31  	fldRequestHeaders           = "requestHeaders"
    32  	fldQueryParams              = "queryParams"
    33  	fldScope                    = "scope"
    34  	fldGrantType                = "grantType"
    35  	fldAuthMethod               = "authMethod"
    36  	fldAuthResponseType         = "authResponseType"
    37  	fldAuthType                 = "auth.type"
    38  	fldAuthRequestHeaders       = "auth.requestHeaders"
    39  	fldAuthQueryParams          = "auth.queryParams"
    40  	fldAuthAccessToken          = "auth.accessToken"
    41  	fldAuthClientID             = "auth.clientId"
    42  	fldAuthClientSecret         = "auth.clientSecret"
    43  	fldAuthClientScope          = "auth.clientScope"
    44  	fldAuthPrivateKey           = "auth.privateKey"
    45  	fldAuthPublicKey            = "auth.publicKey"
    46  	fldAuthKeyPassword          = "auth.keyPassword"
    47  	fldAuthTokenSigningMethod   = "auth.tokenSigningMethod"
    48  	fldAuthUseCachedToken       = "auth." + propUseCachedToken
    49  	fldAuthUseRegistrationToken = "auth." + propUseRegistrationToken
    50  	fldSSLInsecureSkipVerify    = "ssl." + propInsecureSkipVerify
    51  	fldSSLRootCACertPath        = "ssl.rootCACertPath"
    52  	fldSSLClientCertPath        = "ssl.clientCertPath"
    53  	fldSSLClientKeyPath         = "ssl.clientKeyPath"
    54  )
    55  
    56  var configProperties = []string{
    57  	fldName,
    58  	fldTitle,
    59  	fldType,
    60  	fldMetadataURL,
    61  	fldExtraProperties,
    62  	fldRequestHeaders,
    63  	fldQueryParams,
    64  	fldScope,
    65  	fldGrantType,
    66  	fldAuthMethod,
    67  	fldAuthResponseType,
    68  	fldAuthType,
    69  	fldAuthRequestHeaders,
    70  	fldAuthQueryParams,
    71  	fldAuthAccessToken,
    72  	fldAuthClientID,
    73  	fldAuthClientSecret,
    74  	fldAuthClientScope,
    75  	fldSSLInsecureSkipVerify,
    76  	fldSSLRootCACertPath,
    77  	fldSSLClientCertPath,
    78  	fldSSLClientKeyPath,
    79  	fldAuthPrivateKey,
    80  	fldAuthPublicKey,
    81  	fldAuthKeyPassword,
    82  	fldAuthTokenSigningMethod,
    83  	fldAuthUseCachedToken,
    84  	fldAuthUseRegistrationToken,
    85  }
    86  
    87  var validIDPAuthType = map[string]bool{
    88  	AccessToken:             true,
    89  	Client:                  true,
    90  	ClientSecretBasic:       true,
    91  	ClientSecretPost:        true,
    92  	ClientSecretJWT:         true,
    93  	PrivateKeyJWT:           true,
    94  	SelfSignedTLSClientAuth: true,
    95  	TLSClientAuth:           true,
    96  }
    97  
    98  // ExternalIDPConfig -
    99  type ExternalIDPConfig interface {
   100  	GetIDPList() []IDPConfig
   101  	ValidateCfg() (err error)
   102  }
   103  
   104  type externalIDPConfig struct {
   105  	IDPConfigs map[string]IDPConfig
   106  }
   107  
   108  func (e *externalIDPConfig) GetIDPList() []IDPConfig {
   109  	list := make([]IDPConfig, 0)
   110  	for _, idpCfg := range e.IDPConfigs {
   111  		list = append(list, idpCfg)
   112  	}
   113  	return list
   114  }
   115  
   116  func (e *externalIDPConfig) ValidateCfg() (err error) {
   117  	for _, idpCfg := range e.IDPConfigs {
   118  		exception.Block{
   119  			Try: func() {
   120  				idpCfg.validate()
   121  			},
   122  			Catch: func(e error) {
   123  				err = e
   124  			},
   125  		}.Do()
   126  	}
   127  	return err
   128  }
   129  
   130  // ExtraProperties - type for representing extra IdP provider properties to be included in client request
   131  type ExtraProperties map[string]string
   132  
   133  // UnmarshalJSON - deserializes extra properties from env config
   134  func (e *ExtraProperties) UnmarshalJSON(data []byte) error {
   135  	ep := map[string]string(*e)
   136  	return parseKeyValuePairs(ep, data)
   137  }
   138  
   139  // IDPRequestHeaders - additional request headers for calls to IdP
   140  type IDPRequestHeaders map[string]string
   141  
   142  // UnmarshalJSON - deserializes request header from env config
   143  func (e *IDPRequestHeaders) UnmarshalJSON(data []byte) error {
   144  	headers := map[string]string(*e)
   145  	return parseKeyValuePairs(headers, data)
   146  }
   147  
   148  // IDPQueryParams - additional query params for calls to IdP
   149  type IDPQueryParams map[string]string
   150  
   151  // UnmarshalJSON - deserializes query parameters from env config
   152  func (e *IDPQueryParams) UnmarshalJSON(data []byte) error {
   153  	qp := map[string]string(*e)
   154  	return parseKeyValuePairs(qp, data)
   155  }
   156  
   157  func parseKeyValuePairs(kv map[string]string, data []byte) error {
   158  	m := make(map[string]string)
   159  	// try parsing the data as json string, ground agent config setup as json string
   160  	buf, err := strconv.Unquote(string(data))
   161  	if err != nil {
   162  		// parse as json map in case data is not json string
   163  		buf = string(data)
   164  	}
   165  	err = json.Unmarshal([]byte(buf), &m)
   166  	if err != nil {
   167  		return err
   168  	}
   169  
   170  	for key, val := range m {
   171  		kv[key] = val
   172  	}
   173  	return nil
   174  }
   175  
   176  // IDPAuthConfig - interface for IdP provider auth config
   177  type IDPAuthConfig interface {
   178  	// GetType - type of authentication mechanism to use "accessToken" or "client"
   179  	GetType() string
   180  	// GetAccessToken - token(initial access token/Admin API Token etc) to be used by Agent SDK to authenticate with IdP
   181  	GetAccessToken() string
   182  	// GetClientID - Identifier of the client in IdP that can used to create new OAuth clients
   183  	GetClientID() string
   184  	// GetClientSecret - Secret for the client in IdP that can used to create new OAuth clients
   185  	GetClientSecret() string
   186  	// GetClientScope - Scopes used for requesting the token using the ID client
   187  	GetClientScope() string
   188  	// validate - Validates the IDP auth configuration
   189  	validate(tlsCfg TLSConfig)
   190  	// GetPrivateKey() - private key to be used for private_key_jwt authentication
   191  	GetPrivateKey() string
   192  	// GetPublicKey() - public key to be used for private_key_jwt authentication
   193  	GetPublicKey() string
   194  	// GetKeyPassword() - public key to be used for private_key_jwt authentication
   195  	GetKeyPassword() string
   196  	// GetSigningMethod() - the token signing method for private_key_jwt authentication
   197  	GetTokenSigningMethod() string
   198  	// UseTokenCache() - return flag to indicate if the auth client to get new token on each request
   199  	UseTokenCache() bool
   200  	// UseRegistrationAccessToken - return flag to indicate if the auth client to use registration access token
   201  	UseRegistrationAccessToken() bool
   202  	// GetRequestHeaders - set of additional request headers to be applied when registering the client
   203  	GetRequestHeaders() map[string]string
   204  	// GetQueryParams - set of additional query parameters to be applied when registering the client
   205  	GetQueryParams() map[string]string
   206  }
   207  
   208  // IDPConfig - interface for IdP provider config
   209  type IDPConfig interface {
   210  	// GetMetadataURL - URL exposed by OAuth authorization server to provide metadata information
   211  	GetMetadataURL() string
   212  	// GetIDPType - IDP type ("generic" or "okta")
   213  	GetIDPType() string
   214  	// GetIDPName - for the identity provider
   215  	GetIDPName() string
   216  	// GetIDPTitle - for the identity provider friendly name
   217  	GetIDPTitle() string
   218  	// GetAuthConfig - to be used for authentication with IDP
   219  	GetAuthConfig() IDPAuthConfig
   220  	// GetClientScopes - default list of scopes that are included in the client metadata request to IDP
   221  	GetClientScopes() string
   222  	// GetGrantType - default grant type to be used when creating the client. (default :  "client_credentials")
   223  	GetGrantType() string
   224  	// GetAuthMethod - default token endpoint authentication method(default : "client_secret_basic")
   225  	GetAuthMethod() string
   226  	// GetAuthResponseType - default token response type to be used when registering the client
   227  	GetAuthResponseType() string
   228  	// GetExtraProperties - set of additional properties to be applied when registering the client
   229  	GetExtraProperties() map[string]string
   230  	// GetRequestHeaders - set of additional request headers to be applied when registering the client
   231  	GetRequestHeaders() map[string]string
   232  	// GetQueryParams - set of additional query parameters to be applied when registering the client
   233  	GetQueryParams() map[string]string
   234  	// GetTLSConfig - tls config for IDP connection
   235  	GetTLSConfig() TLSConfig
   236  	// validate - Validates the IDP configuration
   237  	validate()
   238  }
   239  
   240  // IDPAuthConfiguration - Structure to hold the IdP provider auth config
   241  type IDPAuthConfiguration struct {
   242  	Type                 string            `json:"type,omitempty"`
   243  	RequestHeaders       IDPRequestHeaders `json:"requestHeaders,omitempty"`
   244  	QueryParams          IDPQueryParams    `json:"queryParams,omitempty"`
   245  	AccessToken          string            `json:"accessToken,omitempty"`
   246  	ClientID             string            `json:"clientId,omitempty"`
   247  	ClientSecret         string            `json:"clientSecret,omitempty"`
   248  	ClientScope          string            `json:"clientScope,omitempty"`
   249  	PrivateKey           string            `json:"privateKey,omitempty"`
   250  	PublicKey            string            `json:"publicKey,omitempty"`
   251  	KeyPwd               string            `json:"keyPassword,omitempty"`
   252  	TokenSigningMethod   string            `json:"tokenSigningMethod,omitempty"`
   253  	UseCachedToken       bool              `json:"-"`
   254  	UseRegistrationToken bool              `json:"-"`
   255  }
   256  
   257  // IDPConfiguration - Structure to hold the IdP provider config
   258  type IDPConfiguration struct {
   259  	Name             string            `json:"name,omitempty"`
   260  	Title            string            `json:"title,omitempty"`
   261  	Type             string            `json:"type,omitempty"`
   262  	MetadataURL      string            `json:"metadataUrl,omitempty"`
   263  	AuthConfig       IDPAuthConfig     `json:"auth,omitempty"`
   264  	ClientScopes     string            `json:"scope,omitempty"`
   265  	GrantType        string            `json:"grantType,omitempty"`
   266  	AuthMethod       string            `json:"authMethod,omitempty"`
   267  	AuthResponseType string            `json:"authResponseType,omitempty"`
   268  	ExtraProperties  ExtraProperties   `json:"extraProperties,omitempty"`
   269  	RequestHeaders   IDPRequestHeaders `json:"requestHeaders,omitempty"`
   270  	QueryParams      IDPQueryParams    `json:"queryParams,omitempty"`
   271  	TLSConfig        TLSConfig         `json:"-"`
   272  }
   273  
   274  // GetIDPName - for the identity provider
   275  func (i *IDPConfiguration) GetIDPName() string {
   276  	return i.Name
   277  }
   278  
   279  // GetIDPName - for the identity provider frinedly name
   280  func (i *IDPConfiguration) GetIDPTitle() string {
   281  	return i.Title
   282  }
   283  
   284  // GetIDPType - IDP type ("generic" or "okta")
   285  func (i *IDPConfiguration) GetIDPType() string {
   286  	return i.Type
   287  }
   288  
   289  // GetAuthConfig - to be used for authentication with IDP
   290  func (i *IDPConfiguration) GetAuthConfig() IDPAuthConfig {
   291  	return i.AuthConfig
   292  }
   293  
   294  // GetMetadataURL - URL exposed by OAuth authorization server to provide metadata information
   295  func (i *IDPConfiguration) GetMetadataURL() string {
   296  	return i.MetadataURL
   297  }
   298  
   299  // GetExtraProperties - set of additional properties to be applied when registering the client
   300  func (i *IDPConfiguration) GetExtraProperties() map[string]string {
   301  	return i.ExtraProperties
   302  }
   303  
   304  // GetRequestHeaders - set of additional request headers to be applied when registering the client
   305  func (i *IDPConfiguration) GetRequestHeaders() map[string]string {
   306  	return i.RequestHeaders
   307  }
   308  
   309  // GetQueryParams - set of additional query params to be applied when registering the client
   310  func (i *IDPConfiguration) GetQueryParams() map[string]string {
   311  	return i.QueryParams
   312  }
   313  
   314  // GetClientScopes - default list of scopes that are included in the client metadata request to IDP
   315  func (i *IDPConfiguration) GetClientScopes() string {
   316  	return i.ClientScopes
   317  }
   318  
   319  // GetGrantType - default grant type to be used when creating the client. (default :  "client_credentials")
   320  func (i *IDPConfiguration) GetGrantType() string {
   321  	return i.GrantType
   322  }
   323  
   324  // GetAuthMethod - default token endpoint authentication method(default : "client_secret_basic")
   325  func (i *IDPConfiguration) GetAuthMethod() string {
   326  	return i.AuthMethod
   327  }
   328  
   329  // GetAuthResponseType - default token response type to be used when registering the client
   330  func (i *IDPConfiguration) GetAuthResponseType() string {
   331  	return i.AuthResponseType
   332  }
   333  
   334  // GetTLSConfig - tls config for IDP connection
   335  func (i *IDPConfiguration) GetTLSConfig() TLSConfig {
   336  	return i.TLSConfig
   337  }
   338  
   339  // UnmarshalJSON - custom unmarshaler for IDPConfiguration struct
   340  func (i *IDPConfiguration) UnmarshalJSON(data []byte) error {
   341  	type Alias IDPConfiguration
   342  	i.RequestHeaders = make(IDPRequestHeaders)
   343  	i.QueryParams = make(IDPQueryParams)
   344  	i.ExtraProperties = make(ExtraProperties)
   345  
   346  	i.AuthConfig = &IDPAuthConfiguration{
   347  		RequestHeaders: make(IDPRequestHeaders),
   348  		QueryParams:    make(IDPQueryParams),
   349  	}
   350  	if err := json.Unmarshal(data, &struct{ *Alias }{Alias: (*Alias)(i)}); err != nil {
   351  		return err
   352  	}
   353  
   354  	var allFields interface{}
   355  	json.Unmarshal(data, &allFields)
   356  	b := allFields.(map[string]interface{})
   357  
   358  	if v, ok := b["auth"]; ok {
   359  		buf, _ := json.Marshal(v)
   360  		json.Unmarshal(buf, i.AuthConfig)
   361  	}
   362  
   363  	return nil
   364  }
   365  
   366  // MarshalJSON - custom marshaler for IDPConfiguration struct
   367  func (i *IDPConfiguration) MarshalJSON() ([]byte, error) {
   368  	type Alias IDPConfiguration
   369  
   370  	idp, err := json.Marshal(&struct{ *Alias }{Alias: (*Alias)(i)})
   371  	if err != nil {
   372  		return nil, err
   373  	}
   374  	var allFields interface{}
   375  	json.Unmarshal(idp, &allFields)
   376  	b := allFields.(map[string]interface{})
   377  
   378  	idpAuthCfg, err := json.Marshal(i.AuthConfig)
   379  	if err != nil {
   380  		return nil, err
   381  	}
   382  
   383  	m := make(map[string]interface{})
   384  	json.Unmarshal(idpAuthCfg, &m)
   385  	b["auth"] = m
   386  
   387  	return json.Marshal(b)
   388  }
   389  
   390  // validate - Validates the IDP configuration
   391  func (i *IDPConfiguration) validate() {
   392  	if i.Name == "" {
   393  		exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldName))
   394  	}
   395  	if i.Title == "" {
   396  		i.Title = i.Name
   397  	}
   398  
   399  	if i.MetadataURL == "" {
   400  		exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldMetadataURL))
   401  	}
   402  
   403  	i.AuthConfig.validate(i.TLSConfig)
   404  }
   405  
   406  // GetType - type of authentication mechanism to use "accessToken" or "client"
   407  func (i *IDPAuthConfiguration) GetType() string {
   408  	return i.Type
   409  }
   410  
   411  // GetRequestHeaders - set of additional request headers to be applied when registering the client
   412  func (i *IDPAuthConfiguration) GetRequestHeaders() map[string]string {
   413  	return i.RequestHeaders
   414  }
   415  
   416  // GetQueryParams - set of additional query params to be applied when registering the client
   417  func (i *IDPAuthConfiguration) GetQueryParams() map[string]string {
   418  	return i.QueryParams
   419  }
   420  
   421  // GetAccessToken - token(initial access token/Admin API Token etc) to be used by Agent SDK to authenticate with IdP
   422  func (i *IDPAuthConfiguration) GetAccessToken() string {
   423  	return i.AccessToken
   424  }
   425  
   426  // GetClientID - Identifier of the client in IdP that can used to create new OAuth client
   427  func (i *IDPAuthConfiguration) GetClientID() string {
   428  	return i.ClientID
   429  }
   430  
   431  // GetClientSecret - Secret for the client in IdP that can used to create new OAuth clients
   432  func (i *IDPAuthConfiguration) GetClientSecret() string {
   433  	return i.ClientSecret
   434  }
   435  
   436  // GetClientScope - scopes used for requesting the token using the ID client
   437  func (i *IDPAuthConfiguration) GetClientScope() string {
   438  	return i.ClientScope
   439  }
   440  
   441  // GetPrivateKey -
   442  func (i *IDPAuthConfiguration) GetPrivateKey() string {
   443  	return i.PrivateKey
   444  }
   445  
   446  // GetPublicKey -
   447  func (i *IDPAuthConfiguration) GetPublicKey() string {
   448  	return i.PublicKey
   449  }
   450  
   451  // GetKeyPassword -
   452  func (i *IDPAuthConfiguration) GetKeyPassword() string {
   453  	return i.KeyPwd
   454  }
   455  
   456  // GetTokenSigningMethod -
   457  func (i *IDPAuthConfiguration) GetTokenSigningMethod() string {
   458  	return i.TokenSigningMethod
   459  }
   460  
   461  // UseTokenCache - return flag to indicate if the auth client to get new token on each request
   462  func (i *IDPAuthConfiguration) UseTokenCache() bool {
   463  	return i.UseCachedToken
   464  }
   465  
   466  // UseRegistrationAccessToken - return flag to indicate if the auth client to use registration access token
   467  func (i *IDPAuthConfiguration) UseRegistrationAccessToken() bool {
   468  	return i.UseRegistrationToken
   469  }
   470  
   471  // UnmarshalJSON - custom unmarshaler for IDPAuthConfiguration struct
   472  func (i *IDPAuthConfiguration) UnmarshalJSON(data []byte) error {
   473  	type Alias IDPAuthConfiguration // Create an intermittent type to unmarshal the base attributes
   474  
   475  	if err := json.Unmarshal(data, &struct{ *Alias }{Alias: (*Alias)(i)}); err != nil {
   476  		return err
   477  	}
   478  
   479  	var allFields interface{}
   480  	json.Unmarshal(data, &allFields)
   481  	b := allFields.(map[string]interface{})
   482  
   483  	// Default to use the cached token
   484  	i.UseCachedToken = true
   485  	if v, ok := b[propUseCachedToken]; ok {
   486  		i.UseCachedToken = (v == "true")
   487  	}
   488  	// Default to use not use registration access token
   489  	i.UseRegistrationToken = false
   490  	if v, ok := b[propUseRegistrationToken]; ok {
   491  		i.UseRegistrationToken = (v == "true")
   492  	}
   493  	return nil
   494  }
   495  
   496  // MarshalJSON - custom marshaler for Application struct
   497  func (i *IDPAuthConfiguration) MarshalJSON() ([]byte, error) {
   498  	type Alias IDPAuthConfiguration // Create an intermittent type to marshal the base attributes
   499  
   500  	app, err := json.Marshal(&struct{ *Alias }{Alias: (*Alias)(i)})
   501  	if err != nil {
   502  		return nil, err
   503  	}
   504  
   505  	// decode it back to get a map
   506  	var allFields interface{}
   507  	json.Unmarshal(app, &allFields)
   508  	b := allFields.(map[string]interface{})
   509  
   510  	if i.UseCachedToken {
   511  		b[propUseCachedToken] = "true"
   512  	}
   513  
   514  	// Return encoding of the map
   515  	return json.Marshal(b)
   516  }
   517  
   518  // validate - Validates the IDP auth configuration
   519  func (i *IDPAuthConfiguration) validate(tlsCfg TLSConfig) {
   520  	if ok := validIDPAuthType[i.GetType()]; !ok {
   521  		exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthType))
   522  	}
   523  
   524  	switch i.GetType() {
   525  	case AccessToken:
   526  		i.validateAccessTokenAuthConfig()
   527  	case Client:
   528  		fallthrough
   529  	case ClientSecretBasic:
   530  		fallthrough
   531  	case ClientSecretPost:
   532  		fallthrough
   533  	case ClientSecretJWT:
   534  		i.validateClientSecretAuthConfig()
   535  	case PrivateKeyJWT:
   536  		i.validatePrivateKeyJwtAuthConfig()
   537  	case TLSClientAuth:
   538  		fallthrough
   539  	case SelfSignedTLSClientAuth:
   540  		i.validateTLSClientAuthConfig(tlsCfg)
   541  	}
   542  }
   543  
   544  func (i *IDPAuthConfiguration) validateAccessTokenAuthConfig() {
   545  	if i.GetAccessToken() == "" {
   546  		exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthAccessToken))
   547  	}
   548  }
   549  
   550  func (i *IDPAuthConfiguration) validateClientIDConfig() {
   551  	if i.GetClientID() == "" {
   552  		exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthClientID))
   553  	}
   554  }
   555  
   556  func (i *IDPAuthConfiguration) validateClientSecretConfig() {
   557  	if i.GetClientSecret() == "" {
   558  		exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldAuthClientSecret))
   559  	}
   560  }
   561  
   562  func (i *IDPAuthConfiguration) validateClientSecretAuthConfig() {
   563  	i.validateClientIDConfig()
   564  	i.validateClientSecretConfig()
   565  }
   566  
   567  func (i *IDPAuthConfiguration) validatePrivateKeyJwtAuthConfig() {
   568  	i.validateClientIDConfig()
   569  
   570  	validateAuthFileConfig(pathExternalIDP+"."+fldAuthPrivateKey, i.PrivateKey, "", "private key")
   571  	validateAuthFileConfig(pathExternalIDP+"."+fldAuthPublicKey, i.PublicKey, "", "public key")
   572  }
   573  
   574  func (i *IDPAuthConfiguration) validateTLSClientAuthConfig(tlsCfg TLSConfig) {
   575  	i.validateClientIDConfig()
   576  
   577  	if tlsCfg == nil {
   578  		exception.Throw(ErrBadConfig.FormatError(pathExternalIDP + "." + fldSSLClientCertPath))
   579  	}
   580  	validateAuthFileConfig(pathExternalIDP+"."+fldSSLClientCertPath, tlsCfg.(*TLSConfiguration).ClientCertificatePath, "", "tls client certificate")
   581  	validateAuthFileConfig(pathExternalIDP+"."+fldSSLClientKeyPath, tlsCfg.(*TLSConfiguration).ClientKeyPath, "", "tls client key")
   582  }
   583  
   584  func addExternalIDPProperties(props properties.Properties) {
   585  	props.AddObjectSliceProperty(pathExternalIDP, configProperties)
   586  }
   587  
   588  func parseExternalIDPConfig(props properties.Properties) (ExternalIDPConfig, error) {
   589  	envIDPCfgList := props.ObjectSlicePropertyValue(pathExternalIDP)
   590  
   591  	cfg := &externalIDPConfig{
   592  		IDPConfigs: make(map[string]IDPConfig),
   593  	}
   594  
   595  	for _, envIdpCfg := range envIDPCfgList {
   596  		idpCfg := &IDPConfiguration{
   597  			AuthConfig: &IDPAuthConfiguration{
   598  				RequestHeaders: make(IDPRequestHeaders),
   599  				QueryParams:    make(IDPQueryParams),
   600  			},
   601  			ExtraProperties:  make(ExtraProperties),
   602  			RequestHeaders:   make(IDPRequestHeaders),
   603  			QueryParams:      make(IDPQueryParams),
   604  			ClientScopes:     "resource.READ resource.WRITE",
   605  			GrantType:        "client_credentials",
   606  			AuthMethod:       "client_secret_basic",
   607  			AuthResponseType: "token",
   608  		}
   609  
   610  		buf, _ := json.Marshal(envIdpCfg)
   611  		err := json.Unmarshal(buf, idpCfg)
   612  		if err != nil {
   613  			return nil, fmt.Errorf("error parsing idp configuration, %s", err)
   614  		}
   615  		if entry, ok := envIdpCfg["ssl"]; ok && entry != nil {
   616  			idpCfg.TLSConfig = parseExternalIDPTLSConfig(entry)
   617  		}
   618  		cfg.IDPConfigs[idpCfg.Name] = idpCfg
   619  	}
   620  
   621  	return cfg, nil
   622  }
   623  
   624  func parseExternalIDPTLSConfig(idpTLSCfg interface{}) TLSConfig {
   625  	tlsCfg := NewTLSConfig()
   626  	tlsConfig, ok := idpTLSCfg.(map[string]interface{})
   627  	if ok {
   628  		buf, _ := json.Marshal(tlsConfig)
   629  		json.Unmarshal(buf, tlsCfg)
   630  		v := tlsConfig[propInsecureSkipVerify]
   631  		if s, ok := v.(string); ok && s == "true" {
   632  			tlsCfg.(*TLSConfiguration).InsecureSkipVerify = true
   633  		}
   634  	}
   635  	return tlsCfg
   636  }