Cleand authentication-code up

This commit is contained in:
Mawoka
2022-07-26 22:50:39 +02:00
parent ba79c6a8c1
commit 29bda964b0
7 changed files with 111 additions and 136 deletions
+46
View File
@@ -12,6 +12,9 @@ from fastapi.background import BackgroundTasks
from fastapi.responses import JSONResponse, RedirectResponse, PlainTextResponse from fastapi.responses import JSONResponse, RedirectResponse, PlainTextResponse
from fastapi.security import OAuth2PasswordRequestForm from fastapi.security import OAuth2PasswordRequestForm
import html import html
from jose import jwt, JWTError
from classquiz import oauth from classquiz import oauth
from classquiz.helpers.avatar import gzipped_user_avatar from classquiz.helpers.avatar import gzipped_user_avatar
import base64 import base64
@@ -266,3 +269,46 @@ async def get_other_avatar(respo: Response, user_id: uuid.UUID):
raise HTTPException(status_code=404, detail="User not found") raise HTTPException(status_code=404, detail="User not found")
respo.headers.append("Content-Type", "image/svg+xml") respo.headers.append("Content-Type", "image/svg+xml")
return gzip.decompress(base64.b64decode(user.avatar)) return gzip.decompress(base64.b64decode(user.avatar))
class InternalAuthData(BaseModel):
rememberme: str
jwt: str | None
@router.post("/auth/internal")
async def internal_auth(data: InternalAuthData, resp: Response):
try:
data.jwt = data.jwt.replace("Bearer ", "")
except AttributeError:
pass
if data.jwt is not None:
try:
payload = jwt.decode(data.jwt, settings.secret_key, algorithms=["HS256"])
email: str = payload.get("sub")
if email is None:
resp.status_code = 401
return resp
except JWTError:
resp.status_code = 401
return resp
else:
return await rememberme_check(data.rememberme, resp)
class GetEmailFromJWT(BaseModel):
jwt: str
@router.post("/auth/internal/email")
async def get_email_from_jwt(data: GetEmailFromJWT):
try:
data.jwt = data.jwt.replace("Bearer ", "")
except AttributeError:
pass
try:
payload = jwt.decode(data.jwt, settings.secret_key, algorithms=["HS256"])
return payload.get("sub")
except JWTError as e:
print(e)
raise HTTPException(status_code=401)
+1 -4
View File
@@ -25,11 +25,8 @@ RUN corepack enable && corepack prepare pnpm@7.5.0 --activate && pnpm i
# copy the generated modules and all other files to the container # copy the generated modules and all other files to the container
COPY . . COPY . .
RUN apt update && \
apt install -y redis-server
# build the application # build the application
RUN nohup bash -c "redis-server &" && sleep 4 && pnpm run build RUN pnpm run build
### Serve Step ### Serve Step
# pull the Node.js Docker image # pull the Node.js Docker image
-1
View File
@@ -48,7 +48,6 @@
"felte": "^1.2.2", "felte": "^1.2.2",
"highlight.js": "^11.5.1", "highlight.js": "^11.5.1",
"i18next-browser-languagedetector": "^6.1.4", "i18next-browser-languagedetector": "^6.1.4",
"ioredis": "^5.1.0",
"js-cookie": "^3.0.1", "js-cookie": "^3.0.1",
"luxon": "^2.4.0", "luxon": "^2.4.0",
"mapbox-gl": "^2.9.1", "mapbox-gl": "^2.9.1",
-84
View File
@@ -36,7 +36,6 @@ specifiers:
highlight.js: ^11.5.1 highlight.js: ^11.5.1
i18next: ^21.8.13 i18next: ^21.8.13
i18next-browser-languagedetector: ^6.1.4 i18next-browser-languagedetector: ^6.1.4
ioredis: ^5.1.0
js-cookie: ^3.0.1 js-cookie: ^3.0.1
luxon: ^2.4.0 luxon: ^2.4.0
mapbox-gl: ^2.9.1 mapbox-gl: ^2.9.1
@@ -101,7 +100,6 @@ devDependencies:
felte: 1.2.2_svelte@3.49.0 felte: 1.2.2_svelte@3.49.0
highlight.js: 11.6.0 highlight.js: 11.6.0
i18next-browser-languagedetector: 6.1.4 i18next-browser-languagedetector: 6.1.4
ioredis: 5.2.1
js-cookie: 3.0.1 js-cookie: 3.0.1
luxon: 2.5.0 luxon: 2.5.0
mapbox-gl: 2.9.2 mapbox-gl: 2.9.2
@@ -251,13 +249,6 @@ packages:
} }
dev: true dev: true
/@ioredis/commands/1.2.0:
resolution:
{
integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==
}
dev: true
/@jridgewell/resolve-uri/3.1.0: /@jridgewell/resolve-uri/3.1.0:
resolution: resolution:
{ {
@@ -1439,14 +1430,6 @@ packages:
} }
dev: true dev: true
/cluster-key-slot/1.1.0:
resolution:
{
integrity: sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==
}
engines: { node: '>=0.10.0' }
dev: true
/color-convert/2.0.1: /color-convert/2.0.1:
resolution: resolution:
{ {
@@ -1724,14 +1707,6 @@ packages:
} }
dev: true dev: true
/denque/2.1.0:
resolution:
{
integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
}
engines: { node: '>=0.10' }
dev: true
/detect-indent/6.1.0: /detect-indent/6.1.0:
resolution: resolution:
{ {
@@ -2797,26 +2772,6 @@ packages:
} }
dev: true dev: true
/ioredis/5.2.1:
resolution:
{
integrity: sha512-+rgPUIawiT+L3am9FbUcwjI7R7KtLDUSJNYWF82NZmlUXCZELws7iJkVDuECQoNUHqZTf/EGn3uw9IA+PlBiyg==
}
engines: { node: '>=12.22.0' }
dependencies:
'@ioredis/commands': 1.2.0
cluster-key-slot: 1.1.0
debug: 4.3.4
denque: 2.1.0
lodash.defaults: 4.2.0
lodash.isarguments: 3.1.0
redis-errors: 1.2.0
redis-parser: 3.0.0
standard-as-callback: 2.1.0
transitivePeerDependencies:
- supports-color
dev: true
/is-binary-path/2.1.0: /is-binary-path/2.1.0:
resolution: resolution:
{ {
@@ -2979,20 +2934,6 @@ packages:
} }
dev: true dev: true
/lodash.defaults/4.2.0:
resolution:
{
integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==
}
dev: true
/lodash.isarguments/3.1.0:
resolution:
{
integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==
}
dev: true
/lodash.isplainobject/4.0.6: /lodash.isplainobject/4.0.6:
resolution: resolution:
{ {
@@ -4088,24 +4029,6 @@ packages:
picomatch: 2.3.1 picomatch: 2.3.1
dev: true dev: true
/redis-errors/1.2.0:
resolution:
{
integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==
}
engines: { node: '>=4' }
dev: true
/redis-parser/3.0.0:
resolution:
{
integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==
}
engines: { node: '>=4' }
dependencies:
redis-errors: 1.2.0
dev: true
/regenerator-runtime/0.13.9: /regenerator-runtime/0.13.9:
resolution: resolution:
{ {
@@ -4418,13 +4341,6 @@ packages:
deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
dev: true dev: true
/standard-as-callback/2.1.0:
resolution:
{
integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==
}
dev: true
/string-width/4.2.3: /string-width/4.2.3:
resolution: resolution:
{ {
+18
View File
@@ -3,3 +3,21 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
/// <reference types="@sveltejs/kit" />
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
// and what to do when importing types
declare namespace App {
interface Locals {
email: string | null;
}
// interface Platform {}
interface Session {
authenticated: boolean;
email: string | null;
}
// interface Stuff {}
}
+41 -44
View File
@@ -5,56 +5,53 @@
*/ */
import * as cookie from 'cookie'; import * as cookie from 'cookie';
import Redis from 'ioredis'; import type { Handle, GetSession } from '@sveltejs/kit';
const redis = new Redis(process.env.REDIS_URL);
/** @type {import('@sveltejs/kit').Handle} */ /** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) { export const handle: Handle = async ({ event, resolve }) => {
const cookies = cookie.parse(event.request.headers.get('cookie') || ''); const cookies = cookie.parse(event.request.headers.get('cookie') || '');
const regex_token = /^Bearer (.*)$/gm.exec(cookies.access_token); const jwt = /^Bearer (.*)$/gm.exec(cookies.access_token);
if (regex_token === null) { const rememberme_token = cookies.rememberme_token;
event.locals.token = null; if (rememberme_token) {
} else { const res = await fetch(`${process.env.API_URL}/api/v1/users/auth/internal`, {
event.locals.token = regex_token[1]; method: 'POST',
}
event.locals.rememberme = cookies.rememberme_token;
return await resolve(event);
}
/** @type {import('@sveltejs/kit').GetSession} */
export async function getSession(event) {
const redis_res = await redis.get(event.locals.token);
let user_email: string;
if (redis_res === null) {
const res = await fetch(`${process.env.API_URL}/api/v1/users/check`, {
headers: { headers: {
Cookie: `access_token=Bearer ${event.locals.token}` // skipcq: JS-0378 'Content-Type': 'application/json'
} },
body: JSON.stringify({
rememberme: rememberme_token,
jwt: jwt === null ? undefined : jwt[0]
})
}); });
if (res.ok) { let new_jwt;
const json = await res.json(); if (jwt) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment new_jwt = jwt[0];
//@ts-ignore // skipcq: JS-0295
user_email = json.email;
} else { } else {
user_email = null; new_jwt = cookie.parse(res.headers.get('set-cookie')).access_token;
} }
event.locals.email = await (
await fetch(`${process.env.API_URL}/api/v1/users/auth/internal/email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
jwt: new_jwt
})
})
).text();
const resp = await resolve(event);
resp.headers.set('Set-Cookie', res.headers.get('set-cookie'));
return resp;
} else { } else {
user_email = redis_res; event.locals.email = null;
return resolve(event);
} }
if (user_email === null) { };
return {
authenticated: false, export const getSession: GetSession = async (event) => {
token: event.locals.token, return {
email: null email: event.locals.email,
}; authenticated: Boolean(event.locals.email)
} else { };
return { };
authenticated: true,
token: event.locals.token,
email: user_email
};
}
}
+5 -3
View File
@@ -9,7 +9,7 @@
<footer class="text-center text-white border-black w-screen"> <footer class="text-center text-white border-black w-screen">
<div class="grid grid-cols-12 w-full pt-4 bg-gray-700 pb-2"> <div class="grid grid-cols-12 w-full pt-4 bg-gray-700 pb-2">
<p class="col-start-2 col-end-12 text-center w-full"> <p class="col-start-3 col-end-11 text-center w-full">
Made with ❤️ by Made with ❤️ by
<a <a
href="https://mawoka.eu?utm_source=ClassQuiz&utm_medium=footer" href="https://mawoka.eu?utm_source=ClassQuiz&utm_medium=footer"
@@ -36,14 +36,16 @@
>More details are here.</a >More details are here.</a
> >
</p> </p>
<div class="flex flex-col items-center min-h-full h-full md:block hidden"> <div
class="flex flex-col items-center min-h-full h-full md:block hidden col-start-11 col-end-12"
>
<div class="my-auto mr-16"> <div class="my-auto mr-16">
<LanguageToggle /> <LanguageToggle />
</div> </div>
</div> </div>
</div> </div>
<div class="md:hidden block"> <div class="md:hidden block">
<div class="self-end flex justify-center min-h-full h-full bg-gray-700 md:pb-2"> <div class="self-end flex justify-center min-h-full h-full bg-gray-700 pb-2 md:pb-0">
<div class="m-auto md:invisible visible"> <div class="m-auto md:invisible visible">
<LanguageToggle /> <LanguageToggle />
</div> </div>