From 7e0c26066a5c59af742ae56bddaff9635debe034 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 29 Dec 2022 15:31:40 +0100 Subject: External auth can set more user fields videoQuota, videoQuotaDaily, adminFlags --- server/lib/auth/external-auth.ts | 60 +++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'server/lib/auth/external-auth.ts') diff --git a/server/lib/auth/external-auth.ts b/server/lib/auth/external-auth.ts index 053112801..155ec03d8 100644 --- a/server/lib/auth/external-auth.ts +++ b/server/lib/auth/external-auth.ts @@ -1,26 +1,33 @@ -import { isUserDisplayNameValid, isUserRoleValid, isUserUsernameValid } from '@server/helpers/custom-validators/users' +import { + isUserAdminFlagsValid, + isUserDisplayNameValid, + isUserRoleValid, + isUserUsernameValid, + isUserVideoQuotaDailyValid, + isUserVideoQuotaValid +} from '@server/helpers/custom-validators/users' import { logger } from '@server/helpers/logger' import { generateRandomString } from '@server/helpers/utils' import { PLUGIN_EXTERNAL_AUTH_TOKEN_LIFETIME } from '@server/initializers/constants' import { PluginManager } from '@server/lib/plugins/plugin-manager' import { OAuthTokenModel } from '@server/models/oauth/oauth-token' +import { MUser } from '@server/types/models' import { RegisterServerAuthenticatedResult, RegisterServerAuthPassOptions, RegisterServerExternalAuthenticatedResult } from '@server/types/plugins/register-server-auth.model' -import { UserRole } from '@shared/models' +import { UserAdminFlag, UserRole } from '@shared/models' + +export type ExternalUser = + Pick & + { displayName: string } // Token is the key, expiration date is the value const authBypassTokens = new Map() @@ -172,30 +179,20 @@ function getBypassFromExternalAuth (username: string, externalAuthToken: string) } function isAuthResultValid (npmName: string, authName: string, result: RegisterServerAuthenticatedResult) { - if (!isUserUsernameValid(result.username)) { - logger.error('Auth method %s of plugin %s did not provide a valid username.', authName, npmName, { username: result.username }) + const returnError = (field: string) => { + logger.error('Auth method %s of plugin %s did not provide a valid %s.', authName, npmName, field, { [field]: result[field] }) return false } - if (!result.email) { - logger.error('Auth method %s of plugin %s did not provide a valid email.', authName, npmName, { email: result.email }) - return false - } + if (!isUserUsernameValid(result.username)) return returnError('username') + if (!result.email) return returnError('email') - // role is optional - if (result.role && !isUserRoleValid(result.role)) { - logger.error('Auth method %s of plugin %s did not provide a valid role.', authName, npmName, { role: result.role }) - return false - } - - // display name is optional - if (result.displayName && !isUserDisplayNameValid(result.displayName)) { - logger.error( - 'Auth method %s of plugin %s did not provide a valid display name.', - authName, npmName, { displayName: result.displayName } - ) - return false - } + // Following fields are optional + if (result.role && !isUserRoleValid(result.role)) return returnError('role') + if (result.displayName && !isUserDisplayNameValid(result.displayName)) return returnError('displayName') + if (result.adminFlags && !isUserAdminFlagsValid(result.adminFlags)) return returnError('adminFlags') + if (result.videoQuota && !isUserVideoQuotaValid(result.videoQuota + '')) return returnError('videoQuota') + if (result.videoQuotaDaily && !isUserVideoQuotaDailyValid(result.videoQuotaDaily + '')) return returnError('videoQuotaDaily') return true } @@ -205,7 +202,12 @@ function buildUserResult (pluginResult: RegisterServerAuthenticatedResult) { username: pluginResult.username, email: pluginResult.email, role: pluginResult.role ?? UserRole.USER, - displayName: pluginResult.displayName || pluginResult.username + displayName: pluginResult.displayName || pluginResult.username, + + adminFlags: pluginResult.adminFlags ?? UserAdminFlag.NONE, + + videoQuota: pluginResult.videoQuota, + videoQuotaDaily: pluginResult.videoQuotaDaily } } -- cgit v1.2.3 From 60b880acdfa85eab5c9ec09ba1283f82ae58ec85 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 30 Dec 2022 10:12:20 +0100 Subject: External auth can update user on login --- server/lib/auth/external-auth.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'server/lib/auth/external-auth.ts') diff --git a/server/lib/auth/external-auth.ts b/server/lib/auth/external-auth.ts index 155ec03d8..bc5b74257 100644 --- a/server/lib/auth/external-auth.ts +++ b/server/lib/auth/external-auth.ts @@ -19,6 +19,7 @@ import { RegisterServerExternalAuthenticatedResult } from '@server/types/plugins/register-server-auth.model' import { UserAdminFlag, UserRole } from '@shared/models' +import { BypassLogin } from './oauth-model' export type ExternalUser = Pick & @@ -28,6 +29,7 @@ export type ExternalUser = const authBypassTokens = new Map() @@ -63,7 +65,8 @@ async function onExternalUserAuthenticated (options: { expires, user, npmName, - authName + authName, + userUpdater: authResult.userUpdater }) // Cleanup expired tokens @@ -85,7 +88,7 @@ async function getAuthNameFromRefreshGrant (refreshToken?: string) { return tokenModel?.authName } -async function getBypassFromPasswordGrant (username: string, password: string) { +async function getBypassFromPasswordGrant (username: string, password: string): Promise { const plugins = PluginManager.Instance.getIdAndPassAuths() const pluginAuths: { npmName?: string, registerAuthOptions: RegisterServerAuthPassOptions }[] = [] @@ -140,7 +143,8 @@ async function getBypassFromPasswordGrant (username: string, password: string) { bypass: true, pluginName: pluginAuth.npmName, authName: authOptions.authName, - user: buildUserResult(loginResult) + user: buildUserResult(loginResult), + userUpdater: loginResult.userUpdater } } catch (err) { logger.error('Error in auth method %s of plugin %s', authOptions.authName, pluginAuth.npmName, { err }) @@ -150,7 +154,7 @@ async function getBypassFromPasswordGrant (username: string, password: string) { return undefined } -function getBypassFromExternalAuth (username: string, externalAuthToken: string) { +function getBypassFromExternalAuth (username: string, externalAuthToken: string): BypassLogin { const obj = authBypassTokens.get(externalAuthToken) if (!obj) throw new Error('Cannot authenticate user with unknown bypass token') @@ -174,6 +178,7 @@ function getBypassFromExternalAuth (username: string, externalAuthToken: string) bypass: true, pluginName: npmName, authName, + userUpdater: obj.userUpdater, user } } @@ -194,6 +199,11 @@ function isAuthResultValid (npmName: string, authName: string, result: RegisterS if (result.videoQuota && !isUserVideoQuotaValid(result.videoQuota + '')) return returnError('videoQuota') if (result.videoQuotaDaily && !isUserVideoQuotaDailyValid(result.videoQuotaDaily + '')) return returnError('videoQuotaDaily') + if (result.userUpdater && typeof result.userUpdater !== 'function') { + logger.error('Auth method %s of plugin %s did not provide a valid user updater function.', authName, npmName) + return false + } + return true } -- cgit v1.2.3