mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-23 02:16:02 +00:00
multiauth WIP
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
const { getTokenSecret, getTokenLifetime } = require('./authCommon');
|
const { getTokenSecret, getTokenLifetime } = require('./authCommon');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
const { getLogger } = require('dbgate-tools');
|
const { getLogger, getPredefinedPermissions } = require('dbgate-tools');
|
||||||
|
|
||||||
const AD = require('activedirectory2').promiseWrapper;
|
const AD = require('activedirectory2').promiseWrapper;
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
@@ -12,7 +12,15 @@ class AuthProviderBase {
|
|||||||
amoid = 'none';
|
amoid = 'none';
|
||||||
|
|
||||||
async login(login, password, options = undefined) {
|
async login(login, password, options = undefined) {
|
||||||
return {};
|
return {
|
||||||
|
accessToken: jwt.sign(
|
||||||
|
{
|
||||||
|
amoid: this.amoid,
|
||||||
|
},
|
||||||
|
getTokenSecret(),
|
||||||
|
{ expiresIn: getTokenLifetime() }
|
||||||
|
),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldAuthorizeApi() {
|
shouldAuthorizeApi() {
|
||||||
@@ -57,6 +65,7 @@ class AuthProviderBase {
|
|||||||
toJson() {
|
toJson() {
|
||||||
return {
|
return {
|
||||||
amoid: this.amoid,
|
amoid: this.amoid,
|
||||||
|
workflowType: 'anonymous',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,12 +136,19 @@ class OAuthProvider extends AuthProviderBase {
|
|||||||
oauthLogout: process.env.OAUTH_LOGOUT,
|
oauthLogout: process.env.OAUTH_LOGOUT,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
...super.toJson(),
|
||||||
|
workflowType: 'redirect',
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ADProvider extends AuthProviderBase {
|
class ADProvider extends AuthProviderBase {
|
||||||
amoid = 'ad';
|
amoid = 'ad';
|
||||||
|
|
||||||
async login(login, password) {
|
async login(login, password, options = undefined) {
|
||||||
const adConfig = {
|
const adConfig = {
|
||||||
url: process.env.AD_URL,
|
url: process.env.AD_URL,
|
||||||
baseDN: process.env.AD_BASEDN,
|
baseDN: process.env.AD_BASEDN,
|
||||||
@@ -152,7 +168,14 @@ class ADProvider extends AuthProviderBase {
|
|||||||
return { error: `Username ${login} not allowed to log in` };
|
return { error: `Username ${login} not allowed to log in` };
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
accessToken: jwt.sign({ login }, getTokenSecret(), { expiresIn: getTokenLifetime() }),
|
accessToken: jwt.sign(
|
||||||
|
{
|
||||||
|
amoid: this.amoid,
|
||||||
|
login,
|
||||||
|
},
|
||||||
|
getTokenSecret(),
|
||||||
|
{ expiresIn: getTokenLifetime() }
|
||||||
|
),
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return { error: 'Login failed' };
|
return { error: 'Login failed' };
|
||||||
@@ -166,15 +189,29 @@ class ADProvider extends AuthProviderBase {
|
|||||||
isLoginForm() {
|
isLoginForm() {
|
||||||
return !process.env.BASIC_AUTH;
|
return !process.env.BASIC_AUTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
...super.toJson(),
|
||||||
|
workflowType: 'credentials',
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoginsProvider extends AuthProviderBase {
|
class LoginsProvider extends AuthProviderBase {
|
||||||
amoid = 'logins';
|
amoid = 'logins';
|
||||||
|
|
||||||
async login(login, password) {
|
async login(login, password, options = undefined) {
|
||||||
if (password == process.env[`LOGIN_PASSWORD_${login}`]) {
|
if (password == process.env[`LOGIN_PASSWORD_${login}`]) {
|
||||||
return {
|
return {
|
||||||
accessToken: jwt.sign({ login }, getTokenSecret(), { expiresIn: getTokenLifetime() }),
|
accessToken: jwt.sign(
|
||||||
|
{
|
||||||
|
amoid: this.amoid,
|
||||||
|
login,
|
||||||
|
},
|
||||||
|
getTokenSecret(),
|
||||||
|
{ expiresIn: getTokenLifetime() }
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return { error: 'Invalid credentials' };
|
return { error: 'Invalid credentials' };
|
||||||
@@ -187,6 +224,13 @@ class LoginsProvider extends AuthProviderBase {
|
|||||||
isLoginForm() {
|
isLoginForm() {
|
||||||
return !process.env.BASIC_AUTH;
|
return !process.env.BASIC_AUTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
...super.toJson(),
|
||||||
|
workflowType: 'credentials',
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DenyAllProvider extends AuthProviderBase {
|
class DenyAllProvider extends AuthProviderBase {
|
||||||
@@ -196,9 +240,16 @@ class DenyAllProvider extends AuthProviderBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async login(login, password) {
|
async login(login, password, options = undefined) {
|
||||||
return { error: 'Login not allowed' };
|
return { error: 'Login not allowed' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
...super.toJson(),
|
||||||
|
workflowType: 'credentials',
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasEnvLogins() {
|
function hasEnvLogins() {
|
||||||
|
|||||||
@@ -30,6 +30,9 @@
|
|||||||
|
|
||||||
$: selectedConnection = availableConnections?.find(x => x.conid == $values.databaseServer);
|
$: selectedConnection = availableConnections?.find(x => x.conid == $values.databaseServer);
|
||||||
|
|
||||||
|
$: selectedProvider = availableProviders?.find(x => x.amoid == $values.amoid);
|
||||||
|
$: workflowType = selectedProvider?.workflowType ?? 'credentials';
|
||||||
|
|
||||||
async function loadAvailableServers(amoid) {
|
async function loadAvailableServers(amoid) {
|
||||||
if (amoid) {
|
if (amoid) {
|
||||||
availableConnections = await apiCall('storage/get-connections-for-login-page', { amoid });
|
availableConnections = await apiCall('storage/get-connections-for-login-page', { amoid });
|
||||||
@@ -80,7 +83,7 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if !isAdminPage && availableConnections}
|
{#if !isAdminPage && availableConnections && workflowType == 'database'}
|
||||||
<FormSelectField
|
<FormSelectField
|
||||||
label="Database server"
|
label="Database server"
|
||||||
name="databaseServer"
|
name="databaseServer"
|
||||||
@@ -97,10 +100,12 @@
|
|||||||
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
|
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
{#if !isAdminPage}
|
{#if !isAdminPage && workflowType == 'credentials'}
|
||||||
<FormTextField label="Username" name="login" autocomplete="username" saveOnInput />
|
<FormTextField label="Username" name="login" autocomplete="username" saveOnInput />
|
||||||
{/if}
|
{/if}
|
||||||
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
|
{#if workflowType == 'credentials'}
|
||||||
|
<FormPasswordField label="Password" name="password" autocomplete="current-password" saveOnInput />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if isAdminPage && $config && !$config.isAdminLoginForm}
|
{#if isAdminPage && $config && !$config.isAdminLoginForm}
|
||||||
@@ -173,31 +178,38 @@
|
|||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<FormSubmit
|
<FormSubmit
|
||||||
value={isAdminPage ? 'Log In as Administrator' : 'Log In'}
|
value={isAdminPage
|
||||||
|
? 'Log In as Administrator'
|
||||||
|
: workflowType == 'redirect'
|
||||||
|
? 'Redirect to login page'
|
||||||
|
: 'Log In'}
|
||||||
on:click={async e => {
|
on:click={async e => {
|
||||||
enableApi();
|
enableApi();
|
||||||
const resp = await apiCall('auth/login', {
|
|
||||||
amoid: $values.amoid,
|
if (isAdminPage || workflowType == 'credentials' || workflowType == 'anonymous') {
|
||||||
isAdminPage,
|
const resp = await apiCall('auth/login', {
|
||||||
...e.detail,
|
amoid: $values.amoid,
|
||||||
});
|
isAdminPage,
|
||||||
if (resp.error) {
|
...e.detail,
|
||||||
internalRedirectTo(
|
});
|
||||||
`/?page=not-logged&error=${encodeURIComponent(resp.error)}&is-admin=${isAdminPage ? 'true' : ''}`
|
if (resp.error) {
|
||||||
);
|
internalRedirectTo(
|
||||||
return;
|
`/?page=not-logged&error=${encodeURIComponent(resp.error)}&is-admin=${isAdminPage ? 'true' : ''}`
|
||||||
}
|
);
|
||||||
const { accessToken } = resp;
|
return;
|
||||||
if (accessToken) {
|
|
||||||
localStorage.setItem(isAdminPage ? 'adminAccessToken' : 'accessToken', accessToken);
|
|
||||||
if (isAdminPage) {
|
|
||||||
internalRedirectTo('/?page=admin');
|
|
||||||
} else {
|
|
||||||
internalRedirectTo('/');
|
|
||||||
}
|
}
|
||||||
return;
|
const { accessToken } = resp;
|
||||||
|
if (accessToken) {
|
||||||
|
localStorage.setItem(isAdminPage ? 'adminAccessToken' : 'accessToken', accessToken);
|
||||||
|
if (isAdminPage) {
|
||||||
|
internalRedirectTo('/?page=admin');
|
||||||
|
} else {
|
||||||
|
internalRedirectTo('/');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
internalRedirectTo(`/?page=not-logged`);
|
||||||
}
|
}
|
||||||
internalRedirectTo(`/?page=not-logged`);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user