Redirect to default login url on 401

Can be an external URL
pull/5544/head
Chocobozzz 2023-01-04 11:41:03 +01:00
parent 60b880acdf
commit 2570fd9c1c
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
5 changed files with 42 additions and 31 deletions

View File

@ -1,3 +1,4 @@
import { environment } from 'src/environments/environment'
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core' import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router' import { ActivatedRoute, Router } from '@angular/router'
import { AuthService, Notifier, RedirectService, SessionStorageService, UserService } from '@app/core' 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 { FormReactive, FormReactiveService, InputTextComponent } from '@app/shared/shared-forms'
import { InstanceAboutAccordionComponent } from '@app/shared/shared-instance' import { InstanceAboutAccordionComponent } from '@app/shared/shared-instance'
import { NgbAccordion, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' 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' import { RegisteredExternalAuthConfig, ServerConfig } from '@shared/models'
@Component({ @Component({
@ -119,7 +120,7 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni
} }
getAuthHref (auth: RegisteredExternalAuthConfig) { getAuthHref (auth: RegisteredExternalAuthConfig) {
return PluginsManager.getExternalAuthHref(auth) return getExternalAuthHref(environment.apiUrl, auth)
} }
login () { login () {

View File

@ -5,10 +5,11 @@ import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { Notifier } from '@app/core/notification/notifier.service' 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 { HttpStatusCode, MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models'
import { environment } from '../../../environments/environment' import { environment } from '../../../environments/environment'
import { RestExtractor } from '../rest/rest-extractor.service' import { RestExtractor } from '../rest/rest-extractor.service'
import { ServerService } from '../server'
import { AuthStatus } from './auth-status.model' import { AuthStatus } from './auth-status.model'
import { AuthUser } from './auth-user.model' import { AuthUser } from './auth-user.model'
@ -44,6 +45,7 @@ export class AuthService {
private refreshingTokenObservable: Observable<any> private refreshingTokenObservable: Observable<any>
constructor ( constructor (
private serverService: ServerService,
private http: HttpClient, private http: HttpClient,
private notifier: Notifier, private notifier: Notifier,
private hotkeysService: HotkeysService, 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') const headers = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
this.refreshingTokenObservable = this.http.post<UserRefreshToken>(AuthService.BASE_TOKEN_URL, body, { headers }) this.refreshingTokenObservable = this.http.post<UserRefreshToken>(AuthService.BASE_TOKEN_URL, body, { headers })
.pipe( .pipe(
map(res => this.handleRefreshToken(res)), map(res => this.handleRefreshToken(res)),
tap(() => { tap(() => {
this.refreshingTokenObservable = null this.refreshingTokenObservable = null
}), }),
catchError(err => { catchError(err => {
this.refreshingTokenObservable = null this.refreshingTokenObservable = null
logger.error(err) logger.error(err)
logger.info('Cannot refresh token -> logout...') logger.info('Cannot refresh token -> logout...')
this.logout() this.logout()
this.router.navigate([ '/login' ])
return observableThrowError(() => ({ const externalLoginUrl = PluginsManager.getDefaultLoginHref(environment.apiUrl, this.serverService.getHTMLConfig())
error: $localize`You need to reconnect.` if (externalLoginUrl) window.location.href = externalLoginUrl
})) else this.router.navigate([ '/login' ])
}),
share() return observableThrowError(() => ({
) error: $localize`You need to reconnect.`
}))
}),
share()
)
return this.refreshingTokenObservable return this.refreshingTokenObservable
} }

View File

@ -1,6 +1,7 @@
import { HotkeysService } from 'angular2-hotkeys' import { HotkeysService } from 'angular2-hotkeys'
import * as debug from 'debug' import * as debug from 'debug'
import { switchMap } from 'rxjs/operators' import { switchMap } from 'rxjs/operators'
import { environment } from 'src/environments/environment'
import { ViewportScroller } from '@angular/common' import { ViewportScroller } from '@angular/common'
import { Component, OnInit, ViewChild } from '@angular/core' import { Component, OnInit, ViewChild } from '@angular/core'
import { Router } from '@angular/router' import { Router } from '@angular/router'
@ -131,12 +132,7 @@ export class MenuComponent implements OnInit {
} }
getExternalLoginHref () { getExternalLoginHref () {
if (!this.serverConfig || this.serverConfig.client.menu.login.redirectOnSingleExternalAuth !== true) return undefined return PluginsManager.getDefaultLoginHref(environment.apiUrl, this.serverConfig)
const externalAuths = this.serverConfig.plugin.registeredExternalAuths
if (externalAuths.length !== 1) return undefined
return PluginsManager.getExternalAuthHref(externalAuths[0])
} }
isRegistrationAllowed () { isRegistrationAllowed () {

View File

@ -3,7 +3,7 @@ import * as debug from 'debug'
import { firstValueFrom, ReplaySubject } from 'rxjs' import { firstValueFrom, ReplaySubject } from 'rxjs'
import { first, shareReplay } from 'rxjs/operators' import { first, shareReplay } from 'rxjs/operators'
import { RegisterClientHelpers } from 'src/types/register-client-option.model' 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 { import {
ClientHookName, ClientHookName,
clientHookObject, clientHookObject,
@ -16,7 +16,6 @@ import {
RegisterClientRouteOptions, RegisterClientRouteOptions,
RegisterClientSettingsScriptOptions, RegisterClientSettingsScriptOptions,
RegisterClientVideoFieldOptions, RegisterClientVideoFieldOptions,
RegisteredExternalAuthConfig,
ServerConfigPlugin ServerConfigPlugin
} from '@shared/models' } from '@shared/models'
import { environment } from '../environments/environment' import { environment } from '../environments/environment'
@ -94,9 +93,13 @@ class PluginsManager {
return isTheme ? '/themes' : '/plugins' return isTheme ? '/themes' : '/plugins'
} }
static getExternalAuthHref (auth: RegisteredExternalAuthConfig) { static getDefaultLoginHref (apiUrl: string, serverConfig: HTMLServerConfig) {
return environment.apiUrl + `/plugins/${auth.name}/${auth.version}/auth/${auth.authName}` 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) { loadPluginsList (config: HTMLServerConfig) {

View File

@ -1,3 +1,4 @@
import { RegisteredExternalAuthConfig } from '@shared/models'
import { HookType } from '../../models/plugins/hook-type.enum' import { HookType } from '../../models/plugins/hook-type.enum'
import { isCatchable, isPromise } from '../common/promises' import { isCatchable, isPromise } from '../common/promises'
@ -49,7 +50,12 @@ async function internalRunHook <T> (options: {
return result return result
} }
function getExternalAuthHref (apiUrl: string, auth: RegisteredExternalAuthConfig) {
return apiUrl + `/plugins/${auth.name}/${auth.version}/auth/${auth.authName}`
}
export { export {
getHookType, getHookType,
internalRunHook internalRunHook,
getExternalAuthHref
} }