From ccfd5e45000c6a9925aa09309ab83323749ed487 Mon Sep 17 00:00:00 2001 From: Oscar Zhou <100548325+oscarzhou-portainer@users.noreply.github.com> Date: Mon, 22 Apr 2024 10:35:26 +1200 Subject: [PATCH] feat(setting/oauth): add authstyle option [EE-6038] (#11590) --- .../test_data/output_24_to_latest.json | 1 + api/http/handler/settings/settings_update.go | 5 ++ api/oauth/oauth.go | 5 +- api/portainer.go | 28 ++++++----- app/portainer/models/settings.js | 1 + .../oauth-settings.controller.js | 9 +++- .../oauth-settings/oauth-settings.html | 2 + .../components/oauth-settings/providers.js | 6 ++- app/portainer/react/components/settings.ts | 12 +++++ .../OAuth/AuthStyleField.tsx | 49 +++++++++++++++++++ .../AuthenticationView/OAuth/index.ts | 1 + app/react/portainer/settings/types.ts | 9 ++++ 12 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 app/react/portainer/settings/AuthenticationView/OAuth/AuthStyleField.tsx create mode 100644 app/react/portainer/settings/AuthenticationView/OAuth/index.ts diff --git a/api/datastore/test_data/output_24_to_latest.json b/api/datastore/test_data/output_24_to_latest.json index b76e357f3..88b3ef248 100644 --- a/api/datastore/test_data/output_24_to_latest.json +++ b/api/datastore/test_data/output_24_to_latest.json @@ -631,6 +631,7 @@ "LogoURL": "", "OAuthSettings": { "AccessTokenURI": "", + "AuthStyle": 0, "AuthorizationURI": "", "ClientID": "", "DefaultTeamID": 0, diff --git a/api/http/handler/settings/settings_update.go b/api/http/handler/settings/settings_update.go index 574050c4d..2b9ceb5c3 100644 --- a/api/http/handler/settings/settings_update.go +++ b/api/http/handler/settings/settings_update.go @@ -13,6 +13,7 @@ import ( httperror "github.com/portainer/portainer/pkg/libhttp/error" "github.com/portainer/portainer/pkg/libhttp/request" "github.com/portainer/portainer/pkg/libhttp/response" + "golang.org/x/oauth2" "github.com/asaskevich/govalidator" "github.com/pkg/errors" @@ -95,6 +96,9 @@ func (payload *settingsUpdatePayload) Validate(r *http.Request) error { } } + if payload.OAuthSettings.AuthStyle < oauth2.AuthStyleAutoDetect || payload.OAuthSettings.AuthStyle > oauth2.AuthStyleInHeader { + return errors.New("Invalid OAuth AuthStyle") + } return nil } @@ -225,6 +229,7 @@ func (handler *Handler) updateSettings(tx dataservices.DataStoreTx, payload sett settings.OAuthSettings = *payload.OAuthSettings settings.OAuthSettings.ClientSecret = clientSecret settings.OAuthSettings.KubeSecretKey = kubeSecret + settings.OAuthSettings.AuthStyle = payload.OAuthSettings.AuthStyle } if payload.EnableEdgeComputeFeatures != nil { diff --git a/api/oauth/oauth.go b/api/oauth/oauth.go index 678c2fff8..86c0dd148 100644 --- a/api/oauth/oauth.go +++ b/api/oauth/oauth.go @@ -172,8 +172,9 @@ func getResource(token string, configuration *portainer.OAuthSettings) (map[stri func buildConfig(configuration *portainer.OAuthSettings) *oauth2.Config { endpoint := oauth2.Endpoint{ - AuthURL: configuration.AuthorizationURI, - TokenURL: configuration.AccessTokenURI, + AuthURL: configuration.AuthorizationURI, + TokenURL: configuration.AccessTokenURI, + AuthStyle: configuration.AuthStyle, } return &oauth2.Config{ diff --git a/api/portainer.go b/api/portainer.go index f68c4a5a3..474c0485c 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -12,6 +12,7 @@ import ( gittypes "github.com/portainer/portainer/api/git/types" models "github.com/portainer/portainer/api/http/models/kubernetes" "github.com/portainer/portainer/pkg/featureflags" + "golang.org/x/oauth2" v1 "k8s.io/api/core/v1" ) @@ -758,19 +759,20 @@ type ( // OAuthSettings represents the settings used to authorize with an authorization server OAuthSettings struct { - ClientID string `json:"ClientID"` - ClientSecret string `json:"ClientSecret,omitempty"` - AccessTokenURI string `json:"AccessTokenURI"` - AuthorizationURI string `json:"AuthorizationURI"` - ResourceURI string `json:"ResourceURI"` - RedirectURI string `json:"RedirectURI"` - UserIdentifier string `json:"UserIdentifier"` - Scopes string `json:"Scopes"` - OAuthAutoCreateUsers bool `json:"OAuthAutoCreateUsers"` - DefaultTeamID TeamID `json:"DefaultTeamID"` - SSO bool `json:"SSO"` - LogoutURI string `json:"LogoutURI"` - KubeSecretKey []byte `json:"KubeSecretKey"` + ClientID string `json:"ClientID"` + ClientSecret string `json:"ClientSecret,omitempty"` + AccessTokenURI string `json:"AccessTokenURI"` + AuthorizationURI string `json:"AuthorizationURI"` + ResourceURI string `json:"ResourceURI"` + RedirectURI string `json:"RedirectURI"` + UserIdentifier string `json:"UserIdentifier"` + Scopes string `json:"Scopes"` + OAuthAutoCreateUsers bool `json:"OAuthAutoCreateUsers"` + DefaultTeamID TeamID `json:"DefaultTeamID"` + SSO bool `json:"SSO"` + LogoutURI string `json:"LogoutURI"` + KubeSecretKey []byte `json:"KubeSecretKey"` + AuthStyle oauth2.AuthStyle `json:"AuthStyle"` } // Pair defines a key/value string pair diff --git a/app/portainer/models/settings.js b/app/portainer/models/settings.js index e27c408df..0d1bda9fa 100644 --- a/app/portainer/models/settings.js +++ b/app/portainer/models/settings.js @@ -78,6 +78,7 @@ export function OAuthSettingsViewModel(data) { this.DefaultTeamID = data.DefaultTeamID; this.SSO = data.SSO; this.LogoutURI = data.LogoutURI; + this.AuthStyle = data.AuthStyle; } export function EdgeSettingsViewModel(data = {}) { diff --git a/app/portainer/oauth/components/oauth-settings/oauth-settings.controller.js b/app/portainer/oauth/components/oauth-settings/oauth-settings.controller.js index dd2fbde56..4e23a3ccd 100644 --- a/app/portainer/oauth/components/oauth-settings/oauth-settings.controller.js +++ b/app/portainer/oauth/components/oauth-settings/oauth-settings.controller.js @@ -4,7 +4,6 @@ import { isLimitedToBE } from '@/react/portainer/feature-flags/feature-flags.ser import { ModalType } from '@@/modals'; import { confirm } from '@@/modals/confirm'; import { buildConfirmButton } from '@@/modals/utils'; - import providers, { getProviderByUrl } from './providers'; const MS_TENANT_ID_PLACEHOLDER = 'TENANT_ID'; @@ -31,6 +30,7 @@ export default class OAuthSettingsController { this.addTeamMembershipMapping = this.addTeamMembershipMapping.bind(this); this.removeTeamMembership = this.removeTeamMembership.bind(this); this.onToggleAutoTeamMembership = this.onToggleAutoTeamMembership.bind(this); + this.onChangeAuthStyle = this.onChangeAuthStyle.bind(this); } onMicrosoftTenantIDChange() { @@ -54,6 +54,7 @@ export default class OAuthSettingsController { this.settings.LogoutURI = provider.logoutUrl; this.settings.UserIdentifier = provider.userIdentifier; this.settings.Scopes = provider.scopes; + this.settings.AuthStyle = provider.authStyle; if (providerId === 'microsoft' && this.state.microsoftTenantID !== '') { this.onMicrosoftTenantIDChange(); @@ -77,6 +78,12 @@ export default class OAuthSettingsController { }); } + onChangeAuthStyle(val) { + this.$scope.$evalAsync(() => { + this.settings.AuthStyle = val; + }); + } + async onChangeHideInternalAuth(checked) { this.$async(async () => { if (this.isLimitedToBE) { diff --git a/app/portainer/oauth/components/oauth-settings/oauth-settings.html b/app/portainer/oauth/components/oauth-settings/oauth-settings.html index 63d8c5598..186c2f245 100644 --- a/app/portainer/oauth/components/oauth-settings/oauth-settings.html +++ b/app/portainer/oauth/components/oauth-settings/oauth-settings.html @@ -341,6 +341,8 @@ /> + + +