diff --git a/console/src/app/pages/projects/apps/app-create/app-create.component.html b/console/src/app/pages/projects/apps/app-create/app-create.component.html index ad2ba14c65..af6a5328ed 100644 --- a/console/src/app/pages/projects/apps/app-create/app-create.component.html +++ b/console/src/app/pages/projects/apps/app-create/app-create.component.html @@ -307,7 +307,7 @@ -
+
{{ 'APP.OIDC.REDIRECT' | translate }} @@ -322,7 +322,7 @@
-
+
{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }} diff --git a/console/src/app/pages/projects/apps/app-detail/app-detail.component.ts b/console/src/app/pages/projects/apps/app-detail/app-detail.component.ts index bd0eef9fd0..68f7996eee 100644 --- a/console/src/app/pages/projects/apps/app-detail/app-detail.component.ts +++ b/console/src/app/pages/projects/apps/app-detail/app-detail.component.ts @@ -77,6 +77,7 @@ export class AppDetailComponent implements OnInit, OnDestroy { public authMethods: RadioItemAuthType[] = []; private subscription?: Subscription; public projectId: string = ''; + public appId: string = ''; public app?: App.AsObject; public environmentMap$ = this.envSvc.env.pipe( @@ -252,6 +253,7 @@ export class AppDetailComponent implements OnInit, OnDestroy { if (projectId && appId) { this.projectId = projectId; + this.appId = appId; this.getData(projectId, appId); } } @@ -639,6 +641,9 @@ export class AppDetailComponent implements OnInit, OnDestroy { this.currentAuthMethod = this.authMethodFromPartialConfig(config); } this.toast.showInfo('APP.TOAST.OIDCUPDATED', true); + setTimeout(() => { + this.getData(this.projectId, this.appId); + }, 1000); }) .catch((error) => { this.toast.showError(error); diff --git a/console/src/app/pages/projects/apps/authmethods.ts b/console/src/app/pages/projects/apps/authmethods.ts index d79c5d40ad..566748bb06 100644 --- a/console/src/app/pages/projects/apps/authmethods.ts +++ b/console/src/app/pages/projects/apps/authmethods.ts @@ -95,7 +95,7 @@ export const DEVICE_CODE_METHOD: RadioItemAuthType = { prefix: 'DEVICECODE', background: 'linear-gradient(40deg, rgb(56 189 248) 30%, rgb(14 165 233))', responseType: OIDCResponseType.OIDC_RESPONSE_TYPE_CODE, - grantType: [OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE, OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE], + grantType: [OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE], authMethod: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC, recommended: false, }; @@ -133,7 +133,7 @@ export function getPartialConfigFromAuthMethod(authMethod: string): config = { oidc: { responseTypesList: [OIDCResponseType.OIDC_RESPONSE_TYPE_CODE], - grantTypesList: [OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE, OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE], + grantTypesList: [OIDCGrantType.OIDC_GRANT_TYPE_DEVICE_CODE], authMethodType: OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE, }, }; diff --git a/internal/domain/application_oidc.go b/internal/domain/application_oidc.go index a5a8c0b2ba..2481000951 100644 --- a/internal/domain/application_oidc.go +++ b/internal/domain/application_oidc.go @@ -149,17 +149,22 @@ func (a *OIDCApp) OriginsValid() bool { } func ContainsRequiredGrantTypes(responseTypes []OIDCResponseType, grantTypes []OIDCGrantType) bool { - required := RequiredOIDCGrantTypes(responseTypes) + required := RequiredOIDCGrantTypes(responseTypes, grantTypes) return ContainsOIDCGrantTypes(required, grantTypes) } -func RequiredOIDCGrantTypes(responseTypes []OIDCResponseType) (grantTypes []OIDCGrantType) { +func RequiredOIDCGrantTypes(responseTypes []OIDCResponseType, grantTypesSet []OIDCGrantType) (grantTypes []OIDCGrantType) { var implicit bool for _, r := range responseTypes { switch r { case OIDCResponseTypeCode: - grantTypes = append(grantTypes, OIDCGrantTypeAuthorizationCode) + // #5684 when "Device Code" is selected, "Authorization Code" is no longer a hard requirement + if !containsOIDCGrantType(grantTypesSet, OIDCGrantTypeDeviceCode) { + grantTypes = append(grantTypes, OIDCGrantTypeAuthorizationCode) + } else { + grantTypes = append(grantTypes, OIDCGrantTypeDeviceCode) + } case OIDCResponseTypeIDToken, OIDCResponseTypeIDTokenToken: if !implicit { implicit = true @@ -172,7 +177,7 @@ func RequiredOIDCGrantTypes(responseTypes []OIDCResponseType) (grantTypes []OIDC } func (a *OIDCApp) getRequiredGrantTypes() []OIDCGrantType { - return RequiredOIDCGrantTypes(a.ResponseTypes) + return RequiredOIDCGrantTypes(a.ResponseTypes, a.GrantTypes) } func ContainsOIDCGrantTypes(shouldContain, list []OIDCGrantType) bool { @@ -222,14 +227,15 @@ func GetOIDCV1Compliance(appType OIDCApplicationType, grantTypes []OIDCGrantType } func checkGrantTypesCombination(compliance *Compliance, grantTypes []OIDCGrantType) { - if containsOIDCGrantType(grantTypes, OIDCGrantTypeRefreshToken) && !containsOIDCGrantType(grantTypes, OIDCGrantTypeAuthorizationCode) { + if !containsOIDCGrantType(grantTypes, OIDCGrantTypeDeviceCode) && containsOIDCGrantType(grantTypes, OIDCGrantTypeRefreshToken) && !containsOIDCGrantType(grantTypes, OIDCGrantTypeAuthorizationCode) { compliance.NoneCompliant = true compliance.Problems = append(compliance.Problems, "Application.OIDC.V1.GrantType.Refresh.NoAuthCode") } } func checkRedirectURIs(compliance *Compliance, grantTypes []OIDCGrantType, appType OIDCApplicationType, redirectUris []string) { - if len(redirectUris) == 0 { + // See #5684 for OIDCGrantTypeDeviceCode and redirectUris further explanation + if len(redirectUris) == 0 && (!containsOIDCGrantType(grantTypes, OIDCGrantTypeDeviceCode) || (containsOIDCGrantType(grantTypes, OIDCGrantTypeDeviceCode) && containsOIDCGrantType(grantTypes, OIDCGrantTypeAuthorizationCode))) { compliance.NoneCompliant = true compliance.Problems = append([]string{"Application.OIDC.V1.NoRedirectUris"}, compliance.Problems...) } diff --git a/internal/domain/application_oidc_test.go b/internal/domain/application_oidc_test.go index da6c454867..b3d9488827 100644 --- a/internal/domain/application_oidc_test.go +++ b/internal/domain/application_oidc_test.go @@ -236,6 +236,11 @@ func Test_checkGrantTypesCombination(t *testing.T) { }, grantTypes: []OIDCGrantType{OIDCGrantTypeImplicit, OIDCGrantTypeRefreshToken}, }, + { + name: "device code flow and refresh token doesnt require OIDCGrantTypeImplicit", + want: &Compliance{}, + grantTypes: []OIDCGrantType{OIDCGrantTypeDeviceCode, OIDCGrantTypeRefreshToken}, + }, { name: "refresh token and authorization code", want: &Compliance{},