From 2570fd9c1c879d1a543fb0dff1e7cfb036234d11 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 4 Jan 2023 11:41:03 +0100 Subject: [PATCH] Redirect to default login url on 401 Can be an external URL --- client/src/app/+login/login.component.ts | 5 ++- client/src/app/core/auth/auth.service.ts | 45 ++++++++++++---------- client/src/app/menu/menu.component.ts | 8 +--- client/src/root-helpers/plugins-manager.ts | 11 ++++-- shared/core-utils/plugins/hooks.ts | 8 +++- 5 files changed, 44 insertions(+), 33 deletions(-) diff --git a/client/src/app/+login/login.component.ts b/client/src/app/+login/login.component.ts index c1705807f..5f6aa842e 100644 --- a/client/src/app/+login/login.component.ts +++ b/client/src/app/+login/login.component.ts @@ -1,3 +1,4 @@ +import { environment } from 'src/environments/environment' import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { AuthService, Notifier, RedirectService, SessionStorageService, UserService } from '@app/core' @@ -7,7 +8,7 @@ import { USER_OTP_TOKEN_VALIDATOR } from '@app/shared/form-validators/user-valid import { FormReactive, FormReactiveService, InputTextComponent } from '@app/shared/shared-forms' import { InstanceAboutAccordionComponent } from '@app/shared/shared-instance' import { NgbAccordion, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' -import { PluginsManager } from '@root-helpers/plugins-manager' +import { getExternalAuthHref } from '@shared/core-utils' import { RegisteredExternalAuthConfig, ServerConfig } from '@shared/models' @Component({ @@ -119,7 +120,7 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni } getAuthHref (auth: RegisteredExternalAuthConfig) { - return PluginsManager.getExternalAuthHref(auth) + return getExternalAuthHref(environment.apiUrl, auth) } login () { diff --git a/client/src/app/core/auth/auth.service.ts b/client/src/app/core/auth/auth.service.ts index 4de28e51e..ed7eabb76 100644 --- a/client/src/app/core/auth/auth.service.ts +++ b/client/src/app/core/auth/auth.service.ts @@ -5,10 +5,11 @@ import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular import { Injectable } from '@angular/core' import { Router } from '@angular/router' import { Notifier } from '@app/core/notification/notifier.service' -import { logger, OAuthUserTokens, objectToUrlEncoded, peertubeLocalStorage } from '@root-helpers/index' +import { logger, OAuthUserTokens, objectToUrlEncoded, peertubeLocalStorage, PluginsManager } from '@root-helpers/index' import { HttpStatusCode, MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models' import { environment } from '../../../environments/environment' import { RestExtractor } from '../rest/rest-extractor.service' +import { ServerService } from '../server' import { AuthStatus } from './auth-status.model' import { AuthUser } from './auth-user.model' @@ -44,6 +45,7 @@ export class AuthService { private refreshingTokenObservable: Observable constructor ( + private serverService: ServerService, private http: HttpClient, private notifier: Notifier, private hotkeysService: HotkeysService, @@ -213,25 +215,28 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular const headers = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded') this.refreshingTokenObservable = this.http.post(AuthService.BASE_TOKEN_URL, body, { headers }) - .pipe( - map(res => this.handleRefreshToken(res)), - tap(() => { - this.refreshingTokenObservable = null - }), - catchError(err => { - this.refreshingTokenObservable = null - - logger.error(err) - logger.info('Cannot refresh token -> logout...') - this.logout() - this.router.navigate([ '/login' ]) - - return observableThrowError(() => ({ - error: $localize`You need to reconnect.` - })) - }), - share() - ) + .pipe( + map(res => this.handleRefreshToken(res)), + tap(() => { + this.refreshingTokenObservable = null + }), + catchError(err => { + this.refreshingTokenObservable = null + + logger.error(err) + logger.info('Cannot refresh token -> logout...') + this.logout() + + const externalLoginUrl = PluginsManager.getDefaultLoginHref(environment.apiUrl, this.serverService.getHTMLConfig()) + if (externalLoginUrl) window.location.href = externalLoginUrl + else this.router.navigate([ '/login' ]) + + return observableThrowError(() => ({ + error: $localize`You need to reconnect.` + })) + }), + share() + ) return this.refreshingTokenObservable } diff --git a/client/src/app/menu/menu.component.ts b/client/src/app/menu/menu.component.ts index 63f01df92..568cb98bb 100644 --- a/client/src/app/menu/menu.component.ts +++ b/client/src/app/menu/menu.component.ts @@ -1,6 +1,7 @@ import { HotkeysService } from 'angular2-hotkeys' import * as debug from 'debug' import { switchMap } from 'rxjs/operators' +import { environment } from 'src/environments/environment' import { ViewportScroller } from '@angular/common' import { Component, OnInit, ViewChild } from '@angular/core' import { Router } from '@angular/router' @@ -131,12 +132,7 @@ export class MenuComponent implements OnInit { } getExternalLoginHref () { - if (!this.serverConfig || this.serverConfig.client.menu.login.redirectOnSingleExternalAuth !== true) return undefined - - const externalAuths = this.serverConfig.plugin.registeredExternalAuths - if (externalAuths.length !== 1) return undefined - - return PluginsManager.getExternalAuthHref(externalAuths[0]) + return PluginsManager.getDefaultLoginHref(environment.apiUrl, this.serverConfig) } isRegistrationAllowed () { diff --git a/client/src/root-helpers/plugins-manager.ts b/client/src/root-helpers/plugins-manager.ts index 6c64e2b01..e5b06a94c 100644 --- a/client/src/root-helpers/plugins-manager.ts +++ b/client/src/root-helpers/plugins-manager.ts @@ -3,7 +3,7 @@ import * as debug from 'debug' import { firstValueFrom, ReplaySubject } from 'rxjs' import { first, shareReplay } from 'rxjs/operators' import { RegisterClientHelpers } from 'src/types/register-client-option.model' -import { getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks' +import { getExternalAuthHref, getHookType, internalRunHook } from '@shared/core-utils/plugins/hooks' import { ClientHookName, clientHookObject, @@ -16,7 +16,6 @@ import { RegisterClientRouteOptions, RegisterClientSettingsScriptOptions, RegisterClientVideoFieldOptions, - RegisteredExternalAuthConfig, ServerConfigPlugin } from '@shared/models' import { environment } from '../environments/environment' @@ -94,9 +93,13 @@ class PluginsManager { return isTheme ? '/themes' : '/plugins' } - static getExternalAuthHref (auth: RegisteredExternalAuthConfig) { - return environment.apiUrl + `/plugins/${auth.name}/${auth.version}/auth/${auth.authName}` + static getDefaultLoginHref (apiUrl: string, serverConfig: HTMLServerConfig) { + if (!serverConfig || serverConfig.client.menu.login.redirectOnSingleExternalAuth !== true) return undefined + const externalAuths = serverConfig.plugin.registeredExternalAuths + if (externalAuths.length !== 1) return undefined + + return getExternalAuthHref(apiUrl, externalAuths[0]) } loadPluginsList (config: HTMLServerConfig) { diff --git a/shared/core-utils/plugins/hooks.ts b/shared/core-utils/plugins/hooks.ts index 3784969b5..96bcc945e 100644 --- a/shared/core-utils/plugins/hooks.ts +++ b/shared/core-utils/plugins/hooks.ts @@ -1,3 +1,4 @@ +import { RegisteredExternalAuthConfig } from '@shared/models' import { HookType } from '../../models/plugins/hook-type.enum' import { isCatchable, isPromise } from '../common/promises' @@ -49,7 +50,12 @@ async function internalRunHook (options: { return result } +function getExternalAuthHref (apiUrl: string, auth: RegisteredExternalAuthConfig) { + return apiUrl + `/plugins/${auth.name}/${auth.version}/auth/${auth.authName}` +} + export { getHookType, - internalRunHook + internalRunHook, + getExternalAuthHref } -- 2.41.0