2

I'm currently working on an existing PWA (Progressive web app) build in VUEJS. Currently i'm using Auth0 for user authentication and it works fine. But it seems a bit overkill and client finds it very hard to manage his users in Auth0 (multiple apps, users and so on...)

So i'm rebuilding the backend with Laravel together with Laravel Fortify and Laravel Sanctum.

Laravel sanctum provides a few solution for authentication and one of them is setting an accesstoken after logging in. (Token is not a JWT, just a random string without user details exposed) I can't use secure httponly cookies since front-end / back-end are on different top domains.

Here is where my Paranoia kinda kicks in, most say just store the token in localStorage it's easy and saves time. We all know that localStorage is not an advised way to store tokens. Simple XSS can expose the localstorage and well goodbye token ...

Having XSS happen will cause a bigger headache than the token i guess but i was wondering if storing the Token in my Service-worker (in memory) will be a bit more secure than localStorage?

I've stumbled upon an article by a user called Ropnop and he provided a service worker template for storing the token in memory.

// These listeners will make the service worker immediately available for the page
self.addEventListener('install', function(event) {
    event.waitUntil(self.skipWaiting());
    console.log('[SW] serviceworker installed!');
});

self.addEventListener('activate', function(event) {
    event.waitUntil(self.clients.claim());
    console.log('[SW] serviceworker ready!');
});

// Hardocded checks for origins/paths to send credentials to
const whitelistedOrigins = [
    "http://localhost", // dev
    "http://localhost:3000", // dev
    "https://tokenstorage.ropnop.dev", // prod
]

const whitelistedPathRegex = /\/api\/[^.]*$/ // anything under /api

// Global token variable in the service worker
let token = '';


// Exposed "method" for saving the token
self.addEventListener('message', function(event) {
    if (event.data && event.data.type === 'SET_TOKEN') {
        token = event.data.token;
        console.log("[SW] token set!");
    }
    if (event.data && event.data.type == 'CLEAR_TOKEN') {
        token = '';
        console.log('[SW] token cleared!');
    }
})

// Helper function to add the auth header if the oubound request matches the whitelists
const addAuthHeader = function (event) {
    destURL = new URL(event.request.url);
    if (whitelistedOrigins.includes(destURL.origin) && whitelistedPathRegex.test(destURL.pathname)) {
        const modifiedHeaders = new Headers(event.request.headers);
        if (token) {
            modifiedHeaders.append('Authorization', token)
        }
        const authReq = new Request(event.request, {headers: modifiedHeaders, mode: 'cors' });
        event.respondWith((async () => fetch(authReq))());
    }
}

// Intercept all fetch requests and add the auth header
self.addEventListener('fetch', addAuthHeader);

Basically you login and my app uses postMessage() to set the token in the service worker and it sets it in the request header before sending any request being made. A severe XSS attack would probably place a keylogger to steal usernames and passwords directly for user input. But some basic xss tricks should be stopped this way? for example just sending the localStorage as a string to a remote server that logs the string or something.

What do you advice? Is the service-worker approach safer or does it just looks safer?

And what should i do? (Secure cookie is not an option since both apps sit on different top domains) Option A: service-worker approach. Option B: Stop being a paranoid goose and use localStorage

I've been doing research for over 3days now but you never find a clear solution for this problem.

Looking forward to your responses!

Best Regards, Bart

2
  • Auth0 seems pretty mature. So I don't understand what you called "overkill". I often suggest that developers never bother too much with security stuff. Just implement and integrated the right configuration of the most mature security library/framework and spent the rest of your time focusing on the business side of your code. After all, users don't care if you use JWT or OpenID Connect for authentication, they only ask that the app "works as exected"
    – Jason Krs
    Commented May 16, 2021 at 16:13
  • @jason thanks for your reply, the client doesn't like auth0 so I can't use it anymore the users don't care about the tools that are being used but the client does. They just don't wanna pay 1000's of dollars for auth0 ... Commented May 16, 2021 at 17:14

0

You must log in to answer this question.

Browse other questions tagged .