From 2ef397112cc1f189fd813677b5b2e1d61976c985 Mon Sep 17 00:00:00 2001 From: lelemm Date: Fri, 20 Dec 2024 11:28:25 -0300 Subject: [PATCH] Added command lines to enable/disable openid from console (#527) * Added command lines to enable/disable openid * md * Update src/scripts/disable-openid.js Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * changed error codes based on code rabbit review * fix for github auth * code review --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- package.json | 2 ++ src/account-db.js | 22 +++++++++++++-- src/accounts/openid.js | 21 ++++++++++---- src/config-types.ts | 1 + src/scripts/disable-openid.js | 44 +++++++++++++++++++++++++++++ src/scripts/enable-openid.js | 53 +++++++++++++++++++++++++++++++++++ upcoming-release-notes/527.md | 6 ++++ 7 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 src/scripts/disable-openid.js create mode 100644 src/scripts/enable-openid.js create mode 100644 upcoming-release-notes/527.md diff --git a/package.json b/package.json index 3f569ba6a..1cbef61fa 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "types": "tsc --noEmit --incremental", "verify": "yarn lint && yarn types", "reset-password": "node src/scripts/reset-password.js", + "enable-openid": "node src/scripts/enable-openid.js", + "disable-openid": "node src/scripts/disable-openid.js", "health-check": "node src/scripts/health-check.js" }, "dependencies": { diff --git a/src/account-db.js b/src/account-db.js index c8c30bf0b..c7fff76ed 100644 --- a/src/account-db.js +++ b/src/account-db.js @@ -169,9 +169,25 @@ export async function disableOpenID(loginSettings) { return { error }; } - getAccountDb().mutate('DELETE FROM sessions'); - getAccountDb().mutate('DELETE FROM users WHERE user_name <> ?', ['']); - getAccountDb().mutate('DELETE FROM auth WHERE method = ?', ['openid']); + try { + accountDb.transaction(() => { + accountDb.mutate('DELETE FROM sessions'); + accountDb.mutate( + `DELETE FROM user_access + WHERE user_access.user_id IN ( + SELECT users.id + FROM users + WHERE users.user_name <> ? + );`, + [''], + ); + accountDb.mutate('DELETE FROM users WHERE user_name <> ?', ['']); + accountDb.mutate('DELETE FROM auth WHERE method = ?', ['openid']); + }); + } catch (err) { + console.error('Error cleaning up openid information:', err); + return { error: 'database-error' }; + } } export function getSession(token) { diff --git a/src/accounts/openid.js b/src/accounts/openid.js index cd1a80f7b..2080a3bcb 100644 --- a/src/accounts/openid.js +++ b/src/accounts/openid.js @@ -170,11 +170,22 @@ export async function loginWithOpenIdFinalize(body) { let { code_verifier, return_url } = pendingRequest; try { - const params = { code: body.code, state: body.state }; - let tokenSet = await client.callback(client.redirect_uris[0], params, { - code_verifier, - state: body.state, - }); + let tokenSet = null; + + if (!config.authMethod || config.authMethod === 'openid') { + const params = { code: body.code, state: body.state }; + tokenSet = await client.callback(client.redirect_uris[0], params, { + code_verifier, + state: body.state, + }); + } else { + tokenSet = await client.grant({ + grant_type: 'authorization_code', + code: body.code, + redirect_uri: client.redirect_uris[0], + code_verifier, + }); + } const userInfo = await client.userinfo(tokenSet.access_token); const identity = userInfo.preferred_username ?? diff --git a/src/config-types.ts b/src/config-types.ts index 778982d59..3feecc9ec 100644 --- a/src/config-types.ts +++ b/src/config-types.ts @@ -32,6 +32,7 @@ export interface Config { client_id: string; client_secret: string; server_hostname: string; + authMethod?: 'openid' | 'oauth2'; }; multiuser: boolean; token_expiration?: 'never' | 'openid-provider' | number; diff --git a/src/scripts/disable-openid.js b/src/scripts/disable-openid.js new file mode 100644 index 000000000..b736b3999 --- /dev/null +++ b/src/scripts/disable-openid.js @@ -0,0 +1,44 @@ +import { + disableOpenID, + getActiveLoginMethod, + needsBootstrap, +} from '../account-db.js'; +import { promptPassword } from '../util/prompt.js'; + +if (needsBootstrap()) { + console.log('System needs to be bootstrapped first. OpenID is not enabled.'); + + process.exit(1); +} else { + console.log('To disable OpenID, you have to enter your server password:'); + try { + const loginMethod = getActiveLoginMethod(); + console.log(`Current login method: ${loginMethod}`); + + if (loginMethod === 'password') { + console.log('OpenID already disabled.'); + process.exit(0); + } + + const password = await promptPassword(); + const { error } = (await disableOpenID({ password })) || {}; + + if (error) { + console.log('Error disabling OpenID:', error); + console.log( + 'Please report this as an issue: https://github.com/actualbudget/actual-server/issues', + ); + process.exit(2); + } + console.log('OpenID disabled!'); + console.log( + 'Note: you will need to log in with the password on any browsers or devices that are currently logged in.', + ); + } catch (err) { + console.log('Unexpected error:', err); + console.log( + 'Please report this as an issue: https://github.com/actualbudget/actual-server/issues', + ); + process.exit(2); + } +} diff --git a/src/scripts/enable-openid.js b/src/scripts/enable-openid.js new file mode 100644 index 000000000..caf782ff1 --- /dev/null +++ b/src/scripts/enable-openid.js @@ -0,0 +1,53 @@ +import { + enableOpenID, + getActiveLoginMethod, + needsBootstrap, +} from '../account-db.js'; +import finalConfig from '../load-config.js'; + +if (needsBootstrap()) { + console.log( + 'It looks like you don’t have a password set yet. Password is the fallback authentication method when using OpenID. Execute the command reset-password before using this command!', + ); + + process.exit(1); +} else { + console.log('Enabling openid based on Environment variables or config.json'); + try { + const loginMethod = getActiveLoginMethod(); + console.log(`Current login method: ${loginMethod}`); + + if (loginMethod === 'openid') { + console.log('OpenID already enabled.'); + process.exit(0); + } + const { error } = (await enableOpenID(finalConfig)) || {}; + + if (error) { + console.log('Error enabling openid:', error); + if (error === 'invalid-login-settings') { + console.log( + 'Error configuring OpenID. Please verify that the configuration file or environment variables are correct.', + ); + + process.exit(1); + } else { + console.log( + 'Please report this as an issue: https://github.com/actualbudget/actual-server/issues', + ); + + process.exit(2); + } + } + console.log('OpenID enabled!'); + console.log( + 'Note: The first user to login with OpenID will be the owner of the server.', + ); + } catch (err) { + console.log('Unexpected error:', err); + console.log( + 'Please report this as an issue: https://github.com/actualbudget/actual-server/issues', + ); + process.exit(2); + } +} diff --git a/upcoming-release-notes/527.md b/upcoming-release-notes/527.md new file mode 100644 index 000000000..575328f07 --- /dev/null +++ b/upcoming-release-notes/527.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [lelemm] +--- + +Commands to enable/disable OpenID from console. Also, enabling to login with oauth2 (for github).