chore: 🔧 add no auth and logout url

This commit is contained in:
Anthony Potdevin 2020-12-15 22:45:57 +01:00
parent 4c39f79cb3
commit 1dcea164d5
No known key found for this signature in database
GPG key ID: 4403F1DFBE779457
9 changed files with 80 additions and 19 deletions

2
.env
View file

@ -39,3 +39,5 @@
# SSO_SERVER_URL='127.0.0.1:10009'
# SSO_CERT_PATH='/path/to/certificate/tls.cert'
# SSO_MACAROON_PATH='/path/to/folder/containing/macaroons'
# DANGEROUS_NO_SSO_AUTH=false
# LOGOUT_URL='http://thunderhub.io'

View file

@ -138,10 +138,11 @@ You can define an account to work with SSO cookie authentication by adding the f
# -----------
# SSO Account Configs
# -----------
COOKIE_PATH = '/path/to/cookie/file/.cookie'; # i.e. '/data/.cookie'
SSO_SERVER_URL = 'url and port to node'; # i.e. '127.0.0.1:10009'
SSO_CERT_PATH = '/path/to/tls/certificate'; # i.e. '\lnd\alice\tls.cert'
SSO_MACAROON_PATH = '/path/to/macaroon/folder'; # i.e. '\lnd\alice\data\chain\bitcoin\regtest\'
COOKIE_PATH = '/path/to/cookie/file/.cookie' # i.e. '/data/.cookie'
SSO_SERVER_URL = 'url and port to node' # i.e. '127.0.0.1:10009'
SSO_CERT_PATH = '/path/to/tls/certificate' # i.e. '\lnd\alice\tls.cert'
SSO_MACAROON_PATH = '/path/to/macaroon/folder' # i.e. '\lnd\alice\data\chain\bitcoin\regtest\'
LOGOUT_URL = 'http://LogoutToThisUrl.com' # If not set it will logout to "/login"
```
To login to this account you must add the cookie file content to the end of your ThunderHub url. For example:
@ -152,6 +153,30 @@ http://localhost:3000/sso?token=[COOKIE]
Replace `[COOKIE]` with the contents of the `.cookie` file.
### SSO Account without authentication
You can DANGEROUSLY remove SSO authentication. This is useful for example if you plan on running ThunderHub **only** on your local network or through TOR.
**DO NOT enable this option if your ThunderHub instance is available on the internet or your funds will probably be lost.**
The configuration for a non authenticated SSO account would look like this:
```bash
# -----------
# SSO Account Configs
# -----------
SSO_SERVER_URL = 'url and port to node'; # i.e. '127.0.0.1:10009'
SSO_CERT_PATH = '/path/to/tls/certificate'; # i.e. '\lnd\alice\tls.cert'
SSO_MACAROON_PATH = '/path/to/macaroon/folder'; # i.e. '\lnd\alice\data\chain\bitcoin\regtest\'
DANGEROUS_NO_SSO_AUTH = 'true' # Default: false
```
To login to this account go to the following url:
```
http://localhost:3000/sso?token=1
```
### Server Accounts
You can add accounts on the server by adding this parameter to the `.env` file:

View file

@ -14,6 +14,8 @@ module.exports = withBundleAnalyzer({
lnCertPath: process.env.SSO_CERT_PATH || '',
macaroonPath: process.env.SSO_MACAROON_PATH || '',
accountConfigPath: process.env.ACCOUNT_CONFIG_PATH || '',
dangerousNoSSOAuth:
process.env.DANGEROUS_NO_SSO_AUTH === 'true' ? true : false,
},
publicRuntimeConfig: {
nodeEnv: process.env.NODE_ENV || 'development',
@ -28,5 +30,6 @@ module.exports = withBundleAnalyzer({
disableLinks: process.env.DISABLE_LINKS === 'true' ? true : false,
disableLnMarkets: process.env.DISABLE_LNMARKETS === 'true' ? true : false,
noVersionCheck: process.env.NO_VERSION_CHECK === 'true' ? true : false,
logoutUrl: process.env.LOGOUT_URL || '',
},
});

View file

@ -12,7 +12,7 @@ import { toWithError } from 'server/helpers/async';
import { decodeMacaroon, isCorrectPassword } from 'server/helpers/crypto';
const { serverRuntimeConfig } = getConfig() || {};
const { cookiePath, nodeEnv } = serverRuntimeConfig || {};
const { cookiePath, nodeEnv, dangerousNoSSOAuth } = serverRuntimeConfig || {};
export const authResolvers = {
Mutation: {
@ -33,22 +33,32 @@ export const authResolvers = {
return false;
}
if (!cookie) {
return false;
}
if (dangerousNoSSOAuth) {
logger.warn(
'SSO authentication is disabled. Make sure this is what you want.'
);
} else {
// No cookie or cookiePath needed when SSO authentication is turned off
if (!cookie) {
return false;
}
if (cookiePath === '') {
logger.warn('SSO auth not available since no cookie path was provided');
return false;
if (cookiePath === '') {
logger.warn(
'SSO auth not available since no cookie path was provided'
);
return false;
}
}
const cookieFile = readCookie(cookiePath);
if (
(cookieFile && cookieFile.trim() === cookie.trim()) ||
nodeEnv === 'development'
nodeEnv === 'development' ||
dangerousNoSSOAuth
) {
refreshCookie(cookiePath);
cookiePath && refreshCookie(cookiePath);
const { lnd } = authenticatedLndGrpc(sso);
const [, error] = await toWithError<GetWalletInfoType>(

View file

@ -4,8 +4,12 @@ import { appendBasePath } from 'src/utils/basePath';
import { getUrlParam } from 'src/utils/url';
import { toast } from 'react-toastify';
import { getErrorContent } from 'src/utils/error';
import getConfig from 'next/config';
import { useGetAuthTokenMutation } from 'src/graphql/mutations/__generated__/getAuthToken.generated';
const { publicRuntimeConfig } = getConfig();
const { logoutUrl } = publicRuntimeConfig;
export const ServerAccounts: React.FC = () => {
const { push, query } = useRouter();
@ -16,7 +20,7 @@ export const ServerAccounts: React.FC = () => {
refetchQueries: ['GetNodeInfo'],
onError: error => {
toast.error(getErrorContent(error));
push(appendBasePath('/login'));
push(logoutUrl || appendBasePath('/login'));
},
});
@ -24,7 +28,7 @@ export const ServerAccounts: React.FC = () => {
if (cookieParam) {
getToken();
} else {
push(appendBasePath('/login'));
push(logoutUrl || appendBasePath('/login'));
}
}, [cookieParam, push, getToken]);

View file

@ -7,9 +7,13 @@ import { HeaderNavButton } from 'src/layouts/header/Header.styled';
import styled from 'styled-components';
import { themeColors } from 'src/styles/Themes';
import ScaleLoader from 'react-spinners/ScaleLoader';
import getConfig from 'next/config';
import { appendBasePath } from '../../utils/basePath';
import { useChatDispatch } from '../../context/ChatContext';
const { publicRuntimeConfig } = getConfig();
const { logoutUrl } = publicRuntimeConfig;
const Logout = styled.button`
cursor: pointer;
text-decoration: none;
@ -33,7 +37,8 @@ export const LogoutButton = () => {
if (data && data.logout) {
dispatchChat({ type: 'disconnected' });
client.clearStore();
push(appendBasePath('/login'));
push(logoutUrl || appendBasePath('/login'));
}
}, [data, dispatchChat, push, client]);

