Documentation changes
This commit is contained in:
parent
2724c77b55
commit
fb382e55e9
16
README.md
16
README.md
@ -2,14 +2,20 @@
|
|||||||
|
|
||||||
This is a SvelteKit-powered authentication service.
|
This is a SvelteKit-powered authentication service.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
1. A MySQL or MariaDB database.
|
||||||
|
2. Node.js 20+ or Docker.
|
||||||
|
|
||||||
## Set up
|
## Set up
|
||||||
|
|
||||||
1. Install dependenices - `npm install`.
|
1. Clone the repository.
|
||||||
2. Configure the environment - `cp .env.example .env`.
|
2. Install dependenices - `npm install`.
|
||||||
3. Generate secrets and stuff:
|
3. Configure the environment - `cp .env.example .env`.
|
||||||
|
4. Generate secrets and stuff:
|
||||||
1. Session secret - `node -e 'console.log(require("crypto").randomBytes(16).toString("hex"))'`.
|
1. Session secret - `node -e 'console.log(require("crypto").randomBytes(16).toString("hex"))'`.
|
||||||
2. Challenge secret - `node -e 'console.log(require("crypto").randomBytes(32).toString("hex"))'`.
|
2. Challenge secret - `node -e 'console.log(require("crypto").randomBytes(32).toString("hex"))'`.
|
||||||
3. Generate JWT keys in the `private` directory - `openssl genpkey -out jwt.private.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048`.
|
3. Generate JWT keys in the `private` directory - `openssl genpkey -out jwt.private.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048`.
|
||||||
4. Also make the public key - `openssl rsa -in jwt.private.pem -pubout -outform PEM -out jwt.public.pem`.
|
4. Also make the public key - `openssl rsa -in jwt.private.pem -pubout -outform PEM -out jwt.public.pem`.
|
||||||
4. Build the application - `npm run build`.
|
5. Build the application - `npm run build`.
|
||||||
5. Run the application - `node -r dotenv/config build`.
|
6. Run the application - `node -r dotenv/config build`.
|
||||||
|
@ -11,19 +11,26 @@ import { handleSession } from 'svelte-kit-cookie-session';
|
|||||||
|
|
||||||
const { AUTO_MIGRATE, SESSION_SECRET, SESSION_SECURE } = env;
|
const { AUTO_MIGRATE, SESSION_SECRET, SESSION_SECURE } = env;
|
||||||
|
|
||||||
|
// Initialize the database
|
||||||
await DB.init();
|
await DB.init();
|
||||||
|
|
||||||
|
// Initialize the JWT keys
|
||||||
await JWT.init();
|
await JWT.init();
|
||||||
|
|
||||||
|
// Migrate the database when automatic migration is enabled
|
||||||
if (AUTO_MIGRATE === 'true') {
|
if (AUTO_MIGRATE === 'true') {
|
||||||
await migrate(DB.drizzle, { migrationsFolder: './migrations' });
|
await migrate(DB.drizzle, { migrationsFolder: './migrations' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run database data seeders
|
||||||
await runSeeds();
|
await runSeeds();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the document theme mode from the cookies
|
||||||
|
*/
|
||||||
const handleThemeHook = (async ({ resolve, event }) => {
|
const handleThemeHook = (async ({ resolve, event }) => {
|
||||||
// Take the theme from the cookies
|
// Take the theme from the cookies
|
||||||
const cookieTheme = event.cookies.get('themeMode') as ThemeModeType;
|
const cookieTheme = event.cookies.get('themeMode') as ThemeModeType;
|
||||||
|
|
||||||
if (cookieTheme) {
|
if (cookieTheme) {
|
||||||
return await resolve(event, {
|
return await resolve(event, {
|
||||||
transformPageChunk: ({ html }) => html.replace('theme-base=""', `theme-base="${cookieTheme}"`)
|
transformPageChunk: ({ html }) => html.replace('theme-base=""', `theme-base="${cookieTheme}"`)
|
||||||
|
@ -26,14 +26,21 @@ export class JWT {
|
|||||||
static jwksKid: string;
|
static jwksKid: string;
|
||||||
|
|
||||||
static async init() {
|
static async init() {
|
||||||
|
try {
|
||||||
const privateKeyFile = await readFile(join('private', 'jwt.private.pem'), {
|
const privateKeyFile = await readFile(join('private', 'jwt.private.pem'), {
|
||||||
encoding: 'utf-8'
|
encoding: 'utf-8'
|
||||||
});
|
});
|
||||||
const publicKeyFile = await readFile(join('private', 'jwt.public.pem'), { encoding: 'utf-8' });
|
const publicKeyFile = await readFile(join('private', 'jwt.public.pem'), {
|
||||||
|
encoding: 'utf-8'
|
||||||
|
});
|
||||||
JWT.privateKey = await importPKCS8(privateKeyFile, JWT_ALGORITHM);
|
JWT.privateKey = await importPKCS8(privateKeyFile, JWT_ALGORITHM);
|
||||||
JWT.publicKey = await importSPKI(publicKeyFile, JWT_ALGORITHM);
|
JWT.publicKey = await importSPKI(publicKeyFile, JWT_ALGORITHM);
|
||||||
JWT.jwks = await exportJWK(JWT.publicKey);
|
JWT.jwks = await exportJWK(JWT.publicKey);
|
||||||
JWT.jwksKid = uuidv4({ random: Buffer.from(JWT.jwks.n as string).subarray(0, 16) });
|
JWT.jwksKid = uuidv4({ random: Buffer.from(JWT.jwks.n as string).subarray(0, 16) });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to initialize the JWT backend:', error);
|
||||||
|
console.error('OpenID Connect flows will not work!');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async issue(claims: Record<string, unknown>, subject: string, audience?: string) {
|
static async issue(claims: Record<string, unknown>, subject: string, audience?: string) {
|
||||||
|
@ -18,25 +18,31 @@ export const themeMode = writable<ThemeModeType>('light', (set) => {
|
|||||||
export const setThemeCookie = (theme: ThemeModeType) =>
|
export const setThemeCookie = (theme: ThemeModeType) =>
|
||||||
(document.cookie = `themeMode=${theme}; path=/; SameSite=Lax; Max-Age=${THEME_COOKIE_MAX_AGE}`);
|
(document.cookie = `themeMode=${theme}; path=/; SameSite=Lax; Max-Age=${THEME_COOKIE_MAX_AGE}`);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forward the initial theme to the theme store, and subscribe to changes.
|
||||||
|
*/
|
||||||
export const forwardInitialTheme = () =>
|
export const forwardInitialTheme = () =>
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
// If a cookie-set theme is not present, set the theme to current user agent theme.
|
// If a cookie-set theme is not present, set the theme to current user agent theme.
|
||||||
const hasServerTheme = !!document.documentElement.getAttribute('theme-base');
|
const hasServerTheme = !!document.documentElement.getAttribute('theme-base');
|
||||||
const uaTheme = window?.matchMedia?.('(prefers-color-scheme: dark)');
|
const uaTheme = window?.matchMedia?.('(prefers-color-scheme: dark)');
|
||||||
const uaMode: ThemeModeType = uaTheme?.matches ? 'dark' : 'light';
|
const uaMode: ThemeModeType = uaTheme?.matches ? 'dark' : 'light';
|
||||||
const uaSetter = () => {
|
|
||||||
themeMode.set(uaTheme?.matches ? 'dark' : 'light');
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!hasServerTheme) {
|
if (!hasServerTheme) {
|
||||||
themeMode.set(uaMode);
|
themeMode.set(uaMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the theme to the current theme store value, and set the cookie.
|
||||||
const unsubscribeForward = themeMode.subscribe(async (theme) => {
|
const unsubscribeForward = themeMode.subscribe(async (theme) => {
|
||||||
document.documentElement.setAttribute('theme-base', theme);
|
document.documentElement.setAttribute('theme-base', theme);
|
||||||
setThemeCookie(theme);
|
setThemeCookie(theme);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set the theme to the user agent theme when the user agent theme changes.
|
||||||
|
const uaSetter = () => {
|
||||||
|
themeMode.set(uaTheme?.matches ? 'dark' : 'light');
|
||||||
|
};
|
||||||
|
|
||||||
uaTheme?.addEventListener?.('change', uaSetter);
|
uaTheme?.addEventListener?.('change', uaSetter);
|
||||||
return () => {
|
return () => {
|
||||||
unsubscribeForward();
|
unsubscribeForward();
|
||||||
|
Loading…
Reference in New Issue
Block a user