diff --git a/client-frameworks-support/testing-utilities/README.md b/client-frameworks-support/testing-utilities/README.md index 2aaf3ed803..788434a161 100644 --- a/client-frameworks-support/testing-utilities/README.md +++ b/client-frameworks-support/testing-utilities/README.md @@ -79,20 +79,19 @@ describe('Another test using cypress', () => { cy.get('.pathExists').click().then(() => { luigiMockUtil.mockPathExists('/test', false); }); - cy.getAllSessionStorage().then((result: any) => { - expect(result).to.deep.equal({ - "http://localhost:4200": { - luigiMockData: '{"pathExists":{"/test":false}}' - }, - }); - }) + cy.getAllSessionStorage().then((storage: any) => { + const result = luigiMockUtil.getCleanSessionStorageData(storage); + + expect(result).to.contains(luigiMockUtil.getMockedPathExistsOutput('/test', false)); + }); }); it('should mock context update', () => { + const visualizationContainerId = luigiMockUtil.getVisualizationContainerId(); const context = {ctxKey: 'ctxValue'}; luigiMockUtil.mockContext(context); - cy.get('#luigi-debug-vis-cnt').contains('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}'); + cy.get('#' + visualizationContainerId).contains(luigiMockUtil.getMockedContextOutput(context)); }); }); ``` @@ -113,22 +112,25 @@ describe('Another test using nightwatch', function () { await browser.expect.element('.pathExists').to.be.present; await browser.element('.pathExists').click().then(() => { luigiMockUtil.mockPathExists('/test', false); - browser.execute(() => window.sessionStorage.getItem('luigiMockData'), [], function (result) { - expect(result.value).to.contains('{"pathExists":{"/test":false}}'); + browser.execute(() => window.sessionStorage, [], function (storage) { + const result = luigiMockUtil.getCleanSessionStorageData(storage.value); + + expect(result).to.contains(luigiMockUtil.getMockedPathExistsOutput('/test', false)); }); }); }); it('should mock context update', async () => { + const visualizationContainerId = luigiMockUtil.getVisualizationContainerId(); const context = {ctxKey: 'ctxValue'}; await luigiMockUtil.mockContext(context); - // Wait until '#luigi-debug-vis-cnt' element is present - await browser.waitForElementPresent('#luigi-debug-vis-cnt', undefined, undefined, false, () => { - const wrapper = browser.expect.element('#luigi-debug-vis-cnt'); + // Wait until Luigi visualization container is present + await browser.waitForElementPresent('#' + visualizationContainerId, undefined, undefined, false, () => { + const wrapper = browser.expect.element('#' + visualizationContainerId); wrapper.to.be.present; - wrapper.text.to.contains('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}'); + wrapper.text.to.contains(luigiMockUtil.getMockedContextOutput(context)); }); }); @@ -158,21 +160,23 @@ describe('Another test using webdriverio', () => { // Wait until session storage item is set await browser.setTimeout(defaultTimeout); - const result = await browser.execute(() => window.sessionStorage.getItem('luigiMockData')); + const storage = await browser.execute(() => window.sessionStorage); + const result = await luigiMockUtil.getCleanSessionStorageData(storage); - await expect(result).toEqual('{"pathExists":{"/test":false}}'); + await expect(result).toContain(luigiMockUtil.getMockedPathExistsOutput('/test', false)); }); it('should mock context update', async () => { luigiMockUtil = new LuigiMockUtil(browser); + const visualizationContainerId = luigiMockUtil.getVisualizationContainerId(); const context = {ctxKey: 'ctxValue'}; await browser.url(baseUrl); await luigiMockUtil.mockContext(context); - // Wait until '#luigi-debug-vis-cnt' element is present + // Wait until Luigi visualization container is present await browser.setTimeout(defaultTimeout); - await expect($('#luigi-debug-vis-cnt')).toHaveHTML(expect.stringContaining('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}')); + await expect($('#' + visualizationContainerId)).toHaveHTML(expect.stringContaining(luigiMockUtil.getMockedContextOutput(context))); }); }); ``` @@ -221,25 +225,27 @@ describe('Another test using puppeteer ->', () => { // Wait until session storage item is set await new Promise(resolve => setTimeout(resolve, 500)); - const result = await page.evaluate(() => window.sessionStorage.getItem('luigiMockData')); + const storage = await page.evaluate(() => JSON.stringify(window.sessionStorage)); + const result = await luigiMockUtil.getCleanSessionStorageData(storage); - await expect(result).toContain('{"pathExists":{"/test":false}}'); + await expect(result).toContain(luigiMockUtil.getMockedPathExistsOutput('/test', false)); }); }); }); it('should mock context update', async () => { + const visualizationContainerId = luigiMockUtil.getVisualizationContainerId(); const context = {ctxKey: 'ctxValue'}; await luigiMockUtil.mockContext(context); - // Wait until '#luigi-debug-vis-cnt' element is present - await page.waitForSelector('#luigi-debug-vis-cnt').then(async () => { + // Wait until Luigi visualization container is present + await page.waitForSelector('#' + visualizationContainerId).then(async () => { const result = await page - .locator('#luigi-debug-vis-cnt div:nth-child(1)') + .locator(`#${visualizationContainerId} div:nth-child(1)`) .map(div => div.innerText) .wait(); - expect(result).toContain('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}'); + expect(result).toContain(luigiMockUtil.getMockedContextOutput(context)); }); }); }); @@ -247,7 +253,11 @@ describe('Another test using puppeteer ->', () => { #### Functions provided - **mockContext**: Mocks the context by sending Luigi context messages with the desired mocked context as parameter. -- **mockPathExists**: This method serves as a mock for the Luigi Client `pathExists()` function. It is used in e2e tests when component being tested utilizes a call to `LuigiClient.linkManager().pathExists()` +- **mockPathExists**: This method serves as a mock for the Luigi Client `pathExists()` function. It is used in e2e tests when component being tested utilizes a call to `LuigiClient.linkManager().pathExists()`. - **modalOpenedWithTitle**: Checks on the printed DOM Luigi message responses for a modal with given title being opened. In such a case, a message would be printed containing a `modal.title`. Returns `false` if such element was not found. -- **getMSG**: Return list of messages, representing message elements added in the DOM for testing. -- **parseLuigiMockedMessages**: Parses the elements added by LuigiMockModule into the DOM and assigns them to the local messages variable \ No newline at end of file +- **getMockedContextOutput**: Returns output of 'mockContext' method with given data. +- **getMockedPathExistsOutput**: Returns output of 'mockPathExists' method with given arguments. +- **getCleanSessionStorageData**: Returns parsed session storage data used for testing. +- **getVisualizationContainerId**: Returns ID of Luigi visualization container added in the DOM for testing. +- **getMSG**: Returns list of messages, representing message elements added in the DOM for testing. +- **parseLuigiMockedMessages**: Parses the elements added by LuigiMockModule into the DOM and assigns them to the local messages variable. \ No newline at end of file diff --git a/client-frameworks-support/testing-utilities/src/luigi-mock-engine.ts b/client-frameworks-support/testing-utilities/src/luigi-mock-engine.ts index 01f3019b8b..b414ea4848 100644 --- a/client-frameworks-support/testing-utilities/src/luigi-mock-engine.ts +++ b/client-frameworks-support/testing-utilities/src/luigi-mock-engine.ts @@ -147,17 +147,20 @@ export class LuigiMockEngine { * which holds data that is useful for e2e testing. */ public static visualize(data: string): void { - let luigiVisualizationContainer: Element | null = document.querySelector('#luigi-debug-vis-cnt'); + const visualizationContainerId = 'luigi-debug-vis-cnt'; + const dataWrapper: HTMLDivElement = document.createElement('div'); + let luigiVisualizationContainer: Element | null = document.querySelector('#' + visualizationContainerId); + // Construct element structure if not already constructed if (!luigiVisualizationContainer) { luigiVisualizationContainer = document.createElement('div'); - luigiVisualizationContainer.setAttribute('id', 'luigi-debug-vis-cnt'); + luigiVisualizationContainer.setAttribute('id', visualizationContainerId); // Hide the added DOM element to avoid interferring/overlapping with other elements during testing. luigiVisualizationContainer.setAttribute('style', 'display:none'); document.body.appendChild(luigiVisualizationContainer); } - const line: HTMLDivElement = document.createElement('div'); - line.textContent = data; - luigiVisualizationContainer.appendChild(line); + + dataWrapper.textContent = data; + luigiVisualizationContainer.appendChild(dataWrapper); } } diff --git a/client-frameworks-support/testing-utilities/src/luigi-mock-util.ts b/client-frameworks-support/testing-utilities/src/luigi-mock-util.ts index b52af70cb7..a9535c73b6 100644 --- a/client-frameworks-support/testing-utilities/src/luigi-mock-util.ts +++ b/client-frameworks-support/testing-utilities/src/luigi-mock-util.ts @@ -1,4 +1,6 @@ export class LuigiMockUtil { + private sessionStorageItemName = 'luigiMockData'; + private visualizationContainerId = 'luigi-debug-vis-cnt'; private messages: any[]; private browser: any; private win: any; @@ -9,14 +11,6 @@ export class LuigiMockUtil { this.win = win; } - /** - * Returns the global window object. - * @returns the glboal win object - */ - private getGlobalThis(): any { - return this.win || globalThis; - } - /** * Parses the elements added by LuigiMockModule into the DOM and assigns them to the local this.messages variable * @returns {Promise} - A Promise that resolves when parsing is complete. @@ -24,7 +18,7 @@ export class LuigiMockUtil { async parseLuigiMockedMessages(): Promise { const window = this.getGlobalThis(); const getTextNodeValues = (): any[] => { - const debugCtn = window.getElementById('luigi-debug-vis-cnt'); + const debugCtn = window.getElementById(this.visualizationContainerId); return Array.from(debugCtn?.childNodes || []).map((item: any) => item.textContent || ''); }; @@ -64,7 +58,7 @@ export class LuigiMockUtil { * Mocks the context by sending luigi context messages with the desired mocked context as parameter. * @param mockContext an object representing the context to be mocked */ - mockContext = (mockContext: Record): void => { + mockContext(mockContext: Record): void { const window = this.getGlobalThis(); const postMessageToLuigi = (context: Record): Record => { window.postMessage({ msg: 'luigi.get-context', context }, '*'); @@ -90,7 +84,7 @@ export class LuigiMockUtil { } catch (error) { console.debug('Failed to mock context: ', error); } - }; + } /** * This method serves as a mock for the luigi client pathExists() function. @@ -108,7 +102,7 @@ export class LuigiMockUtil { * await mockPathExists('pathToCheck', false); * */ - mockPathExists = (path: string, exists: boolean): void => { + mockPathExists(path: string, exists: boolean): void { const window = this.getGlobalThis(); const mockContext: Record = { path, exists }; /** @@ -126,7 +120,7 @@ export class LuigiMockUtil { } }; - window.sessionStorage.setItem('luigiMockData', JSON.stringify(pathExistsMockData)); + window.sessionStorage.setItem(this.sessionStorageItemName, JSON.stringify(pathExistsMockData)); return { ...pathExistsMockData, sessionItem: 'isStored' }; }; @@ -149,7 +143,7 @@ export class LuigiMockUtil { } catch (error) { console.debug('Failed to mock path exists: ', error); } - }; + } /** * Checks on the printed DOM Luigi message responses for a modal with given title @@ -207,9 +201,61 @@ export class LuigiMockUtil { } /** - * Return list of messages, representing message elements added in the DOM for testing. + * Returns output of 'mockContext' method with given data. + * @param {Object} context - Object representing the context to be mocked. + * @returns {string} - Stringified output of 'mockContext' method. + */ + getMockedContextOutput(context: Record): string { + return `{"msg":"luigi.get-context","context":${JSON.stringify(context)}}`; + } + + /** + * Returns output of 'mockPathExists' method with given arguments. + * @param {string} path - The path for which mock data is to be set. + * @param {boolean} exists - Boolean indicating whether the path exists. + * @returns {string} - Stringified output of 'mockPathExists' method. + */ + getMockedPathExistsOutput(path: string, exists: boolean): string { + return JSON.stringify({ [this.sessionStorageItemName]: { pathExists: { [path]: exists } } }).slice(1, -1); + } + + /** + * Returns parsed session storage data used for testing. + * @param {Object} data - Object or string representing the data to be cleaned. + * @returns {string} - Stringified session storage data. + */ + getCleanSessionStorageData(data: any): string { + if (typeof data === 'string') { + data = JSON.parse(data); + } + + return JSON.stringify(data) + .replace(/\\/g, '') + .replace(/"{/g, '{') + .replace(/}"/g, '}'); + } + + /** + * Returns ID of Luigi visualization container added in the DOM for testing. + * @returns {string} - ID of Luigi visualization container. + */ + getVisualizationContainerId(): string { + return this.visualizationContainerId; + } + + /** + * Returns list of messages, representing message elements added in the DOM for testing. + * @returns {Array} - Array of message elements. */ getMSG(): any[] { return this.messages; } + + /** + * Returns the global window object. + * @returns the global win object + */ + private getGlobalThis(): any { + return this.win || globalThis; + } } diff --git a/client-frameworks-support/testing-utilities/test/cypress/e2e/0-luigimockengine/mockengine-test.cy.js b/client-frameworks-support/testing-utilities/test/cypress/e2e/0-luigimockengine/mockengine-test.cy.js index a5b1295741..9a0fe2bab5 100644 --- a/client-frameworks-support/testing-utilities/test/cypress/e2e/0-luigimockengine/mockengine-test.cy.js +++ b/client-frameworks-support/testing-utilities/test/cypress/e2e/0-luigimockengine/mockengine-test.cy.js @@ -1,9 +1,10 @@ -let uxManager, linkManager; - describe('Luigi Mock Engine', () => { + const visualizationContainer = '[id^="luigi-debug-vis-cnt"]'; + before(() => { cy.visit('http://localhost:8181/'); }); + /** * Testing Luigi Client UX Manager features */ @@ -11,7 +12,7 @@ describe('Luigi Mock Engine', () => { it('Check LuigiClient.uxManager().alert', () => { cy.get('[id^=uxbutton1]').click(); - cy.get('[id^="luigi-debug-vis-cnt"]') + cy.get(visualizationContainer) .children() .contains('"msg":"luigi.ux.alert.show"'); }); @@ -19,7 +20,7 @@ describe('Luigi Mock Engine', () => { it('Check LuigiClient.uxManager().confirmModal', () => { cy.get('[id^=uxbutton2]').click(); - cy.get('[id^="luigi-debug-vis-cnt"]') + cy.get(visualizationContainer) .children() .contains('"msg":"luigi.ux.confirmationModal.show"'); }); @@ -27,7 +28,7 @@ describe('Luigi Mock Engine', () => { it('Check LuigiClient.uxManager().loadIndicator', () => { cy.get('[id^=uxbutton3]').click(); - cy.get('[id^="luigi-debug-vis-cnt"]') + cy.get(visualizationContainer) .children() .contains('"msg":"luigi.show-loading-indicator"'); }); @@ -35,7 +36,7 @@ describe('Luigi Mock Engine', () => { it('Check LuigiClient.uxManager().setCurrentLocale', () => { cy.get('[id^=uxbutton4]').click(); - cy.get('[id^="luigi-debug-vis-cnt"]') + cy.get(visualizationContainer) .children() .contains('"msg":"luigi.current-locale-changed"'); }); @@ -48,7 +49,7 @@ describe('Luigi Mock Engine', () => { it('Check LuigiClient.linkManager().openAsModal', () => { cy.get('[id^=button1]').click(); - cy.get('[id^="luigi-debug-vis-cnt"]') + cy.get(visualizationContainer) .children() .contains('"msg":"luigi.navigate.ok"'); }); @@ -56,19 +57,19 @@ describe('Luigi Mock Engine', () => { it('Check LuigiClient.linkManager().split', () => { cy.get('[id^=button2]').click(); - cy.get('[id^="luigi-debug-vis-cnt"]').contains('"msg":"luigi.navigate.ok"'); + cy.get(visualizationContainer).contains('"msg":"luigi.navigate.ok"'); }); it('Check LuigiClient.linkManager().drawer', () => { cy.get('[id^=button3]').click(); - cy.get('[id^="luigi-debug-vis-cnt"]').contains('"msg":"luigi.navigate.ok"'); + cy.get(visualizationContainer).contains('"msg":"luigi.navigate.ok"'); }); it('Check LuigiClient.linkManager().pathExists', () => { cy.get('[id^=button4]').click(); - cy.get('[id^="luigi-debug-vis-cnt"]').contains('"msg":"luigi.navigation.pathExists.answer"'); + cy.get(visualizationContainer).contains('"msg":"luigi.navigation.pathExists.answer"'); }); }); }); diff --git a/docs/luigi-testing-utilities.md b/docs/luigi-testing-utilities.md index 331d90d696..9b6fc682bc 100644 --- a/docs/luigi-testing-utilities.md +++ b/docs/luigi-testing-utilities.md @@ -97,20 +97,19 @@ describe('Another test using cypress', () => { cy.get('.pathExists').click().then(() => { luigiMockUtil.mockPathExists('/test', false); }); - cy.getAllSessionStorage().then((result: any) => { - expect(result).to.deep.equal({ - "http://localhost:4200": { - luigiMockData: '{"pathExists":{"/test":false}}' - }, - }); - }) + cy.getAllSessionStorage().then((storage: any) => { + const result = luigiMockUtil.getCleanSessionStorageData(storage); + + expect(result).to.contains(luigiMockUtil.getMockedPathExistsOutput('/test', false)); + }); }); it('should mock context update', () => { + const visualizationContainerId = luigiMockUtil.getVisualizationContainerId(); const context = {ctxKey: 'ctxValue'}; luigiMockUtil.mockContext(context); - cy.get('#luigi-debug-vis-cnt').contains('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}'); + cy.get('#' + visualizationContainerId).contains(luigiMockUtil.getMockedContextOutput(context)); }); }); ``` @@ -131,22 +130,25 @@ describe('Another test using nightwatch', function () { await browser.expect.element('.pathExists').to.be.present; await browser.element('.pathExists').click().then(() => { luigiMockUtil.mockPathExists('/test', false); - browser.execute(() => window.sessionStorage.getItem('luigiMockData'), [], function (result) { - expect(result.value).to.contains('{"pathExists":{"/test":false}}'); + browser.execute(() => window.sessionStorage, [], function (storage) { + const result = luigiMockUtil.getCleanSessionStorageData(storage.value); + + expect(result).to.contains(luigiMockUtil.getMockedPathExistsOutput('/test', false)); }); }); }); it('should mock context update', async () => { + const visualizationContainerId = luigiMockUtil.getVisualizationContainerId(); const context = {ctxKey: 'ctxValue'}; await luigiMockUtil.mockContext(context); - // Wait until '#luigi-debug-vis-cnt' element is present - await browser.waitForElementPresent('#luigi-debug-vis-cnt', undefined, undefined, false, () => { - const wrapper = browser.expect.element('#luigi-debug-vis-cnt'); + // Wait until Luigi visualization container is present + await browser.waitForElementPresent('#' + visualizationContainerId, undefined, undefined, false, () => { + const wrapper = browser.expect.element('#' + visualizationContainerId); wrapper.to.be.present; - wrapper.text.to.contains('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}'); + wrapper.text.to.contains(luigiMockUtil.getMockedContextOutput(context)); }); }); @@ -176,21 +178,23 @@ describe('Another test using webdriverio', () => { // Wait until session storage item is set await browser.setTimeout(defaultTimeout); - const result = await browser.execute(() => window.sessionStorage.getItem('luigiMockData')); + const storage = await browser.execute(() => window.sessionStorage); + const result = await luigiMockUtil.getCleanSessionStorageData(storage); - await expect(result).toEqual('{"pathExists":{"/test":false}}'); + await expect(result).toContain(luigiMockUtil.getMockedPathExistsOutput('/test', false)); }); it('should mock context update', async () => { luigiMockUtil = new LuigiMockUtil(browser); + const visualizationContainerId = luigiMockUtil.getVisualizationContainerId(); const context = {ctxKey: 'ctxValue'}; await browser.url(baseUrl); await luigiMockUtil.mockContext(context); - // Wait until '#luigi-debug-vis-cnt' element is present + // Wait until Luigi visualization container is present await browser.setTimeout(defaultTimeout); - await expect($('#luigi-debug-vis-cnt')).toHaveHTML(expect.stringContaining('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}')); + await expect($('#' + visualizationContainerId)).toHaveHTML(expect.stringContaining(luigiMockUtil.getMockedContextOutput(context))); }); }); ``` @@ -239,25 +243,27 @@ describe('Another test using puppeteer ->', () => { // Wait until session storage item is set await new Promise(resolve => setTimeout(resolve, 500)); - const result = await page.evaluate(() => window.sessionStorage.getItem('luigiMockData')); + const storage = await page.evaluate(() => JSON.stringify(window.sessionStorage)); + const result = await luigiMockUtil.getCleanSessionStorageData(storage); - await expect(result).toContain('{"pathExists":{"/test":false}}'); + await expect(result).toContain(luigiMockUtil.getMockedPathExistsOutput('/test', false)); }); }); }); it('should mock context update', async () => { + const visualizationContainerId = luigiMockUtil.getVisualizationContainerId(); const context = {ctxKey: 'ctxValue'}; await luigiMockUtil.mockContext(context); - // Wait until '#luigi-debug-vis-cnt' element is present - await page.waitForSelector('#luigi-debug-vis-cnt').then(async () => { + // Wait until Luigi visualization container is present + await page.waitForSelector('#' + visualizationContainerId).then(async () => { const result = await page - .locator('#luigi-debug-vis-cnt div:nth-child(1)') + .locator(`#${visualizationContainerId} div:nth-child(1)`) .map(div => div.innerText) .wait(); - expect(result).toContain('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}'); + expect(result).toContain(luigiMockUtil.getMockedContextOutput(context)); }); }); }); @@ -265,7 +271,11 @@ describe('Another test using puppeteer ->', () => { ## Functions provided - **mockContext**: Mocks the context by sending Luigi context messages with the desired mocked context as parameter. -- **mockPathExists**: This method serves as a mock for the Luigi Client `pathExists()` function. It is used in e2e tests when component being tested utilizes a call to `LuigiClient.linkManager().pathExists()` +- **mockPathExists**: This method serves as a mock for the Luigi Client `pathExists()` function. It is used in e2e tests when component being tested utilizes a call to `LuigiClient.linkManager().pathExists()`. - **modalOpenedWithTitle**: Checks on the printed DOM Luigi message responses for a modal with given title being opened. In such a case, a message would be printed containing a `modal.title`. Returns `false` if such element was not found. +- **getMockedContextOutput**: Returns output of 'mockContext' method with given data. +- **getMockedPathExistsOutput**: Returns output of 'mockPathExists' method with given arguments. +- **getCleanSessionStorageData**: Returns parsed session storage data used for testing. +- **getVisualizationContainerId**: Returns ID of Luigi visualization container added in the DOM for testing. - **getMSG**: Returns list of messages, representing message elements added in the DOM for testing. -- **parseLuigiMockedMessages**: Parses the elements added by LuigiMockModule into the DOM and assigns them to the local messages variable +- **parseLuigiMockedMessages**: Parses the elements added by LuigiMockModule into the DOM and assigns them to the local messages variable. diff --git a/plugins/auth/public/auth-oidc-pkce/README.md b/plugins/auth/public/auth-oidc-pkce/README.md index 3a427c010b..2af0b3548b 100644 --- a/plugins/auth/public/auth-oidc-pkce/README.md +++ b/plugins/auth/public/auth-oidc-pkce/README.md @@ -60,7 +60,7 @@ Luigi.setConfig({ ``` If you want to use the silent token renewal feature, the `silent-callback.html` needs to be copied to a folder in your Luigi Core installation, -which is the return path for the IdP provider, configured through the `redirect_uri` setting. The default location of `redirect_uri` is `/assets/auth-oidc-pkce/silent-callback.html`. +which is the return path for the IdP provider, configured through the `silent_redirect_uri` setting. The default location of `silent_redirect_uri` is `/assets/auth-oidc-pkce/silent-callback.html`. Next, you must install `oidc-client-ts` in your project as a dev dependency: diff --git a/plugins/auth/public/auth-oidc/README.md b/plugins/auth/public/auth-oidc/README.md index e80f2a14b6..d6413b60d0 100644 --- a/plugins/auth/public/auth-oidc/README.md +++ b/plugins/auth/public/auth-oidc/README.md @@ -63,7 +63,7 @@ Luigi.setConfig({ ``` If you want to use the silent token renewal feature, the `silent-callback.html` needs to be copied to a folder in your Luigi Core installation, -which is the return path for the IdP provider, configured through the `redirect_uri` setting. The default location of `redirect_uri` is `/assets/auth-oidc/silent-callback.html`. +which is the return path for the IdP provider, configured through the `silent_redirect_uri` setting. The default location of `silent_redirect_uri` is `/assets/auth-oidc/silent-callback.html`. Next, you must install `oidc-client` in your project as a dev dependency: