diff options
Diffstat (limited to 'server/lib')
-rw-r--r-- | server/lib/auth.ts | 13 | ||||
-rw-r--r-- | server/lib/oauth-model.ts | 2 | ||||
-rw-r--r-- | server/lib/plugins/plugin-manager.ts | 13 | ||||
-rw-r--r-- | server/lib/plugins/register-helpers-store.ts | 22 |
4 files changed, 34 insertions, 16 deletions
diff --git a/server/lib/auth.ts b/server/lib/auth.ts index eaae5fdf3..2ef77bc9c 100644 --- a/server/lib/auth.ts +++ b/server/lib/auth.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { isUserDisplayNameValid, isUserRoleValid, isUserUsernameValid } from '@server/helpers/custom-validators/users' | 1 | import { isUserDisplayNameValid, isUserRoleValid, isUserUsernameValid } from '@server/helpers/custom-validators/users' |
2 | import { logger } from '@server/helpers/logger' | 2 | import { logger } from '@server/helpers/logger' |
3 | import { generateRandomString } from '@server/helpers/utils' | 3 | import { generateRandomString } from '@server/helpers/utils' |
4 | import { OAUTH_LIFETIME, WEBSERVER } from '@server/initializers/constants' | 4 | import { OAUTH_LIFETIME, PLUGIN_EXTERNAL_AUTH_TOKEN_LIFETIME } from '@server/initializers/constants' |
5 | import { revokeToken } from '@server/lib/oauth-model' | 5 | import { revokeToken } from '@server/lib/oauth-model' |
6 | import { PluginManager } from '@server/lib/plugins/plugin-manager' | 6 | import { PluginManager } from '@server/lib/plugins/plugin-manager' |
7 | import { OAuthTokenModel } from '@server/models/oauth/oauth-token' | 7 | import { OAuthTokenModel } from '@server/models/oauth/oauth-token' |
@@ -35,7 +35,7 @@ const authBypassTokens = new Map<string, { | |||
35 | npmName: string | 35 | npmName: string |
36 | }>() | 36 | }>() |
37 | 37 | ||
38 | async function handleIdAndPassLogin (req: express.Request, res: express.Response, next: express.NextFunction) { | 38 | async function handleLogin (req: express.Request, res: express.Response, next: express.NextFunction) { |
39 | const grantType = req.body.grant_type | 39 | const grantType = req.body.grant_type |
40 | 40 | ||
41 | if (grantType === 'password') { | 41 | if (grantType === 'password') { |
@@ -90,10 +90,9 @@ async function onExternalUserAuthenticated (options: { | |||
90 | logger.info('Generating auth bypass token for %s in auth %s of plugin %s.', authResult.username, authName, npmName) | 90 | logger.info('Generating auth bypass token for %s in auth %s of plugin %s.', authResult.username, authName, npmName) |
91 | 91 | ||
92 | const bypassToken = await generateRandomString(32) | 92 | const bypassToken = await generateRandomString(32) |
93 | const tokenLifetime = 1000 * 60 * 5 // 5 minutes | ||
94 | 93 | ||
95 | const expires = new Date() | 94 | const expires = new Date() |
96 | expires.setTime(expires.getTime() + tokenLifetime) | 95 | expires.setTime(expires.getTime() + PLUGIN_EXTERNAL_AUTH_TOKEN_LIFETIME) |
97 | 96 | ||
98 | const user = buildUserResult(authResult) | 97 | const user = buildUserResult(authResult) |
99 | authBypassTokens.set(bypassToken, { | 98 | authBypassTokens.set(bypassToken, { |
@@ -108,7 +107,7 @@ async function onExternalUserAuthenticated (options: { | |||
108 | 107 | ||
109 | // --------------------------------------------------------------------------- | 108 | // --------------------------------------------------------------------------- |
110 | 109 | ||
111 | export { oAuthServer, handleIdAndPassLogin, onExternalUserAuthenticated, handleTokenRevocation } | 110 | export { oAuthServer, handleLogin, onExternalUserAuthenticated, handleTokenRevocation } |
112 | 111 | ||
113 | // --------------------------------------------------------------------------- | 112 | // --------------------------------------------------------------------------- |
114 | 113 | ||
@@ -212,7 +211,7 @@ function proxifyExternalAuthBypass (req: express.Request, res: express.Response) | |||
212 | 211 | ||
213 | const now = new Date() | 212 | const now = new Date() |
214 | if (now.getTime() > expires.getTime()) { | 213 | if (now.getTime() > expires.getTime()) { |
215 | logger.error('Cannot authenticate user with an expired bypass token') | 214 | logger.error('Cannot authenticate user with an expired external auth token') |
216 | return res.sendStatus(400) | 215 | return res.sendStatus(400) |
217 | } | 216 | } |
218 | 217 | ||
@@ -267,7 +266,7 @@ function buildUserResult (pluginResult: RegisterServerAuthenticatedResult) { | |||
267 | return { | 266 | return { |
268 | username: pluginResult.username, | 267 | username: pluginResult.username, |
269 | email: pluginResult.email, | 268 | email: pluginResult.email, |
270 | role: pluginResult.role || UserRole.USER, | 269 | role: pluginResult.role ?? UserRole.USER, |
271 | displayName: pluginResult.displayName || pluginResult.username | 270 | displayName: pluginResult.displayName || pluginResult.username |
272 | } | 271 | } |
273 | } | 272 | } |
diff --git a/server/lib/oauth-model.ts b/server/lib/oauth-model.ts index 8b9975bb4..8d8a6d85e 100644 --- a/server/lib/oauth-model.ts +++ b/server/lib/oauth-model.ts | |||
@@ -139,7 +139,7 @@ async function revokeToken (tokenInfo: { refreshToken: string }) { | |||
139 | 139 | ||
140 | if (token) { | 140 | if (token) { |
141 | if (res.locals.explicitLogout === true && token.User.pluginAuth && token.authName) { | 141 | if (res.locals.explicitLogout === true && token.User.pluginAuth && token.authName) { |
142 | PluginManager.Instance.onLogout(token.User.pluginAuth, token.authName) | 142 | PluginManager.Instance.onLogout(token.User.pluginAuth, token.authName, token.User) |
143 | } | 143 | } |
144 | 144 | ||
145 | clearCacheByToken(token.accessToken) | 145 | clearCacheByToken(token.accessToken) |
diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts index c64ca60aa..38336bcc6 100644 --- a/server/lib/plugins/plugin-manager.ts +++ b/server/lib/plugins/plugin-manager.ts | |||
@@ -21,7 +21,8 @@ import { ClientHtml } from '../client-html' | |||
21 | import { PluginTranslation } from '../../../shared/models/plugins/plugin-translation.model' | 21 | import { PluginTranslation } from '../../../shared/models/plugins/plugin-translation.model' |
22 | import { RegisterHelpersStore } from './register-helpers-store' | 22 | import { RegisterHelpersStore } from './register-helpers-store' |
23 | import { RegisterServerHookOptions } from '@shared/models/plugins/register-server-hook.model' | 23 | import { RegisterServerHookOptions } from '@shared/models/plugins/register-server-hook.model' |
24 | import { MOAuthTokenUser } from '@server/typings/models' | 24 | import { MOAuthTokenUser, MUser } from '@server/typings/models' |
25 | import { RegisterServerAuthPassOptions, RegisterServerAuthExternalOptions } from '@shared/models/plugins/register-server-auth.model' | ||
25 | 26 | ||
26 | export interface RegisteredPlugin { | 27 | export interface RegisteredPlugin { |
27 | npmName: string | 28 | npmName: string |
@@ -133,14 +134,14 @@ export class PluginManager implements ServerHook { | |||
133 | return this.translations[locale] || {} | 134 | return this.translations[locale] || {} |
134 | } | 135 | } |
135 | 136 | ||
136 | onLogout (npmName: string, authName: string) { | 137 | onLogout (npmName: string, authName: string, user: MUser) { |
137 | const auth = this.getAuth(npmName, authName) | 138 | const auth = this.getAuth(npmName, authName) |
138 | 139 | ||
139 | if (auth?.onLogout) { | 140 | if (auth?.onLogout) { |
140 | logger.info('Running onLogout function from auth %s of plugin %s', authName, npmName) | 141 | logger.info('Running onLogout function from auth %s of plugin %s', authName, npmName) |
141 | 142 | ||
142 | try { | 143 | try { |
143 | auth.onLogout() | 144 | auth.onLogout(user) |
144 | } catch (err) { | 145 | } catch (err) { |
145 | logger.warn('Cannot run onLogout function from auth %s of plugin %s.', authName, npmName, { err }) | 146 | logger.warn('Cannot run onLogout function from auth %s of plugin %s.', authName, npmName, { err }) |
146 | } | 147 | } |
@@ -478,8 +479,10 @@ export class PluginManager implements ServerHook { | |||
478 | const plugin = this.getRegisteredPluginOrTheme(npmName) | 479 | const plugin = this.getRegisteredPluginOrTheme(npmName) |
479 | if (!plugin || plugin.type !== PluginType.PLUGIN) return null | 480 | if (!plugin || plugin.type !== PluginType.PLUGIN) return null |
480 | 481 | ||
481 | return plugin.registerHelpersStore.getIdAndPassAuths() | 482 | let auths: (RegisterServerAuthPassOptions | RegisterServerAuthExternalOptions)[] = plugin.registerHelpersStore.getIdAndPassAuths() |
482 | .find(a => a.authName === authName) | 483 | auths = auths.concat(plugin.registerHelpersStore.getExternalAuths()) |
484 | |||
485 | return auths.find(a => a.authName === authName) | ||
483 | } | 486 | } |
484 | 487 | ||
485 | // ###################### Private getters ###################### | 488 | // ###################### Private getters ###################### |
diff --git a/server/lib/plugins/register-helpers-store.ts b/server/lib/plugins/register-helpers-store.ts index 277f2b687..151196bf1 100644 --- a/server/lib/plugins/register-helpers-store.ts +++ b/server/lib/plugins/register-helpers-store.ts | |||
@@ -1,5 +1,12 @@ | |||
1 | import * as express from 'express' | ||
1 | import { logger } from '@server/helpers/logger' | 2 | import { logger } from '@server/helpers/logger' |
2 | import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PLAYLIST_PRIVACIES, VIDEO_PRIVACIES } from '@server/initializers/constants' | 3 | import { |
4 | VIDEO_CATEGORIES, | ||
5 | VIDEO_LANGUAGES, | ||
6 | VIDEO_LICENCES, | ||
7 | VIDEO_PLAYLIST_PRIVACIES, | ||
8 | VIDEO_PRIVACIES | ||
9 | } from '@server/initializers/constants' | ||
3 | import { onExternalUserAuthenticated } from '@server/lib/auth' | 10 | import { onExternalUserAuthenticated } from '@server/lib/auth' |
4 | import { PluginModel } from '@server/models/server/plugin' | 11 | import { PluginModel } from '@server/models/server/plugin' |
5 | import { RegisterServerOptions } from '@server/typings/plugins' | 12 | import { RegisterServerOptions } from '@server/typings/plugins' |
@@ -10,11 +17,15 @@ import { PluginVideoCategoryManager } from '@shared/models/plugins/plugin-video- | |||
10 | import { PluginVideoLanguageManager } from '@shared/models/plugins/plugin-video-language-manager.model' | 17 | import { PluginVideoLanguageManager } from '@shared/models/plugins/plugin-video-language-manager.model' |
11 | import { PluginVideoLicenceManager } from '@shared/models/plugins/plugin-video-licence-manager.model' | 18 | import { PluginVideoLicenceManager } from '@shared/models/plugins/plugin-video-licence-manager.model' |
12 | import { PluginVideoPrivacyManager } from '@shared/models/plugins/plugin-video-privacy-manager.model' | 19 | import { PluginVideoPrivacyManager } from '@shared/models/plugins/plugin-video-privacy-manager.model' |
13 | import { RegisterServerAuthExternalOptions, RegisterServerAuthExternalResult, RegisterServerAuthPassOptions, RegisterServerExternalAuthenticatedResult } from '@shared/models/plugins/register-server-auth.model' | 20 | import { |
21 | RegisterServerAuthExternalOptions, | ||
22 | RegisterServerAuthExternalResult, | ||
23 | RegisterServerAuthPassOptions, | ||
24 | RegisterServerExternalAuthenticatedResult | ||
25 | } from '@shared/models/plugins/register-server-auth.model' | ||
14 | import { RegisterServerHookOptions } from '@shared/models/plugins/register-server-hook.model' | 26 | import { RegisterServerHookOptions } from '@shared/models/plugins/register-server-hook.model' |
15 | import { RegisterServerSettingOptions } from '@shared/models/plugins/register-server-setting.model' | 27 | import { RegisterServerSettingOptions } from '@shared/models/plugins/register-server-setting.model' |
16 | import { serverHookObject } from '@shared/models/plugins/server-hook.model' | 28 | import { serverHookObject } from '@shared/models/plugins/server-hook.model' |
17 | import * as express from 'express' | ||
18 | import { buildPluginHelpers } from './plugin-helpers' | 29 | import { buildPluginHelpers } from './plugin-helpers' |
19 | 30 | ||
20 | type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy' | 31 | type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy' |
@@ -174,6 +185,11 @@ export class RegisterHelpersStore { | |||
174 | const self = this | 185 | const self = this |
175 | 186 | ||
176 | return (options: RegisterServerAuthExternalOptions) => { | 187 | return (options: RegisterServerAuthExternalOptions) => { |
188 | if (!options.authName || !options.onAuthRequest || typeof options.onAuthRequest !== 'function') { | ||
189 | logger.error('Cannot register auth plugin %s: authName of getWeight or login are not valid.', this.npmName) | ||
190 | return | ||
191 | } | ||
192 | |||
177 | this.externalAuths.push(options) | 193 | this.externalAuths.push(options) |
178 | 194 | ||
179 | return { | 195 | return { |