multiauth refactor

This commit is contained in:
Jan Prochazka
2024-08-07 16:28:24 +02:00
parent e179b0f20b
commit 5f14da3844
10 changed files with 98 additions and 63 deletions

View File

@@ -23,10 +23,6 @@ class AuthProviderBase {
};
}
shouldAuthorizeApi() {
return false;
}
oauthToken(params) {
return {};
}
@@ -46,14 +42,6 @@ class AuthProviderBase {
return permissions || process.env.PERMISSIONS;
}
isLoginForm() {
return false;
}
getAdditionalConfigProps() {
return {};
}
getLoginPageConnections() {
return null;
}
@@ -68,15 +56,17 @@ class AuthProviderBase {
workflowType: 'anonymous',
};
}
redirect({ state }) {
return {
status: 'error',
};
}
}
class OAuthProvider extends AuthProviderBase {
amoid = 'oauth';
shouldAuthorizeApi() {
return true;
}
async oauthToken(params) {
const { redirectUri, code } = params;
@@ -143,6 +133,18 @@ class OAuthProvider extends AuthProviderBase {
workflowType: 'redirect',
};
}
redirect({ state, redirectUri }) {
const scopeParam = process.env.OAUTH_SCOPE ? `&scope=${process.env.OAUTH_SCOPE}` : '';
return {
status: 'ok',
uri: `${process.env.OAUTH_AUTH}?client_id=${
process.env.OAUTH_CLIENT_ID
}&response_type=code&redirect_uri=${encodeURIComponent(redirectUri)}&state=${encodeURIComponent(
state
)}${scopeParam}`,
};
}
}
class ADProvider extends AuthProviderBase {
@@ -182,14 +184,6 @@ class ADProvider extends AuthProviderBase {
}
}
shouldAuthorizeApi() {
return !process.env.BASIC_AUTH;
}
isLoginForm() {
return !process.env.BASIC_AUTH;
}
toJson() {
return {
...super.toJson(),
@@ -217,14 +211,6 @@ class LoginsProvider extends AuthProviderBase {
return { error: 'Invalid credentials' };
}
shouldAuthorizeApi() {
return !process.env.BASIC_AUTH;
}
isLoginForm() {
return !process.env.BASIC_AUTH;
}
toJson() {
return {
...super.toJson(),
@@ -236,10 +222,6 @@ class LoginsProvider extends AuthProviderBase {
class DenyAllProvider extends AuthProviderBase {
amoid = 'deny';
shouldAuthorizeApi() {
return true;
}
async login(login, password, options = undefined) {
return { error: 'Login not allowed' };
}

View File

@@ -5,7 +5,12 @@ const { getLogger } = require('dbgate-tools');
const AD = require('activedirectory2').promiseWrapper;
const crypto = require('crypto');
const { getTokenSecret, getTokenLifetime } = require('../auth/authCommon');
const { getAuthProviderFromReq, getAuthProviders, getDefaultAuthProvider, getAuthProviderById } = require('../auth/authProvider');
const {
getAuthProviderFromReq,
getAuthProviders,
getDefaultAuthProvider,
getAuthProviderById,
} = require('../auth/authProvider');
const storage = require('./storage');
const logger = getLogger('auth');
@@ -27,6 +32,7 @@ function authMiddleware(req, res, next) {
'/config/get-settings',
'/auth/oauth-token',
'/auth/login',
'/auth/redirect',
'/stream',
'storage/get-connections-for-login-page',
'auth/get-providers',
@@ -37,11 +43,13 @@ function authMiddleware(req, res, next) {
// console.log('********************* getAuthProvider()', getAuthProvider());
const isAdminPage = req.headers['x-is-admin-page'] == 'true';
// const isAdminPage = req.headers['x-is-admin-page'] == 'true';
if (!isAdminPage && !getAuthProviderFromReq(req).shouldAuthorizeApi()) {
if (process.env.BASIC_AUTH) {
// API is not authorized for basic auth
return next();
}
let skipAuth = !!SKIP_AUTH_PATHS.find(x => req.path == getExpressPath(x));
const authHeader = req.headers.authorization;
@@ -70,7 +78,8 @@ function authMiddleware(req, res, next) {
module.exports = {
oauthToken_meta: true,
async oauthToken(params) {
return getDefaultAuthProvider().oauthToken(params);
const { amoid } = params;
return getAuthProviderById(amoid).oauthToken(params);
},
login_meta: true,
async login(params) {
@@ -107,5 +116,11 @@ module.exports = {
};
},
redirect_meta: true,
async redirect(params) {
const { amoid } = params;
return getAuthProviderById(amoid).redirect(params);
},
authMiddleware,
};

View File

@@ -31,8 +31,6 @@ module.exports = {
const authProvider = getAuthProviderFromReq(req);
const login = authProvider.getCurrentLogin(req);
const permissions = authProvider.getCurrentPermissions(req);
const isLoginForm = authProvider.isLoginForm();
const additionalConfigProps = authProvider.getAdditionalConfigProps();
const isUserLoggedIn = authProvider.isUserLoggedIn(req);
const singleConid = authProvider.getSingleConnectionId(req);
@@ -52,12 +50,17 @@ module.exports = {
isDocker: platformInfo.isDocker,
isElectron: platformInfo.isElectron,
isLicenseValid: platformInfo.isLicenseValid,
licenseError: platformInfo.licenseError,
checkedLicense: platformInfo.checkedLicense,
permissions,
login,
...additionalConfigProps,
isLoginForm,
isAdminLoginForm: !!(process.env.STORAGE_DATABASE && process.env.ADMIN_PASSWORD && !process.env.BASIC_AUTH),
// ...additionalConfigProps,
isBasicAuth: !!process.env.BASIC_AUTH,
isAdminLoginForm: !!(
process.env.STORAGE_DATABASE &&
process.env.ADMIN_PASSWORD &&
!process.env.BASIC_AUTH &&
platformInfo.checkedLicense?.type == 'premium'
),
storageDatabase: process.env.STORAGE_DATABASE,
logsFilePath: getLogsFilePath(),
connectionsFilePath: path.join(datadir(), 'connections.jsonl'),

View File

@@ -1,5 +1,8 @@
function checkLicense() {
return null;
return {
status: 'ok',
type: 'community',
};
}
module.exports = {

View File

@@ -13,8 +13,7 @@ const isDocker = fs.existsSync('/home/dbgate-docker/public');
const isDevMode = process.env.DEVMODE == '1';
const isNpmDist = !!global['IS_NPM_DIST'];
const isForkedApi = processArgs.isForkedApi;
const licenseError = checkLicense();
const isLicenseValid = licenseError == null;
const checkedLicense = checkLicense();
// function moduleAvailable(name) {
// try {
@@ -33,8 +32,8 @@ const platformInfo = {
isElectronBundle: isElectron() && !isDevMode,
isForkedApi,
isElectron: isElectron(),
isLicenseValid,
licenseError,
checkedLicense,
isLicenseValid: checkedLicense?.status == 'ok',
isDevMode,
isNpmDist,
isSnap: process.env.ELECTRON_SNAP == 'true',