implemented authentication

This commit is contained in:
Johanna Kuehner
2024-02-29 21:05:08 +01:00
parent 601449d7e0
commit 7c19ee9215
12 changed files with 277 additions and 36 deletions

View File

@ -7,9 +7,15 @@
<script setup>
import { createPinia } from "pinia";
import piniaPluginPersistedState from "pinia-plugin-persistedstate"
//const layout = "empty";
//const route = useRoute();
const pinia = createPinia();
pinia.use(piniaPluginPersistedState);
useHead({
//title: `Tüit ERP - ${route.meta.title}`,

View File

@ -70,11 +70,17 @@ const handleLogin = async () => {
try {
let res = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/login`, requestBody);
const sessionToken = useCookie('token', {maxAge: 604800, sameSite: true});
sessionToken.value = res.data.token;
Axios.defaults.headers.common['Authorization'] = `${username}`;
const userToken = useCookie('user', {maxAge: 604800, sameSite: true});
userToken.value = username;
// something to do with the res?
console.log(res.data)
console.log(sessionToken)
console.log(res.data.message)
// sucessfully logged in
router.push('/')
router.push('/home')
} catch (err) {
// handle the error
console.log(err.response.statusText)

View File

@ -5,6 +5,13 @@ import type {
export default defineNuxtConfig({
devtools: { enabled: true },
modules: [
'@pinia/nuxt',
],/*
buildModules: [
'@nuxtjs/composition-api/module',
['@pinia/nuxt', { disableVuex: false }],
],*/
devServer: {
https: {
key: './certs/privkey.pem',

135
package-lock.json generated
View File

@ -12,16 +12,20 @@
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"express": "^4.18.2",
"h3": "^1.11.1",
"jsonwebtoken": "^9.0.2",
"leading-trim": "^1.0.2",
"mariadb": "^3.2.3",
"pinia-plugin-persistedstate": "^3.2.1",
"uuid": "^9.0.1",
"vite": "^5.1.0",
"vuex": "^4.1.0"
},
"devDependencies": {
"@nuxt/devtools": "latest",
"@pinia/nuxt": "^0.5.1",
"nuxt": "^3.8.0",
"pinia": "^2.1.7",
"vue": "^3.3.7",
"vue-router": "^4.2.5"
}
@ -2582,6 +2586,19 @@
"node": ">=0.10"
}
},
"node_modules/@pinia/nuxt": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@pinia/nuxt/-/nuxt-0.5.1.tgz",
"integrity": "sha512-6wT6TqY81n+7/x3Yhf0yfaJVKkZU42AGqOR0T3+UvChcaOJhSma7OWPN64v+ptYlznat+fS1VTwNAcbi2lzHnw==",
"dev": true,
"dependencies": {
"@nuxt/kit": "^3.5.0",
"pinia": ">=2.1.7"
},
"funding": {
"url": "https://github.com/sponsors/posva"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@ -4449,7 +4466,6 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz",
"integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==",
"dev": true,
"engines": {
"node": "^14.18.0 || >=16.10.0"
}
@ -4496,8 +4512,7 @@
"node_modules/cookie-es": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.0.0.tgz",
"integrity": "sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ==",
"dev": true
"integrity": "sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ=="
},
"node_modules/cookie-signature": {
"version": "1.0.6",
@ -4837,8 +4852,7 @@
"node_modules/defu": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
"dev": true
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="
},
"node_modules/delayed-stream": {
"version": "1.0.0",
@ -4871,10 +4885,9 @@
}
},
"node_modules/destr": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/destr/-/destr-2.0.2.tgz",
"integrity": "sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==",
"dev": true
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/destr/-/destr-2.0.3.tgz",
"integrity": "sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ=="
},
"node_modules/destroy": {
"version": "1.2.0",
@ -5730,22 +5743,35 @@
}
},
"node_modules/h3": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/h3/-/h3-1.10.1.tgz",
"integrity": "sha512-UBAUp47hmm4BB5/njB4LrEa9gpuvZj4/Qf/ynSMzO6Ku2RXaouxEfiG2E2IFnv6fxbhAkzjasDxmo6DFdEeXRg==",
"dev": true,
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/h3/-/h3-1.11.1.tgz",
"integrity": "sha512-AbaH6IDnZN6nmbnJOH72y3c5Wwh9P97soSVdGSBbcDACRdkC0FEWf25pzx4f/NuOCK6quHmW18yF2Wx+G4Zi1A==",
"dependencies": {
"cookie-es": "^1.0.0",
"crossws": "^0.2.2",
"defu": "^6.1.4",
"destr": "^2.0.2",
"destr": "^2.0.3",
"iron-webcrypto": "^1.0.0",
"ohash": "^1.1.3",
"radix3": "^1.1.0",
"ufo": "^1.3.2",
"ufo": "^1.4.0",
"uncrypto": "^0.1.3",
"unenv": "^1.9.0"
}
},
"node_modules/h3/node_modules/crossws": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/crossws/-/crossws-0.2.4.tgz",
"integrity": "sha512-DAxroI2uSOgUKLz00NX6A8U/8EE3SZHmIND+10jkVSaypvyt57J5JEOxAQOL6lQxyzi/wZbTIwssU1uy69h5Vg==",
"peerDependencies": {
"uWebSockets.js": "*"
},
"peerDependenciesMeta": {
"uWebSockets.js": {
"optional": true
}
}
},
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@ -6131,7 +6157,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.0.0.tgz",
"integrity": "sha512-anOK1Mktt8U1Xi7fCM3RELTuYbnFikQY5VtrDj7kPgpejV7d43tWKhzgioO0zpkazLEL/j/iayRqnJhrGfqUsg==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/brc-dd"
}
@ -6912,7 +6937,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
"dev": true,
"bin": {
"mime": "cli.js"
},
@ -7730,8 +7754,7 @@
"node_modules/node-fetch-native": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.2.tgz",
"integrity": "sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==",
"dev": true
"integrity": "sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w=="
},
"node_modules/node-forge": {
"version": "1.3.1",
@ -8264,8 +8287,7 @@
"node_modules/ohash": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz",
"integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==",
"dev": true
"integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw=="
},
"node_modules/on-finished": {
"version": "2.4.1",
@ -8527,8 +8549,7 @@
"node_modules/pathe": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
"dev": true
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="
},
"node_modules/perfect-debounce": {
"version": "1.0.0",
@ -8553,6 +8574,64 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pinia": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz",
"integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==",
"dependencies": {
"@vue/devtools-api": "^6.5.0",
"vue-demi": ">=0.14.5"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"@vue/composition-api": "^1.4.0",
"typescript": ">=4.4.4",
"vue": "^2.6.14 || ^3.3.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
"node_modules/pinia-plugin-persistedstate": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.1.tgz",
"integrity": "sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==",
"peerDependencies": {
"pinia": "^2.0.0"
}
},
"node_modules/pinia/node_modules/vue-demi": {
"version": "0.14.7",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/pkg-types": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
@ -9159,8 +9238,7 @@
"node_modules/radix3": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.0.tgz",
"integrity": "sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A==",
"dev": true
"integrity": "sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A=="
},
"node_modules/randombytes": {
"version": "2.1.0",
@ -10394,8 +10472,7 @@
"node_modules/ufo": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz",
"integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==",
"dev": true
"integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ=="
},
"node_modules/ultrahtml": {
"version": "1.5.2",
@ -10406,8 +10483,7 @@
"node_modules/uncrypto": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz",
"integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
"dev": true
"integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="
},
"node_modules/unctx": {
"version": "2.3.1",
@ -10443,7 +10519,6 @@
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/unenv/-/unenv-1.9.0.tgz",
"integrity": "sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g==",
"dev": true,
"dependencies": {
"consola": "^3.2.3",
"defu": "^6.1.3",

View File

@ -11,7 +11,9 @@
},
"devDependencies": {
"@nuxt/devtools": "latest",
"@pinia/nuxt": "^0.5.1",
"nuxt": "^3.8.0",
"pinia": "^2.1.7",
"vue": "^3.3.7",
"vue-router": "^4.2.5"
},
@ -21,9 +23,11 @@
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"express": "^4.18.2",
"h3": "^1.11.1",
"jsonwebtoken": "^9.0.2",
"leading-trim": "^1.0.2",
"mariadb": "^3.2.3",
"pinia-plugin-persistedstate": "^3.2.1",
"uuid": "^9.0.1",
"vite": "^5.1.0",
"vuex": "^4.1.0"

0
pinia.js Normal file
View File

View File

@ -1,4 +1,4 @@
import { loginSuccessful, errorMsg } from "../middleware/login";
import { loginSuccessful, sessionToken, errorMsg } from "../middleware/login";
import { OutgoingMessage } from 'http';
export default defineEventHandler(async (event) => {
@ -10,6 +10,11 @@ export default defineEventHandler(async (event) => {
})
}
setResponseStatus(event, 200)
return 'Successfully logged in.'
setResponseStatus(event, 200);
//setResponseHeader(event, "Set-Cookie", sessionToken);
const resBody = {
token: sessionToken,
message: 'Login successful'
};
return resBody;
})

1
server/main.ts Normal file
View File

@ -0,0 +1 @@
import { pinia } from '@/store'

View File

@ -0,0 +1,63 @@
import { useAuthStore } from '~/store/auth';
export default defineEventHandler (async (event) => {
// Check if user is not authenticated and trying to access a page other than /login
let isAuthenticated = false;
if (event.path !== '/login' && event.path !== '/api/login') {
//const reqUsername = getHeader(event, "Authorization");
//const reqCookie = getHeader(event, "Cookie");
const reqUsername = getCookie(event, 'user');
const reqToken = getCookie(event, 'token');
//console.log('getHeader: ', reqCookie);
console.log('getCookie user: ', reqUsername);
console.log('getCookie token: ', reqToken);
const auth = useAuthStore();
const authUsername = auth.username;
const authToken = auth.token;
console.log('auth user: ', authUsername);
console.log('auth token: ', authToken);
if (authUsername == reqUsername && authToken == reqToken) {
isAuthenticated = true;
}
if (!isAuthenticated) {
await sendRedirect(event, '/login');
}
}
});
/*function isAuthenticated(event) {
// Implement authentication logic
/*const auth = useAuthStore();
const authUsername = auth.username;
const authToken = auth.token;
const reqUsername = getHeader(event, 'Authorization');
const reqCookie = getHeader(event, 'Cookie');
const reqToken = useCookie('token');
console.log('getHeader: ', reqCookie);
console.log('useCookie: ', reqToken);
if (authUsername.equals(reqUsername) ) {
return true;
}*/
/*return false;
// Return true if authenticated, false otherwise
}*/
/*export default defineNuxtRouteMiddleware((to) => {
const auth = useAuthStore();
const authUsername = auth.username;
const authToken = auth.token;
const reqUsername =
})*/

View File

@ -1,8 +1,10 @@
import axios, { AxiosError } from 'axios';
import serversideConfig from '../../serversideConfig';
import https from 'https';
import { useAuthStore } from '~/store/auth';
let loginSuccessful = false;
let sessionToken = 'token';
let errorMsg = '';
export default defineEventHandler(async (event) => {
@ -29,6 +31,9 @@ export default defineEventHandler(async (event) => {
username: body.username,
password: body.password,
});
sessionToken = res.data.token;
const auth = useAuthStore();
auth.createNewSession(res.data.user, sessionToken);
loginSuccessful = true;
} catch (err) {
if (axios.isAxiosError(err)) {
@ -53,4 +58,4 @@ export default defineEventHandler(async (event) => {
}
})
export { loginSuccessful, errorMsg };
export { loginSuccessful, sessionToken, errorMsg };

65
store/auth.ts Normal file
View File

@ -0,0 +1,65 @@
import { defineStore } from 'pinia';
export const useAuthStore = defineStore('auth', {
state: () => ({
userobject: null,
username: 'user',
token: 'token',
authenticated: false,
}),
actions: {
createNewSession( user: any, t: string ) {
this.userobject = user;
this.username = user.username;
this.token = t;
this.authenticated = true;
},
logUserOut() {
this.username = 'user';
this.token = 'token';
this.authenticated = false;
},
},
persist: true,
});
/*interface UserPayloadInterface {
username: string;
password: string;
}
export const useAuthStore = defineStore('auth', {
state: () => ({
authenticated: false,
loading: false,
}),
actions: {
async authenticateUser({ username, password }: UserPayloadInterface) {
// useFetch from nuxt 3
const { data, pending }: any = await useFetch('https://dummyjson.com/auth/login', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: {
username,
password,
},
});
this.loading = pending;
if (data.value) {
const token = useCookie('token'); // useCookie new hook in nuxt 3
token.value = data?.value?.token; // set token to cookie
this.authenticated = true; // set authenticated state value to true
}
},
logUserOut() {
const token = useCookie('token'); // useCookie new hook in nuxt 3
this.authenticated = false; // set authenticated state value to false
token.value = null; // clear the token cookie
},
},
});*/

4
store/index.ts Normal file
View File

@ -0,0 +1,4 @@
import { createPinia } from "pinia";
import piniaPluginPersistedState from "pinia-plugin-persistedstate"
export const pinia = createPinia().use(piniaPluginPersistedState);