From 6672cdb5d3e76a621dc6f9407855f19124b184d6 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 25 Aug 2023 10:50:29 -0400 Subject: [PATCH 1/8] Implement nextUrl for OIDC Authentication Signed-off-by: Craig Perkins --- common/index.ts | 3 +- public/apps/login/login-page.tsx | 6 +- server/auth/types/openid/routes.ts | 134 +++++++++++++++++++++++++++-- 3 files changed, 135 insertions(+), 8 deletions(-) diff --git a/common/index.ts b/common/index.ts index c688731d6..9b038a581 100644 --- a/common/index.ts +++ b/common/index.ts @@ -30,9 +30,10 @@ export const CUSTOM_ERROR_PAGE_URI = '/app/' + APP_ID_CUSTOMERROR; export const API_AUTH_LOGIN = '/auth/login'; export const API_AUTH_LOGOUT = '/auth/logout'; export const OPENID_AUTH_LOGIN = '/auth/openid/login'; +export const OPENID_AUTH_LOGIN_WITH_FRAGMENT = '/auth/openid/captureUrlFragment'; export const SAML_AUTH_LOGIN = '/auth/saml/login'; -export const ANONYMOUS_AUTH_LOGIN = '/auth/anonymous'; export const SAML_AUTH_LOGIN_WITH_FRAGMENT = '/auth/saml/captureUrlFragment'; +export const ANONYMOUS_AUTH_LOGIN = '/auth/anonymous'; export const OPENID_AUTH_LOGOUT = '/auth/openid/logout'; export const SAML_AUTH_LOGOUT = '/auth/saml/logout'; diff --git a/public/apps/login/login-page.tsx b/public/apps/login/login-page.tsx index 82019cba7..e935a507a 100644 --- a/public/apps/login/login-page.tsx +++ b/public/apps/login/login-page.tsx @@ -33,7 +33,7 @@ import { validateCurrentPassword } from '../../utils/login-utils'; import { ANONYMOUS_AUTH_LOGIN, AuthType, - OPENID_AUTH_LOGIN, + OPENID_AUTH_LOGIN_WITH_FRAGMENT, SAML_AUTH_LOGIN_WITH_FRAGMENT, } from '../../../common'; @@ -228,7 +228,9 @@ export function LoginPage(props: LoginPageDeps) { } case AuthType.OPEN_ID: { const oidcConfig = props.config.ui[AuthType.OPEN_ID].login; - formBodyOp.push(renderLoginButton(AuthType.OPEN_ID, OPENID_AUTH_LOGIN, oidcConfig)); + const nextUrl = extractNextUrlFromWindowLocation(); + const oidcAuthLoginUrl = OPENID_AUTH_LOGIN_WITH_FRAGMENT + nextUrl; + formBodyOp.push(renderLoginButton(AuthType.OPEN_ID, oidcAuthLoginUrl, oidcConfig)); break; } case AuthType.SAML: { diff --git a/server/auth/types/openid/routes.ts b/server/auth/types/openid/routes.ts index b598dd1a8..c26d09d96 100644 --- a/server/auth/types/openid/routes.ts +++ b/server/auth/types/openid/routes.ts @@ -99,6 +99,7 @@ export class OpenIdAuthRoutes { validate: validateNextUrl, }) ), + redirectHash: schema.maybe(schema.string()), state: schema.maybe(schema.string()), refresh: schema.maybe(schema.string()), }, @@ -133,6 +134,7 @@ export class OpenIdAuthRoutes { oidc: { state: nonce, nextUrl: getNextUrl(this.config, this.core, request), + redirectHash: request.query.redirectHash === 'true', }, authType: AuthType.OPEN_ID, }; @@ -162,6 +164,7 @@ export class OpenIdAuthRoutes { const nextUrl: string = cookie.oidc.nextUrl; const clientId = this.config.openid?.client_id; const clientSecret = this.config.openid?.client_secret; + const redirectHash: boolean = cookie.oidc?.redirectHash || false; const query: any = { grant_type: AUTH_GRANT_TYPE, code: request.query.code, @@ -209,11 +212,21 @@ export class OpenIdAuthRoutes { ); this.sessionStorageFactory.asScoped(request).set(sessionStorage); - return response.redirected({ - headers: { - location: nextUrl, - }, - }); + if (redirectHash) { + return response.redirected({ + headers: { + location: `${ + this.core.http.basePath.serverBasePath + }/auth/openid/redirectUrlFragment?nextUrl=${escape(nextUrl)}`, + }, + }); + } else { + return response.redirected({ + headers: { + location: nextUrl, + }, + }); + } } catch (error: any) { context.security_plugin.logger.error(`OpenId authentication failed: ${error}`); if (error.toString().toLowerCase().includes('authentication exception')) { @@ -269,5 +282,116 @@ export class OpenIdAuthRoutes { }); } ); + + // captureUrlFragment is the first route that will be invoked in the SP initiated login. + // This route will execute the captureUrlFragment.js script. + this.core.http.resources.register( + { + path: '/auth/openid/captureUrlFragment', + validate: { + query: schema.object({ + nextUrl: schema.maybe( + schema.string({ + validate: validateNextUrl, + }) + ), + }), + }, + options: { + authRequired: false, + }, + }, + async (context, request, response) => { + this.sessionStorageFactory.asScoped(request).clear(); + const serverBasePath = this.core.http.basePath.serverBasePath; + return response.renderHtml({ + body: ` + + OSD OIDC Capture + + + `, + }); + } + ); + + // This script will store the URL Hash in browser's local storage. + this.core.http.resources.register( + { + path: '/auth/openid/captureUrlFragment.js', + validate: false, + options: { + authRequired: false, + }, + }, + async (context, request, response) => { + this.sessionStorageFactory.asScoped(request).clear(); + return response.renderJs({ + body: `let oidcHash=window.location.hash.toString(); + let redirectHash = false; + if (oidcHash !== "") { + window.localStorage.removeItem('oidcHash'); + window.localStorage.setItem('oidcHash', oidcHash); + redirectHash = true; + } + let params = new URLSearchParams(window.location.search); + let nextUrl = params.get("nextUrl"); + finalUrl = "login?nextUrl=" + encodeURIComponent(nextUrl); + finalUrl += "&redirectHash=" + encodeURIComponent(redirectHash); + window.location.replace(finalUrl); + `, + }); + } + ); + + // Once the User is authenticated the browser will be redirected to '/auth/openid/redirectUrlFragment' + // route, which will execute the redirectUrlFragment.js. + this.core.http.resources.register( + { + path: '/auth/openid/redirectUrlFragment', + validate: { + query: schema.object({ + nextUrl: schema.any(), + }), + }, + options: { + authRequired: true, + }, + }, + async (context, request, response) => { + const serverBasePath = this.core.http.basePath.serverBasePath; + return response.renderHtml({ + body: ` + + OSD OpenID Success + + + `, + }); + } + ); + + // This script will pop the Hash from local storage if it exists. + // And forward the browser to the next url. + this.core.http.resources.register( + { + path: '/auth/openid/redirectUrlFragment.js', + validate: false, + options: { + authRequired: true, + }, + }, + async (context, request, response) => { + return response.renderJs({ + body: `let oidcHash=window.localStorage.getItem('oidcHash'); + window.localStorage.removeItem('oidcHash'); + let params = new URLSearchParams(window.location.search); + let nextUrl = params.get("nextUrl"); + finalUrl = nextUrl + oidcHash; + window.location.replace(finalUrl); + `, + }); + } + ); } } From b877019af9b9d8548455fcac35a6386cff4674a8 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 25 Aug 2023 12:04:56 -0400 Subject: [PATCH 2/8] Make sure hash is carried over when OIDC is only auth type for ODS Signed-off-by: Craig Perkins --- server/auth/types/openid/openid_auth.ts | 35 ++++++++++++++++--------- server/auth/types/openid/routes.ts | 4 ++- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/server/auth/types/openid/openid_auth.ts b/server/auth/types/openid/openid_auth.ts index accabb7c1..5192e9634 100644 --- a/server/auth/types/openid/openid_auth.ts +++ b/server/auth/types/openid/openid_auth.ts @@ -25,13 +25,17 @@ import { LifecycleResponseFactory, AuthToolkit, IOpenSearchDashboardsResponse, + AuthResult, } from 'opensearch-dashboards/server'; import HTTP from 'http'; import HTTPS from 'https'; import { PeerCertificate } from 'tls'; import { Server, ServerStateCookieOptions } from '@hapi/hapi'; import { SecurityPluginConfigType } from '../../..'; -import { SecuritySessionCookie } from '../../../session/security_cookie'; +import { + SecuritySessionCookie, + clearOldVersionCookieValue, +} from '../../../session/security_cookie'; import { OpenIdAuthRoutes } from './routes'; import { AuthenticationType } from '../authentication_type'; import { callTokenEndpoint } from './helper'; @@ -118,6 +122,22 @@ export class OpenIdAuthentication extends AuthenticationType { } } + private generateNextUrl(request: OpenSearchDashboardsRequest): string { + const path = + this.coreSetup.http.basePath.serverBasePath + + (request.url.pathname || '/app/opensearch-dashboards'); + return escape(path); + } + + private redirectOIDCCapture = (request: OpenSearchDashboardsRequest, toolkit: AuthToolkit) => { + const nextUrl = this.generateNextUrl(request); + const clearOldVersionCookie = clearOldVersionCookieValue(this.config); + return toolkit.redirected({ + location: `${this.coreSetup.http.basePath.serverBasePath}/auth/openid/captureUrlFragment?nextUrl=${nextUrl}`, + 'set-cookie': clearOldVersionCookie, + }); + }; + private createWreckClient(): typeof wreck { const wreckHttpsOption: WreckHttpsOptions = {}; if (this.config.openid?.root_ca) { @@ -266,18 +286,9 @@ export class OpenIdAuthentication extends AuthenticationType { request: OpenSearchDashboardsRequest, response: LifecycleResponseFactory, toolkit: AuthToolkit - ): IOpenSearchDashboardsResponse { + ): IOpenSearchDashboardsResponse | AuthResult { if (this.isPageRequest(request)) { - // nextUrl is a key value pair - const nextUrl = composeNextUrlQueryParam( - request, - this.coreSetup.http.basePath.serverBasePath - ); - return response.redirected({ - headers: { - location: `${this.coreSetup.http.basePath.serverBasePath}${OPENID_AUTH_LOGIN}?${nextUrl}`, - }, - }); + return this.redirectOIDCCapture(request, toolkit); } else { return response.unauthorized(); } diff --git a/server/auth/types/openid/routes.ts b/server/auth/types/openid/routes.ts index c26d09d96..5eca74665 100644 --- a/server/auth/types/openid/routes.ts +++ b/server/auth/types/openid/routes.ts @@ -24,7 +24,9 @@ import { OpenSearchDashboardsRequest, Logger, } from '../../../../../../src/core/server'; -import { SecuritySessionCookie } from '../../../session/security_cookie'; +import { + SecuritySessionCookie, +} from '../../../session/security_cookie'; import { SecurityPluginConfigType } from '../../..'; import { OpenIdAuthConfig } from './openid_auth'; import { SecurityClient } from '../../../backend/opensearch_security_client'; From 5b4aa035326895a74dc404cdd51a1f0952a94463 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 25 Aug 2023 12:45:55 -0400 Subject: [PATCH 3/8] Run yarn lint fix Signed-off-by: Craig Perkins --- server/auth/types/openid/routes.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/auth/types/openid/routes.ts b/server/auth/types/openid/routes.ts index 5eca74665..c26d09d96 100644 --- a/server/auth/types/openid/routes.ts +++ b/server/auth/types/openid/routes.ts @@ -24,9 +24,7 @@ import { OpenSearchDashboardsRequest, Logger, } from '../../../../../../src/core/server'; -import { - SecuritySessionCookie, -} from '../../../session/security_cookie'; +import { SecuritySessionCookie } from '../../../session/security_cookie'; import { SecurityPluginConfigType } from '../../..'; import { OpenIdAuthConfig } from './openid_auth'; import { SecurityClient } from '../../../backend/opensearch_security_client'; From a2b2bb3b60c47421454e80679285e58c0fb3bd46 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Fri, 25 Aug 2023 13:31:01 -0400 Subject: [PATCH 4/8] Update login-page snapshot Signed-off-by: Craig Perkins --- public/apps/login/test/__snapshots__/login-page.test.tsx.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/apps/login/test/__snapshots__/login-page.test.tsx.snap b/public/apps/login/test/__snapshots__/login-page.test.tsx.snap index a73477edc..d5e32bf27 100644 --- a/public/apps/login/test/__snapshots__/login-page.test.tsx.snap +++ b/public/apps/login/test/__snapshots__/login-page.test.tsx.snap @@ -121,7 +121,7 @@ exports[`Login page renders renders with config value for multiauth 1`] = ` aria-label="openid_login_button" className="test-btn-style" data-test-subj="submit" - href="/app/opensearch-dashboards/auth/openid/login" + href="/app/opensearch-dashboards/auth/openid/captureUrlFragment?nextUrl=%2F" iconType="http://localhost:5601/images/test.png" size="s" type="prime" From 12535e944fef40df7d9816841f155b1d8c17f61b Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 30 Nov 2023 13:19:09 -0500 Subject: [PATCH 5/8] Verify OIDC tests Signed-off-by: Craig Perkins --- .github/workflows/cypress-test-oidc-e2e.yml | 1 - server/auth/types/openid/routes.ts | 2 +- test/cypress/e2e/oidc/oidc_auth_test.spec.js | 85 +++++++++----------- 3 files changed, 40 insertions(+), 48 deletions(-) diff --git a/.github/workflows/cypress-test-oidc-e2e.yml b/.github/workflows/cypress-test-oidc-e2e.yml index c673018b7..e33f529c2 100644 --- a/.github/workflows/cypress-test-oidc-e2e.yml +++ b/.github/workflows/cypress-test-oidc-e2e.yml @@ -60,7 +60,6 @@ jobs: else echo "Checksum match confirmed. Proceeding with setup." fi - chmod +x ./kc.sh # Setup and Run Keycloak - name: Get and run Keycloak on Linux diff --git a/server/auth/types/openid/routes.ts b/server/auth/types/openid/routes.ts index b148a2baa..3c2056e4d 100644 --- a/server/auth/types/openid/routes.ts +++ b/server/auth/types/openid/routes.ts @@ -380,7 +380,7 @@ export class OpenIdAuthRoutes { path: '/auth/openid/redirectUrlFragment.js', validate: false, options: { - authRequired: true, + authRequired: false, }, }, async (context, request, response) => { diff --git a/test/cypress/e2e/oidc/oidc_auth_test.spec.js b/test/cypress/e2e/oidc/oidc_auth_test.spec.js index b4c5c80d2..fa5457e18 100644 --- a/test/cypress/e2e/oidc/oidc_auth_test.spec.js +++ b/test/cypress/e2e/oidc/oidc_auth_test.spec.js @@ -18,22 +18,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -const login = 'admin'; -const password = 'admin'; - describe('Log in via OIDC', () => { afterEach(() => { - cy.origin('http://localhost:5601', () => { - cy.clearCookies(); - cy.clearLocalStorage(); - }); + cy.clearCookies(); + cy.clearLocalStorage(); }); const kcLogin = () => { - cy.get('#kc-page-title').should('be.visible'); - cy.get('input[id=username]').should('be.visible').type(login); - cy.get('input[id=password]').should('be.visible').type(password); - cy.get('#kc-login').click(); + cy.origin('http://127.0.0.1:8080', () => { + const login = 'admin'; + const password = 'admin'; + + cy.get('#kc-page-title').should('be.visible'); + cy.get('input[id=username]').should('be.visible').type(login); + cy.get('input[id=password]').should('be.visible').type(password); + cy.get('#kc-login').click(); + }); }; it('Login to app/opensearch_dashboards_overview#/ when OIDC is enabled', () => { @@ -43,14 +43,12 @@ describe('Log in via OIDC', () => { kcLogin(); - cy.origin('http://localhost:5601', () => { - localStorage.setItem('opendistro::security::tenant::saved', '""'); - localStorage.setItem('home:newThemeModal:show', 'false'); + localStorage.setItem('opendistro::security::tenant::saved', '""'); + localStorage.setItem('home:newThemeModal:show', 'false'); - cy.get('#osdOverviewPageHeader__title').should('be.visible'); + cy.get('#osdOverviewPageHeader__title').should('be.visible'); - cy.getCookie('security_authentication').should('exist'); - }); + cy.getCookie('security_authentication').should('exist'); }); it('Login to app/dev_tools#/console when OIDC is enabled', () => { @@ -60,33 +58,32 @@ describe('Log in via OIDC', () => { kcLogin(); - cy.origin('http://localhost:5601', () => { - localStorage.setItem('opendistro::security::tenant::saved', '""'); - localStorage.setItem('home:newThemeModal:show', 'false'); + localStorage.setItem('opendistro::security::tenant::saved', '""'); + localStorage.setItem('home:newThemeModal:show', 'false'); - cy.visit('http://localhost:5601/app/dev_tools#/console'); + cy.visit('http://localhost:5601/app/dev_tools#/console'); - cy.get('a').contains('Dev Tools').should('be.visible'); + cy.get('a').contains('Dev Tools').should('be.visible'); - cy.getCookie('security_authentication').should('exist'); - }); + cy.getCookie('security_authentication').should('exist'); }); it('Login to Dashboard with Hash', () => { cy.visit( - `http://localhost:5601/app/dashboards#/view/7adfa750-4c81-11e8-b3d7-01146121b73d?_g=(filters:!(),refreshInterval:(pause:!f,value:900000),time:(from:now-24h,to:now))&_a=(description:'Analyze%20mock%20flight%20data%20for%20OpenSearch-Air,%20Logstash%20Airways,%20OpenSearch%20Dashboards%20Airlines%20and%20BeatsWest',filters:!(),fullScreenMode:!f,options:(hidePanelTitles:!f,useMargins:!t),query:(language:kuery,query:''),timeRestore:!t,title:'%5BFlights%5D%20Global%20Flight%20Dashboard',viewMode:view)` + `http://localhost:5601/app/dashboards#/view/7adfa750-4c81-11e8-b3d7-01146121b73d?_g=(filters:!(),refreshInterval:(pause:!f,value:900000),time:(from:now-24h,to:now))&_a=(description:'Analyze%20mock%20flight%20data%20for%20OpenSearch-Air,%20Logstash%20Airways,%20OpenSearch%20Dashboards%20Airlines%20and%20BeatsWest',filters:!(),fullScreenMode:!f,options:(hidePanelTitles:!f,useMargins:!t),query:(language:kuery,query:''),timeRestore:!t,title:'%5BFlights%5D%20Global%20Flight%20Dashboard',viewMode:view)`, + { + failOnStatusCode: false, + } ); kcLogin(); - cy.origin('http://localhost:5601', () => { - localStorage.setItem('opendistro::security::tenant::saved', '""'); - localStorage.setItem('home:newThemeModal:show', 'false'); + localStorage.setItem('opendistro::security::tenant::saved', '""'); + localStorage.setItem('home:newThemeModal:show', 'false'); - cy.get('.euiHeader.euiHeader--default.euiHeader--fixed.primaryHeader').should('be.visible'); + cy.get('.euiHeader.euiHeader--default.euiHeader--fixed.primaryHeader').should('be.visible'); - cy.getCookie('security_authentication').should('exist'); - }); + cy.getCookie('security_authentication').should('exist'); }); it('Tenancy persisted after logout in OIDC', () => { @@ -96,30 +93,26 @@ describe('Log in via OIDC', () => { kcLogin(); - cy.origin('http://localhost:5601', () => { - localStorage.setItem('home:newThemeModal:show', 'false'); + localStorage.setItem('home:newThemeModal:show', 'false'); - cy.get('#private').should('be.enabled'); - cy.get('#private').click({ force: true }); + cy.get('#private').should('be.enabled'); + cy.get('#private').click({ force: true }); - cy.get('button[data-test-subj="confirm"]').click(); + cy.get('button[data-test-subj="confirm"]').click(); - cy.get('#osdOverviewPageHeader__title').should('be.visible'); + cy.get('#osdOverviewPageHeader__title').should('be.visible'); - cy.get('button[id="user-icon-btn"]').click(); + cy.get('button[id="user-icon-btn"]').click(); - cy.get('button[data-test-subj^="log-out-"]').click(); - }); + cy.get('button[data-test-subj^="log-out-"]').click(); kcLogin(); - cy.origin('http://localhost:5601', () => { - cy.get('#user-icon-btn').should('be.visible'); - cy.get('#user-icon-btn').click(); + cy.get('#user-icon-btn').should('be.visible'); + cy.get('#user-icon-btn').click(); - cy.get('#osdOverviewPageHeader__title').should('be.visible'); + cy.get('#osdOverviewPageHeader__title').should('be.visible'); - cy.get('#tenantName').should('have.text', 'Private'); - }); + cy.get('#tenantName').should('have.text', 'Private'); }); }); From 581f2c408a7888859b6ef9ae7144967c90696b2a Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 30 Nov 2023 14:20:19 -0500 Subject: [PATCH 6/8] Set to true Signed-off-by: Craig Perkins --- server/auth/types/openid/routes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/auth/types/openid/routes.ts b/server/auth/types/openid/routes.ts index 3c2056e4d..b148a2baa 100644 --- a/server/auth/types/openid/routes.ts +++ b/server/auth/types/openid/routes.ts @@ -380,7 +380,7 @@ export class OpenIdAuthRoutes { path: '/auth/openid/redirectUrlFragment.js', validate: false, options: { - authRequired: false, + authRequired: true, }, }, async (context, request, response) => { From 9a5b152d6b8c7238b3bc1ce4d6ab6545fdf11a11 Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Thu, 30 Nov 2023 16:58:05 -0500 Subject: [PATCH 7/8] Update test Signed-off-by: Craig Perkins --- test/cypress/e2e/oidc/oidc_auth_test.spec.js | 29 ++++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/test/cypress/e2e/oidc/oidc_auth_test.spec.js b/test/cypress/e2e/oidc/oidc_auth_test.spec.js index fa5457e18..08a7e8ae1 100644 --- a/test/cypress/e2e/oidc/oidc_auth_test.spec.js +++ b/test/cypress/e2e/oidc/oidc_auth_test.spec.js @@ -69,21 +69,26 @@ describe('Log in via OIDC', () => { }); it('Login to Dashboard with Hash', () => { - cy.visit( - `http://localhost:5601/app/dashboards#/view/7adfa750-4c81-11e8-b3d7-01146121b73d?_g=(filters:!(),refreshInterval:(pause:!f,value:900000),time:(from:now-24h,to:now))&_a=(description:'Analyze%20mock%20flight%20data%20for%20OpenSearch-Air,%20Logstash%20Airways,%20OpenSearch%20Dashboards%20Airlines%20and%20BeatsWest',filters:!(),fullScreenMode:!f,options:(hidePanelTitles:!f,useMargins:!t),query:(language:kuery,query:''),timeRestore:!t,title:'%5BFlights%5D%20Global%20Flight%20Dashboard',viewMode:view)`, - { - failOnStatusCode: false, - } - ); + const urlWithHash = `http://localhost:5601/app/security-dashboards-plugin#/getstarted`; + + cy.visit(urlWithHash, { + failOnStatusCode: false, + }); kcLogin(); + cy.getCookie('security_authentication').should('exist'); + cy.getCookie('security_authentication_oidc1').should('exist'); + + cy.url().then((url) => { + cy.visit(url, { + failOnStatusCode: false, + }); + }); localStorage.setItem('opendistro::security::tenant::saved', '""'); localStorage.setItem('home:newThemeModal:show', 'false'); - cy.get('.euiHeader.euiHeader--default.euiHeader--fixed.primaryHeader').should('be.visible'); - - cy.getCookie('security_authentication').should('exist'); + cy.get('h1.euiTitle--large').contains('Get started'); }); it('Tenancy persisted after logout in OIDC', () => { @@ -93,6 +98,12 @@ describe('Log in via OIDC', () => { kcLogin(); + cy.url().then((url) => { + cy.visit(url, { + failOnStatusCode: false, + }); + }); + localStorage.setItem('home:newThemeModal:show', 'false'); cy.get('#private').should('be.enabled'); From 01a62481a5fb5ee93b3b8bbe539fcc06a8e4fbbd Mon Sep 17 00:00:00 2001 From: Craig Perkins Date: Tue, 5 Dec 2023 14:19:25 -0500 Subject: [PATCH 8/8] Address review comments Signed-off-by: Craig Perkins --- .github/workflows/cypress-test-oidc-e2e.yml | 2 +- server/auth/types/openid/routes.ts | 2 +- server/session/security_cookie.ts | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cypress-test-oidc-e2e.yml b/.github/workflows/cypress-test-oidc-e2e.yml index e33f529c2..6ef90f4fd 100644 --- a/.github/workflows/cypress-test-oidc-e2e.yml +++ b/.github/workflows/cypress-test-oidc-e2e.yml @@ -48,7 +48,6 @@ jobs: echo "Unpacking Keycloak" tar -xzf keycloak-${{ env.KEYCLOAK_VERSION }}.tar.gz cd keycloak-${{ env.KEYCLOAK_VERSION }}/bin - chmod +x ./kc.sh echo "Generating checksum for the downloaded kc.sh script..." DOWNLOADED_CHECKSUM=$(sha256sum kc.sh | awk '{print $1}') echo "Downloaded kc.sh checksum: $DOWNLOADED_CHECKSUM" @@ -60,6 +59,7 @@ jobs: else echo "Checksum match confirmed. Proceeding with setup." fi + chmod +x ./kc.sh # Setup and Run Keycloak - name: Get and run Keycloak on Linux diff --git a/server/auth/types/openid/routes.ts b/server/auth/types/openid/routes.ts index b148a2baa..a9b84e75c 100644 --- a/server/auth/types/openid/routes.ts +++ b/server/auth/types/openid/routes.ts @@ -100,7 +100,7 @@ export class OpenIdAuthRoutes { validate: validateNextUrl, }) ), - redirectHash: schema.maybe(schema.string()), + redirectHash: schema.maybe(schema.boolean()), state: schema.maybe(schema.string()), refresh: schema.maybe(schema.string()), }, diff --git a/server/session/security_cookie.ts b/server/session/security_cookie.ts index 50b880d9b..c0365e7e1 100644 --- a/server/session/security_cookie.ts +++ b/server/session/security_cookie.ts @@ -30,7 +30,11 @@ export interface SecuritySessionCookie { tenant?: any; // for oidc auth workflow - oidc?: any; + oidc?: { + state?: string; + nextUrl?: string; + redirectHash?: boolean; + }; // for Saml auth workflow saml?: {