Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 102 additions & 17 deletions auth/provider_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,15 @@ const (
spEntityIDKey = "spConfig.spEntityId"
callbackURIKey = "spConfig.callbackUri"

clientIDKey = "clientId"
issuerKey = "issuer"
clientIDKey = "clientId"
clientSecretKey = "clientSecret"
issuerKey = "issuer"

displayNameKey = "displayName"
enabledKey = "enabled"

idTokenResponseTypeKey = "responseType.idToken"
codeResponseTypeKey = "responseType.code"
)

type nestedMap map[string]interface{}
Expand Down Expand Up @@ -113,11 +117,14 @@ func buildMask(data map[string]interface{}) []string {
// OIDCProviderConfig is the OIDC auth provider configuration.
// See https://openid.net/specs/openid-connect-core-1_0-final.html.
type OIDCProviderConfig struct {
ID string
DisplayName string
Enabled bool
ClientID string
Issuer string
ID string
DisplayName string
Enabled bool
ClientID string
Issuer string
ClientSecret string
CodeResponseType bool
IDTokenResponseType bool
}

// OIDCProviderConfigToCreate represents the options used to create a new OIDCProviderConfig.
Expand Down Expand Up @@ -152,6 +159,27 @@ func (config *OIDCProviderConfigToCreate) Enabled(enabled bool) *OIDCProviderCon
return config.set(enabledKey, enabled)
}

// ClientSecret sets the client secret for the new provider.
// This is required for the code flow.
func (config *OIDCProviderConfigToCreate) ClientSecret(secret string) *OIDCProviderConfigToCreate {
return config.set(clientSecretKey, secret)
}

// IDTokenResponseType sets whether to enable the ID token response flow for the new provider.
// By default, this is enabled if no response type is specified.
// Having both the code and ID token response flows is currently not supported.
func (config *OIDCProviderConfigToCreate) IDTokenResponseType(enabled bool) *OIDCProviderConfigToCreate {
return config.set(idTokenResponseTypeKey, enabled)
}

// CodeResponseType sets whether to enable the code response flow for the new provider.
// By default, this is not enabled if no response type is specified.
// A client secret must be set for this response type.
// Having both the code and ID token response flows is currently not supported.
func (config *OIDCProviderConfigToCreate) CodeResponseType(enabled bool) *OIDCProviderConfigToCreate {
return config.set(codeResponseTypeKey, enabled)
}

func (config *OIDCProviderConfigToCreate) set(key string, value interface{}) *OIDCProviderConfigToCreate {
if config.params == nil {
config.params = make(nestedMap)
Expand Down Expand Up @@ -180,6 +208,19 @@ func (config *OIDCProviderConfigToCreate) buildRequest() (nestedMap, string, err
return nil, "", fmt.Errorf("failed to parse Issuer: %v", err)
}

if val, ok := config.params.Get(codeResponseTypeKey); ok && val.(bool) {
if val, ok := config.params.GetString(clientSecretKey); !ok || val == "" {
return nil, "", errors.New("Client Secret must not be empty for Code Response Type")
}
if val, ok := config.params.Get(idTokenResponseTypeKey); ok && val.(bool) {
return nil, "", errors.New("Only one response type may be chosen")
}
} else if ok && !val.(bool) {
if val, ok := config.params.Get(idTokenResponseTypeKey); ok && !val.(bool) {
return nil, "", errors.New("At least one response type must be returned")
}
}

return config.params, config.id, nil
}

Expand Down Expand Up @@ -213,6 +254,27 @@ func (config *OIDCProviderConfigToUpdate) Enabled(enabled bool) *OIDCProviderCon
return config.set(enabledKey, enabled)
}

// ClientSecret sets the client secret for the provider.
// This is required for the code flow.
func (config *OIDCProviderConfigToUpdate) ClientSecret(secret string) *OIDCProviderConfigToUpdate {
return config.set(clientSecretKey, secret)
}

// IDTokenResponseType sets whether to enable the ID token response flow for the provider.
// By default, this is enabled if no response type is specified.
// Having both the code and ID token response flows is currently not supported.
func (config *OIDCProviderConfigToUpdate) IDTokenResponseType(enabled bool) *OIDCProviderConfigToUpdate {
return config.set(idTokenResponseTypeKey, enabled)
}

// CodeResponseType sets whether to enable the code response flow for the new provider.
// By default, this is not enabled if no response type is specified.
// A client secret must be set for this response type.
// Having both the code and ID token response flows is currently not supported.
func (config *OIDCProviderConfigToUpdate) CodeResponseType(enabled bool) *OIDCProviderConfigToUpdate {
return config.set(codeResponseTypeKey, enabled)
}

func (config *OIDCProviderConfigToUpdate) set(key string, value interface{}) *OIDCProviderConfigToUpdate {
if config.params == nil {
config.params = make(nestedMap)
Expand Down Expand Up @@ -240,6 +302,19 @@ func (config *OIDCProviderConfigToUpdate) buildRequest() (nestedMap, error) {
}
}

if val, ok := config.params.Get(codeResponseTypeKey); ok && val.(bool) {
if val, ok := config.params.GetString(clientSecretKey); !ok || val == "" {
return nil, errors.New("Client Secret must not be empty for Code Response Type")
}
if val, ok := config.params.Get(idTokenResponseTypeKey); ok && val.(bool) {
return nil, errors.New("Only one response type may be chosen")
}
} else if ok && !val.(bool) {
if val, ok := config.params.Get(idTokenResponseTypeKey); ok && !val.(bool) {
return nil, errors.New("At least one response type must be returned")
}
}

return config.params, nil
}

Expand Down Expand Up @@ -826,20 +901,30 @@ func (c *baseClient) makeRequest(
}

type oidcProviderConfigDAO struct {
Name string `json:"name"`
ClientID string `json:"clientId"`
Issuer string `json:"issuer"`
DisplayName string `json:"displayName"`
Enabled bool `json:"enabled"`
Name string `json:"name"`
ClientID string `json:"clientId"`
Issuer string `json:"issuer"`
DisplayName string `json:"displayName"`
Enabled bool `json:"enabled"`
ClientSecret string `json:"clientSecret"`
ResponseType oidcProviderResponseType `json:"responseType"`
}

type oidcProviderResponseType struct {
Code bool `json:"code"`
IDToken bool `json:"idToken"`
}

func (dao *oidcProviderConfigDAO) toOIDCProviderConfig() *OIDCProviderConfig {
return &OIDCProviderConfig{
ID: extractResourceID(dao.Name),
DisplayName: dao.DisplayName,
Enabled: dao.Enabled,
ClientID: dao.ClientID,
Issuer: dao.Issuer,
ID: extractResourceID(dao.Name),
DisplayName: dao.DisplayName,
Enabled: dao.Enabled,
ClientID: dao.ClientID,
Issuer: dao.Issuer,
ClientSecret: dao.ClientSecret,
CodeResponseType: dao.ResponseType.Code,
IDTokenResponseType: dao.ResponseType.IDToken,
}
}

Expand Down
Loading