diff --git a/conversejs/builtin.ts b/conversejs/builtin.ts index 1af90e80..feeeb965 100644 --- a/conversejs/builtin.ts +++ b/conversejs/builtin.ts @@ -159,6 +159,7 @@ async function initConverse ( // no viewer mode if authenticated. params.livechat_enable_viewer_mode = autoViewerMode && !isAuthenticated && !isRemoteWithNicknameSet + params.livechat_external_auth_oidc_button_label = initConverseParams.externalAuthOIDC?.buttonLabel if (chatIncludeMode === 'peertube-video') { params.livechat_mini_muc_head = true // we must replace the muc-head by the custom buttons toolbar. diff --git a/conversejs/custom/shared/styles/livechat.scss b/conversejs/custom/shared/styles/livechat.scss index 49d8a3ee..9b1cc456 100644 --- a/conversejs/custom/shared/styles/livechat.scss +++ b/conversejs/custom/shared/styles/livechat.scss @@ -93,6 +93,17 @@ body[livechat-viewer-mode="on"] { } } +.livechat-external-login-modal { + .livechat-external-login-modal-external-auth-oidc { + text-align: center; + width: 100%; + } + + hr { + background-color: var(--chatroom-head-bg-color); + } +} + // Transparent mode body.livechat-transparent { // --peertube-main-background: rgba(0 0 0 / 0%) !important; diff --git a/conversejs/custom/templates/livechat-external-login-modal.js b/conversejs/custom/templates/livechat-external-login-modal.js index fdba789c..b5a158c3 100644 --- a/conversejs/custom/templates/livechat-external-login-modal.js +++ b/conversejs/custom/templates/livechat-external-login-modal.js @@ -1,3 +1,4 @@ +import { api } from '@converse/headless/core' import { __ } from 'i18n' import { html } from 'lit' @@ -7,7 +8,22 @@ export const tplExternalLoginModal = (el, o) => { // eslint-disable-next-line no-undef const i18nRemotePeertubeUrl = __(LOC_login_remote_peertube_url) const i18nRemotePeertubeOpen = __('OK') + const externalAuthOIDCButtonLabel = api.settings.get('livechat_external_auth_oidc_button_label') return html`` } - - ` + + ` } diff --git a/conversejs/lib/plugins/livechat-specific.ts b/conversejs/lib/plugins/livechat-specific.ts index b12a2c74..8844b38e 100644 --- a/conversejs/lib/plugins/livechat-specific.ts +++ b/conversejs/lib/plugins/livechat-specific.ts @@ -34,7 +34,12 @@ export const livechatSpecificsPlugin = { } // update other settings - for (const k of ['hide_muc_participants', 'livechat_enable_viewer_mode', 'livechat_mini_muc_head']) { + for (const k of [ + 'hide_muc_participants', + 'livechat_enable_viewer_mode', + 'livechat_external_auth_oidc_button_label', + 'livechat_mini_muc_head' + ]) { _converse.api.settings.set(k, params[k]) } diff --git a/conversejs/lib/plugins/livechat-viewer-mode.ts b/conversejs/lib/plugins/livechat-viewer-mode.ts index 562ae384..1157a2b4 100644 --- a/conversejs/lib/plugins/livechat-viewer-mode.ts +++ b/conversejs/lib/plugins/livechat-viewer-mode.ts @@ -8,7 +8,8 @@ export const livechatViewerModePlugin = { _converse.api.settings.extend({ livechat_enable_viewer_mode: false, livechat_peertube_video_original_url: undefined, - livechat_peertube_video_uuid: undefined + livechat_peertube_video_uuid: undefined, + livechat_external_auth_oidc_button_label: undefined }) const originalGetDefaultMUCNickname = _converse.getDefaultMUCNickname diff --git a/server/lib/conversejs/params.ts b/server/lib/conversejs/params.ts index 7fb2a702..40702df3 100644 --- a/server/lib/conversejs/params.ts +++ b/server/lib/conversejs/params.ts @@ -79,7 +79,11 @@ async function getConverseJSParams ( const oidc = ExternalAuthOIDC.singleton() // TODO: - const externalAuthOIDC = await oidc.isOk() ? undefined : undefined + const externalAuthOIDC = await oidc.isOk() + ? { + buttonLabel: oidc.getButtonLabel() ?? '???' + } + : undefined return { peertubeVideoOriginalUrl: roomInfos.video?.url, diff --git a/server/lib/diagnostic/external-auth-custom-oidc.ts b/server/lib/diagnostic/external-auth-custom-oidc.ts index a0b51413..495120ed 100644 --- a/server/lib/diagnostic/external-auth-custom-oidc.ts +++ b/server/lib/diagnostic/external-auth-custom-oidc.ts @@ -16,13 +16,20 @@ export async function diagExternalAuthCustomOIDC (test: string, _options: Regist return result } - const errors = await oidc.check() - if (errors.length) { + result.messages.push('Discovery URL: ' + (oidc.getDiscoveryUrl() ?? 'undefined')) + + const oidcErrors = await oidc.check() + if (oidcErrors.length) { result.messages.push({ level: 'error', message: 'The ExternalAuthOIDC singleton got some errors:' }) - result.messages.push(...errors) + for (const oidcError of oidcErrors) { + result.messages.push({ + level: 'error', + message: oidcError + }) + } return result } } catch (err) { @@ -33,6 +40,18 @@ export async function diagExternalAuthCustomOIDC (test: string, _options: Regist return result } + const oidc = ExternalAuthOIDC.singleton() + const issuer = await oidc.loadIssuer() + if (issuer) { + result.messages.push('Discovery URL loaded: ' + JSON.stringify(issuer.metadata)) + } else { + result.messages.push({ + level: 'error', + message: 'Failed to load the Discovery URL.' + }) + return result + } + result.ok = true result.messages.push('Configuration OK.') return result diff --git a/server/lib/external-auth/oidc.ts b/server/lib/external-auth/oidc.ts index 11a3e06d..e394ff79 100644 --- a/server/lib/external-auth/oidc.ts +++ b/server/lib/external-auth/oidc.ts @@ -14,6 +14,7 @@ class ExternalAuthOIDC { private readonly clientId: string | undefined private readonly clientSecret: string | undefined private ok: boolean | undefined + private issuer: Issuer | undefined | null protected readonly logger: { debug: (s: string) => void info: (s: string) => void @@ -54,6 +55,22 @@ class ExternalAuthOIDC { return !this.enabled } + /** + * Get the button + * @returns Button label + */ + getButtonLabel (): string | undefined { + return this.buttonLabel + } + + /** + * Get the discovery URL + * @returns discoveryURL + */ + getDiscoveryUrl (): string | undefined { + return this.discoveryUrl + } + /** * Indicates if the OIDC provider is correctly configured. * @param force If true, all checks will be forced again. @@ -78,43 +95,52 @@ class ExternalAuthOIDC { } const errors: string[] = [] - if (this.buttonLabel === undefined) { + if ((this.buttonLabel ?? '') === '') { errors.push('Missing button label') } - if (this.discoveryUrl === undefined) { + if ((this.discoveryUrl ?? '') === '') { errors.push('Missing discovery url') } else { try { - const uri = new URL(this.discoveryUrl) + const uri = new URL(this.discoveryUrl ?? 'wrong url') this.logger.debug('OIDC Discovery url is valid: ' + uri.toString()) } catch (err) { errors.push('Invalid discovery url') } } - if (this.clientId === undefined) { + if ((this.clientId ?? '') === '') { errors.push('Missing client id') } - if (this.clientSecret === undefined) { + if ((this.clientSecret ?? '') === '') { errors.push('Missing client secret') } - if (errors.length === 0) { - // Now we can try to use the discover service - try { - const issuer = await Issuer.discover(this.discoveryUrl as string) - this.logger.debug(`Discovered issuer, metadata are: ${JSON.stringify(issuer.metadata)}`) - } catch (err) { - this.logger.error(err as string) - errors.push(`Discovery URL non working: ${err as string}`) - } - } - if (errors.length) { this.logger.error('OIDC is not ok: ' + JSON.stringify(errors)) } return errors } + /** + * Ensure the issuer is loaded. + * @returns the issuer if enabled + */ + async loadIssuer (): Promise { + // this.issuer === null means we already tried, but it failed. + if (this.issuer !== undefined) { return this.issuer } + + if (!await this.isOk()) { return null } + + try { + this.issuer = await Issuer.discover(this.discoveryUrl as string) + this.logger.debug(`Discovered issuer, metadata are: ${JSON.stringify(this.issuer.metadata)}`) + } catch (err) { + this.logger.error(err as string) + this.issuer = null + } + return this.issuer + } + /** * frees the singleton */ @@ -143,6 +169,7 @@ class ExternalAuthOIDC { settings['external-auth-custom-oidc-client-id'] as string | undefined, settings['external-auth-custom-oidc-client-secret'] as string | undefined ) + return singleton }