View file

@ -2,8 +2,12 @@ import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { toast } from 'react-toastify';
import { useGetNodeInfoQuery } from 'src/graphql/queries/__generated__/getNodeInfo.generated';
import getConfig from 'next/config';
import { appendBasePath } from '../../utils/basePath';
const { publicRuntimeConfig } = getConfig();
const { logoutUrl } = publicRuntimeConfig;
export const StatusCheck: React.FC = () => {
const { push } = useRouter();
@ -17,7 +21,7 @@ export const StatusCheck: React.FC = () => {
if (error) {
toast.error(`Unable to connect to node`);
stopPolling();
push(appendBasePath('/login'));
push(logoutUrl || appendBasePath('/login'));
}
}, [error, push, stopPolling]);

View file

@ -4,6 +4,10 @@ import { parseCookies } from 'src/utils/cookies';
import { DocumentNode } from 'graphql';
import { appConstants } from 'server/utils/appConstants';
import { GET_AUTH_TOKEN } from 'src/graphql/mutations/getAuthToken';
import getConfig from 'next/config';
const { publicRuntimeConfig } = getConfig();
const { logoutUrl } = publicRuntimeConfig;
const cookieProps = (
context: NextPageContext,
@ -17,7 +21,7 @@ const cookieProps = (
const hasToken = !!cookies[appConstants.tokenCookieName];
if (!cookies[appConstants.cookieName] && !noAuth) {
context.res?.writeHead(302, { Location: '/login' });
context.res?.writeHead(302, { Location: logoutUrl || '/login' });
context.res?.end();
return { theme: 'dark', authenticated: false, hasToken };

View file

@ -3,6 +3,7 @@ import styled from 'styled-components';
import { AlertCircle } from 'react-feather';
import { useRouter } from 'next/router';
import { useLogoutMutation } from 'src/graphql/mutations/__generated__/logout.generated';
import getConfig from 'next/config';
import {
Card,
CardWithTitle,
@ -15,6 +16,9 @@ import { ColorButton } from '../../components/buttons/colorButton/ColorButton';
import { appendBasePath } from '../../utils/basePath';
import { useChatDispatch } from '../../context/ChatContext';
const { publicRuntimeConfig } = getConfig();
const { logoutUrl } = publicRuntimeConfig;
export const ButtonRow = styled.div`
width: auto;
display: flex;
@ -56,7 +60,7 @@ export const DangerView = () => {
const { push } = useRouter();
const [logout] = useLogoutMutation({
onCompleted: () => push(appendBasePath('/login')),
onCompleted: () => push(logoutUrl || appendBasePath('/login')),
});
const handleDeleteAll = () => {