diff --git a/hooks/useConfig.js b/hooks/useConfig.js index 8adedcaf..678b6d1c 100644 --- a/hooks/useConfig.js +++ b/hooks/useConfig.js @@ -2,7 +2,7 @@ import { useEffect } from 'react'; import useStore, { setConfig } from 'store/app'; import useApi from 'hooks/useApi'; -let fetched = false; +let loading = false; export default function useConfig() { const { config } = useStore(); @@ -10,12 +10,13 @@ export default function useConfig() { async function loadConfig() { const { data } = await get('/config'); + loading = false; setConfig(data); } useEffect(() => { - if (!config && !fetched) { - fetched = true; + if (!config && !loading) { + loading = true; loadConfig(); } }, []); diff --git a/lib/auth.js b/lib/auth.js index 93027544..25985168 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -1,22 +1,26 @@ import { parseSecureToken, parseToken } from 'next-basics'; import { getAccount, getWebsite } from 'queries'; +import debug from 'debug'; import { SHARE_TOKEN_HEADER, TYPE_ACCOUNT, TYPE_WEBSITE } from 'lib/constants'; import { secret } from 'lib/crypto'; -export function getAuthToken(req) { +const log = debug('umami:auth'); + +export function parseAuthToken(req) { try { const token = req.headers.authorization; - return parseSecureToken(token.split(' ')[1], secret()); - } catch { + } catch (e) { + log(e); return null; } } -export function getShareToken(req) { +export function parseShareToken(req) { try { return parseToken(req.headers[SHARE_TOKEN_HEADER], secret()); - } catch { + } catch (e) { + log(e); return null; } } @@ -29,6 +33,7 @@ export function isValidToken(token, validation) { return validation(token); } } catch (e) { + log(e); return false; } diff --git a/lib/crypto.js b/lib/crypto.js index 74470549..ceb8aa99 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -9,11 +9,11 @@ export function secret() { export function salt() { const ROTATING_SALT = hash(startOfMonth(new Date()).toUTCString()); - return hash([secret(), ROTATING_SALT]); + return hash(secret(), ROTATING_SALT); } export function uuid(...args) { if (!args.length) return v4(); - return v5(hash([...args, salt()]), v5.DNS); + return v5(hash(...args, salt()), v5.DNS); } diff --git a/lib/middleware.js b/lib/middleware.js index 8189ea66..d42823fa 100644 --- a/lib/middleware.js +++ b/lib/middleware.js @@ -1,7 +1,7 @@ import { createMiddleware, unauthorized, badRequest, serverError } from 'next-basics'; import cors from 'cors'; import { getSession } from './session'; -import { getAuthToken, getShareToken } from './auth'; +import { parseAuthToken, parseShareToken } from './auth'; export const useCors = createMiddleware(cors()); @@ -26,8 +26,8 @@ export const useSession = createMiddleware(async (req, res, next) => { }); export const useAuth = createMiddleware(async (req, res, next) => { - const token = await getAuthToken(req); - const shareToken = await getShareToken(req); + const token = await parseAuthToken(req); + const shareToken = await parseShareToken(req); if (!token && !shareToken) { return unauthorized(res); diff --git a/package.json b/package.json index aad3b913..e27b1f61 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "maxmind": "^4.3.6", "moment-timezone": "^0.5.35", "next": "^12.3.1", - "next-basics": "^0.18.0", + "next-basics": "^0.20.0", "node-fetch": "^3.2.8", "npm-run-all": "^4.1.5", "prop-types": "^15.7.2", diff --git a/pages/_app.js b/pages/_app.js index 0d942f9d..c3617a08 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -2,34 +2,27 @@ import Head from 'next/head'; import { useRouter } from 'next/router'; import { IntlProvider } from 'react-intl'; import useLocale from 'hooks/useLocale'; +import useConfig from 'hooks/useConfig'; import 'styles/variables.css'; import 'styles/bootstrap-grid.css'; import 'styles/index.css'; import '@fontsource/inter/400.css'; import '@fontsource/inter/600.css'; -const Intl = ({ children }) => { - const { locale, messages } = useLocale(); - - const Wrapper = ({ children }) => {children}; - - return ( - - {children} - - ); -}; - export default function App({ Component, pageProps }) { + const { locale, messages } = useLocale(); const { basePath } = useRouter(); const { dir } = useLocale(); + useConfig(); + + const Wrapper = ({ children }) => {children}; if (process.env.uiDisabled) { return null; } return ( - + @@ -45,6 +38,6 @@ export default function App({ Component, pageProps }) {
-
+ ); } diff --git a/pages/sso.js b/pages/sso.js new file mode 100644 index 00000000..c2c337ab --- /dev/null +++ b/pages/sso.js @@ -0,0 +1,38 @@ +import { useEffect } from 'react'; +import debug from 'debug'; +import { useRouter } from 'next/router'; +import { setItem } from 'next-basics'; +import { AUTH_TOKEN } from 'lib/constants'; +import useApi from 'hooks/useApi'; +import { setUser } from 'store/app'; + +const log = debug('umami:sso'); + +export default function SingleSignOnPage() { + const router = useRouter(); + const { get } = useApi(); + const { token, url } = router.query; + + useEffect(() => { + async function verify() { + setItem(AUTH_TOKEN, token); + + const { ok, data } = await get('/auth/verify'); + + if (ok) { + log(data); + setUser(data); + + if (url) { + await router.push(url); + } + } + } + + if (token) { + verify(); + } + }, [token]); + + return null; +} diff --git a/yarn.lock b/yarn.lock index ef95aaec..5aa6d841 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5244,10 +5244,10 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -next-basics@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/next-basics/-/next-basics-0.18.0.tgz#7683ec67d562fb57a6f3fb346c989802157450d1" - integrity sha512-KJZjAHahQ++YYaSPuJVAY0wH9QYXVq85ZUGW5mBMq+qDfL8ZVG4nTWc8GhuI8EYLLR+oZp/eInvoqYgiW/dbhg== +next-basics@^0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/next-basics/-/next-basics-0.20.0.tgz#f88791dcc538438b5044695e37d58b4fdccc6dd8" + integrity sha512-KPqVVSzkKUvu9shvZt5Bp7Xv1nZ2xJRRqwqQ+a6a5JjsdE10Q3p07VLrT2ykl+v/CvR4sz98c0n+MaWpgO3Ckw== dependencies: base-x "^4.0.0" bcryptjs "^2.4.3"