Nowy standard. Twoje centrum tworzenia inteligentnego, szybkiego i zrównoważonego oprogramowania AI
Table of Contents
and 7 more
Vue.js nie ma wbudowanego mechanizmu uwierzytelniania. Logowanie, sesje i uprawnienia obsługuje twój backend oraz dostawca tożsamości, a zadaniem aplikacji Vue jest przeprowadzenie procesu logowania, śledzenie tego, kto jest zalogowany, i odpowiednie dostosowanie interfejsu.
Ten podział myli wiele zespołów, bo oficjalna dokumentacja Vue omawia XSS i bezpieczeństwo szablonów, ale prawie nic nie mówi o auth. Ten przewodnik uzupełnia tę lukę dla Vue 3 i Nuxt: podpowiada, jaką architekturę wybrać, jak chronić trasy w Vue Router, gdzie przechowywać tokeny, jak obsługiwać role i jakich błędów unikać.
Podsumowanie
Bezpieczne uwierzytelnianie w Vue.js zaczyna się poza Vue: dla większości aplikacji biznesowych najbezpieczniejszym rozwiązaniem jest backend-for-frontend (BFF), który obsługuje przepływ OAuth 2.0/OpenID Connect i przekazuje przeglądarce wyłącznie cookie sesyjne HttpOnly. To właśnie ten wzorzec RFC 10017 IETF „zdecydowanie zaleca” dla aplikacji biznesowych i przetwarzających wrażliwe dane.
W samej aplikacji Vue za to, co widzi użytkownik, odpowiadają strażnicy tras w Vue Router i sprawdzanie uprawnień, ale nie są one granicą bezpieczeństwa; twój interfejs API musi weryfikować tożsamość i uprawnienia przy każdym żądaniu.
Większość zespołów powinna korzystać z dostawcy tożsamości, takiego jak Auth0, Okta, Microsoft Entra ID czy Keycloak, zamiast budować logowanie od zera. Błędy w tym obszarze są kosztowne: według raportu IBM 2026 Cost of a Data Breach Report średni koszt naruszenia danych wynosi dziś 4,99 mln USD.
Czym różnią się uwierzytelnianie i autoryzacja w Vue.js?
Uwierzytelnianie odpowiada na pytanie „kim jesteś?”, a autoryzacja na pytanie „co wolno ci zrobić?”. Uwierzytelnianie potwierdza tożsamość, zwykle za pomocą hasła, passkey, jednorazowego kodu albo logowania single sign-on (SSO) przez dostawcę takiego jak Google czy Microsoft. Autoryzacja określa, do których stron, działań i danych ma dostęp taki zweryfikowany użytkownik, na podstawie ról lub uprawnień.
Mówiąc prościej, uwierzytelnianie wpuszcza cię przez drzwi wejściowe, a autoryzacja decyduje, do których pomieszczeń możesz wejść. W aplikacji Vue.js oba te mechanizmy działają w dwóch miejscach, a różnica między nimi ma znaczenie:
W przeglądarce aplikacja przekierowuje wylogowanych użytkowników na stronę logowania, ukrywa przycisk „Usuń” przed osobami bez odpowiednich uprawnień i pokazuje nazwę użytkownika w nagłówku. To element doświadczenia użytkownika.
Po stronie serwera API sprawdza sesję lub token przy każdym żądaniu i odrzuca wszystko, czego użytkownikowi nie wolno zrobić. To jest bezpieczeństwo.
Wszystko, co działa w przeglądarce, użytkownik może odczytać i zmienić. Jeśli jedyną rzeczą, która powstrzymuje zwykłego użytkownika przed otwarciem /admin, jest strażnik trasy, atakujący może go pominąć i wywołać twoje administracyjne API bezpośrednio. Potrzebujesz obu warstw, ale dane chroni tylko ta po stronie serwera.
Dlaczego uwierzytelnianie w aplikacji Vue.js ma znaczenie biznesowe?
Słabe uwierzytelnianie kosztuje na dwa sposoby: przez naruszenia i utracone kontrakty. Przejęte sesje i błędna kontrola dostępu prowadzą do naruszeń, a IBM podaje, że średni koszt naruszenia danych w 2026 roku wynosi 4,99 mln USD, czyli o 12% więcej niż rok wcześniej.
Przepisy jeszcze podnoszą stawkę. Artykuł 32 RODO wymaga „odpowiednich środków technicznych i organizacyjnych” do ochrony danych osobowych, a HIPAA Security Rule wymaga kontroli dostępu w systemach przetwarzających dane medyczne. Jeśli tworzysz oprogramowanie w HealthTech albo FinTech, projekt uwierzytelniania pojawi się zarówno podczas audytów, jak i w ankietach bezpieczeństwa od klientów.
Jest jeszcze aspekt sprzedażowy. Klienci B2B, zwłaszcza firmy klasy enterprise, często oczekują SSO przez własnego dostawcę tożsamości (przez OpenID Connect lub SAML), a do tego uwierzytelniania wieloskładnikowego i logów audytowych. Aplikacja, której nie da się podłączyć do dzierżawy Microsoft Entra ID lub Okta klienta, może utknąć na etapie zakupów, więc warto wybrać architekturę, która obsłuży takie funkcje, zanim staną się potrzebne.
Jakiej architektury uwierzytelniania powinna używać aplikacja Vue.js?
W większości aplikacji biznesowych najlepiej zastosować backend-for-frontend (BFF). Dokument IETF RFC 10017 „OAuth 2.0 for Browser-Based Applications” (opublikowany jako Best Current Practice w sierpniu 2026 roku) porównuje trzy sposoby obsługi OAuth w aplikacji jednostronicowej, takiej jak aplikacja Vue, i porządkuje je według tego, jak wiele może wykraść złośliwy skrypt uruchomiony w stronie:
Wzorzec | Gdzie są przechowywane tokeny | Co może zrobić atakujący wykorzystujący XSS | Kiedy go wybrać |
|---|---|---|---|
Backend-for-frontend (BFF) | Na serwerze. Przeglądarka otrzymuje tylko cookie sesyjne HttpOnly. | Może działać jako użytkownik, dopóki strona jest otwarta, ale nie może wykraść tokenów. | Domyślny wybór dla aplikacji biznesowych, aplikacji przetwarzających dane osobowe i wszystkiego, co podlega regulacjom. |
Backend pośredniczący w obsłudze tokenów | Backend przechowuje refresh token, a przeglądarka otrzymuje krótkotrwałe tokeny dostępu. | Może wykraść tokeny dostępu i wywoływać twoje API bezpośrednio do momentu ich wygaśnięcia. | Gdy pełny BFF działający jako proxy jest niepraktyczny, na przykład gdy przeglądarka musi wywoływać zewnętrzne API bezpośrednio. |
Klient OAuth działający wyłącznie w przeglądarce | W przeglądarce (tokeny dostępu i ewentualnie refresh tokeny). | Może wykraść tokeny i nadal z nich korzystać, potencjalnie przez długi czas. | Aplikacje niskiego ryzyka, bez własnego backendu. |
RFC 10017 stwierdza, że wzorzec BFF jest „zdecydowanie zalecany dla aplikacji biznesowych, aplikacji przetwarzających wrażliwe dane i aplikacji obsługujących dane osobowe”. Wymaga też PKCE (Proof Key for Code Exchange) dla publicznych klientów działających w przeglądarce i uznaje dawny implicit grant za przestarzały. Jeśli jakiś poradnik zaleca ci implicit flow, jest już nieaktualny.
Koszt tego podejścia jest taki, że BFF to kolejny komponent serwerowy, który trzeba zbudować, wdrożyć i skalować. Jeśli masz już backend w Node.NET, Javie albo Pythonie, zwykle jest to niewielkie rozszerzenie. Jeśli używasz Nuxt, jego ścieżki serwerowe mogą pełnić rolę BFF, o czym więcej niżej. Klient działający wyłącznie w przeglądarce z SDK takim jak Auth0 wdrożysz szybciej i może to być akceptowalne w narzędziu wewnętrznym lub prototypie, ale wtedy akceptujesz ryzyko kradzieży tokenów opisane w tabeli.
Czy warto samodzielnie budować uwierzytelnianie w Vue.js, czy lepiej użyć Auth0, Okta albo innego dostawcy?
Korzystaj z dostawcy tożsamości, chyba że masz mocny powód, by tego nie robić. Przechowywanie haseł, MFA, odzyskiwanie konta, ochrona przed atakami brute force, SSO i passkeys to każde z osobna pełny projekt, a każdy błąd kończy się incydentem bezpieczeństwa. Dostawca daje ci to wszystko, a do tego hostowaną stronę logowania, dzięki której dane uwierzytelniające w ogóle nie trafiają do twojego kodu Vue.
Realistyczne opcje są następujące:
Zarządzani dostawcy tożsamości, tacy jak Auth0, Okta, Microsoft Entra ID, AWS Cognito, Firebase Authentication, Supabase Auth czy Clerk. To najszybsza droga do wdrożenia, z SDK dla Vue albo zwykłego JavaScriptu. Ceną jest cykliczna opłata za użytkownika, która rośnie wraz z bazą użytkowników, oraz pewne uzależnienie od dostawcy: konta użytkowników, konfiguracje MFA i własne reguły logowania trudno później przenieść.
Samodzielnie hostowane serwery open source, takie jak Keycloak, Zitadel czy Authentik. Nie ma opłat za użytkownika i masz pełną kontrolę nad rezydencją danych, co ma znaczenie w części projektów regulowanych lub realizowanych dla sektora publicznego. W zamian bierzesz na siebie dostępność, aktualizacje i poprawki bezpieczeństwa.
Budowa własnego rozwiązania, która ma sens tylko wtedy, gdy auth jest proste, czyli e-mail i hasło, jedna aplikacja, brak SSO, a po stronie backendu masz programistów, którzy robili to już wcześniej. Nawet wtedy opieraj się na sprawdzonych modułach uwierzytelniania w swoim frameworku backendowym, zamiast samodzielnie implementować haszowanie haseł czy obsługę sesji.
Niezależnie od wyboru, ukryj dostawcę za własną cienką warstwą, czyli jednym store’em auth i jednym klientem API, żeby późniejsza zmiana dostawcy oznaczała przepisanie modułu, a nie całej aplikacji.
Jak chronić trasy za pomocą uwierzytelniania w Vue Router?
Trasy w Vue Router najlepiej chronić globalnym strażnikiem nawigacji beforeEach, który sprawdza flagę meta.requiresAuth i zwraca przekierowanie na stronę logowania, gdy nikt nie jest zalogowany. Bieżącego użytkownika przechowuj w niewielkim store’ze Pinia; Pinia to biblioteka do zarządzania stanem, którą dokumentacja Vue obecnie rekomenduje, a Vuex jest już tylko utrzymywany.
Minimalna konfiguracja dla BFF albo backendu z sesją opartą na cookie, w której przeglądarka pyta serwer, kto jest zalogowany, wygląda tak:
// stores/auth.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
type User = { id: string; name: string; roles: string[]; permissions: string[] }
export const useAuthStore = defineStore('auth', () => {
const user = ref<User | null>(null)
const checked = ref(false)
const isAuthenticated = computed(() => user.value !== null)
async function fetchUser() {
const res = await fetch('/api/me', { credentials: 'include' })
user.value = res.ok ? await res.json() : null
checked.value = true
}
return { user, checked, isAuthenticated, fetchUser }
})// router/index.ts
declare module 'vue-router' {
interface RouteMeta {
requiresAuth?: boolean
roles?: string[]
}
}
router.beforeEach(async (to) => {
const auth = useAuthStore()
if (!auth.checked) await auth.fetchUser()
if (to.meta.requiresAuth && !auth.isAuthenticated) {
return { name: 'login', query: { redirect: to.fullPath } }
}
if (to.meta.roles && !to.meta.roles.some((role) => auth.user?.roles.includes(role))) {
return { name: 'forbidden' }
}
})W poradnikach często błędnie opisuje się trzy szczegóły:
Zwracaj wartość zamiast wywoływać
next(). Dokumentacja Vue Router nadal wspiera callbacknext, ale nazywa go „częstym źródłem błędów”. Zwrócenie lokalizacji trasy powoduje przekierowanie, a brak zwracanej wartości pozwala kontynuować nawigację. To działa w Vue Router 4 i 5.Nie ustalaj, czy ktoś jest „zalogowany”, na podstawie
localStorage. Wiele starszych przykładów sprawdzalocalStorage.getItem('token'). Taka wartość nic nie mówi o tym, czy sesja nadal jest ważna, a każdy może ją ustawić w DevTools.Po logowaniu waliduj parametr
redirect. Podążaj za nim tylko wtedy, gdy jest ścieżką względną wewnątrz twojej aplikacji; w przeciwnym razie atakujący mogą wykorzystać twoją stronę logowania jako otwarte przekierowanie do witryny phishingowej.
Jeśli korzystasz z SDK, zwykle zawiera ono własnego strażnika. W przypadku Auth0 Vue SDK dodajesz do trasy beforeEnter: authGuard. Okta Vue SDK (od wersji 4 dla Vue 3) udostępnia navigationGuard, który rejestrujesz przez router.beforeEach i łączysz z meta: { requiresAuth: true }.
Jak aplikacja Vue.js powinna przechowywać i wysyłać tokeny uwierzytelniające?
Najbezpieczniejsze miejsce na tokeny uwierzytelniające wcale nie znajduje się w przeglądarce: przy BFF przeglądarka przechowuje wyłącznie cookie sesyjne HttpOnly, Secure, SameSite, którego JavaScript nie może odczytać. Jeśli tokeny muszą trafić do przeglądarki, przechowuj je w pamięci i unikaj localStorage. OWASP HTML5 Security Cheat Sheet mówi o tym wprost: „Nie przechowuj identyfikatorów sesji w local storage, ponieważ dane są zawsze dostępne dla JavaScriptu”.
Pamięć masowa | Czy JavaScript może odczytać (a więc także XSS)? | Czy przetrwa odświeżenie strony? | Uwagi |
|---|---|---|---|
Cookie HttpOnly (BFF) | Nie | Tak | Wymaga ochrony przed CSRF: cookie SameSite oraz token CSRF dla żądań zmieniających stan. |
W pamięci (zmienna JS lub store) | Tak, dopóki strona jest otwarta | Nie | Auth0 SPA SDK domyślnie przechowuje tokeny w pamięci; opcjonalna rotacja refresh tokenów pozwala przywracać sesje. |
| Tak, i to trwale | Tak | Każdy wstrzyknięty skrypt może odczytać token i wyprowadzić go poza aplikację. Unikaj tego wszędzie tam, gdzie chodzi o wrażliwe dane. |
Sesje oparte na cookie przywracają ryzyko cross-site request forgery (CSRF). Dokumentacja Vue mówi, że problem CSRF rozwiązuje się przede wszystkim po stronie backendu, ale frontend też musi współpracować, na przykład wysyłając token CSRF wystawiony przez backend. Axios potrafi robić to automatycznie: odczytuje cookie i kopiuje jego wartość do nagłówka żądania (xsrfCookieName i xsrfHeaderName).
Aby dołączać dane uwierzytelniające i obsługiwać wygasłe sesje w jednym miejscu, użyj interceptora klienta HTTP zamiast powtarzać tę logikę w każdym komponencie. Starsze artykuły nazywają to „middleware”, ale w Vue chodzi o interceptor Axios albo ofetch. W Nuxt „middleware” oznacza middleware tras, czyli coś innego. Przy krótkotrwałych tokenach dostępu i endpointcie odświeżania odśwież token raz po 401 i ponów pierwotne żądanie:
// api.ts
import axios from 'axios'
export const api = axios.create({ baseURL: '/api', withCredentials: true })
let refreshing: Promise<unknown> | null = null
api.interceptors.response.use(
(response) => response,
async (error) => {
const original = error.config
const isRefreshCall = original?.url === '/auth/refresh'
if (error.response?.status !== 401 || original._retry || isRefreshCall) {
throw error // let the app send the user to the login page
}
original._retry = true
// share one refresh request between all requests that failed at once
refreshing ??= api.post('/auth/refresh').finally(() => { refreshing = null })
await refreshing
return api(original)
}
)Przy pełnym BFF serwer sam odświeża tokeny, więc 401 oznacza po prostu, że sesja się zakończyła i użytkownik musi zalogować się ponownie.
Jak wdrożyć kontrolę dostępu opartą na rolach (RBAC) w Vue.js?
Kontrola dostępu oparta na rolach (RBAC) przypisuje użytkownikom role, takie jak Admin, Manager czy Viewer, a każdej roli zestaw uprawnień, na przykład invoice:read albo invoice:approve. W Vue pobierasz role lub uprawnienia bieżącego użytkownika z API albo z tokenu ID, a następnie używasz ich do pokazywania albo ukrywania tras, elementów menu i przycisków. API egzekwuje te same uprawnienia przy każdym żądaniu.
W małej aplikacji wystarczy jeden helper:
// composables/useCan.ts
import { useAuthStore } from '@/stores/auth'
export function useCan() {
const auth = useAuthStore()
return (permission: string) => auth.user?.permissions.includes(permission) ?? false
}<script setup lang="ts">
const can = useCan()
</script>
<template>
<button v-if="can('invoice:approve')">Approve</button>
</template>Gdy uprawnienia zależą od samych danych, na przykład „managerowie mogą edytować faktury ze swojego działu”, same role szybko przestają wystarczać. CASL obsługuje takie reguły oparte na atrybutach, a jego pakiet @casl/vue dodaje helper $can() oraz komponent <Can> dla Vue 3. Ponieważ reguły CASL to zwykły JavaScript, backend w Node może współdzielić te same definicje, dzięki czemu interfejs i API stosują identyczne zasady.
Sprawdzaj uprawnienia w komponentach i unikaj sprawdzania nazw ról: can('invoice:approve') przetrwa reorganizację ról, a user.role === 'manager' rozsiane po 40 komponentach już nie. Pamiętaj też, że ukrycie przycisku to tylko kosmetyka. Jeśli endpoint API stojący za tym przyciskiem nie sprawdza uprawnienia, każdy może go wywołać.
Czym jest JWT i czy aplikacja Vue może mu zaufać?
JSON Web Token (JWT) to zwięzły, podpisany token złożony z trzech części zakodowanych w Base64URL: nagłówka, czyli typu tokenu i algorytmu podpisu, ładunku z deklaracjami, takimi jak identyfikator użytkownika, data wygaśnięcia czy role, oraz podpisu. Jest podpisany, a nie zaszyfrowany. Zgodnie z RFC 7519 deklaracje JWT są zwykle przenoszone jako ładunek JSON Web Signature, więc każdy, kto ma token, może go zdekodować i odczytać. Nigdy nie umieszczaj sekretów w JWT.
Podpis pozwala serwerowi sprawdzić, czy token nie został zmieniony, ale aplikacja Vue nie jest w stanie zweryfikować tego w sensowny sposób, bo użytkownik kontroluje przeglądarkę. Odczytywanie deklaracji z tokenu ID, żeby wyświetlić nazwę użytkownika albo dopasować menu, jest w porządku. Podejmowanie decyzji bezpieczeństwa na podstawie zdekodowanego JWT w przeglądarce już nie; taka decyzja należy do API, które musi zweryfikować podpis, datę wygaśnięcia, wystawcę i odbiorcę tokenu.
Jak działa uwierzytelnianie w Nuxt?
Nuxt dodaje serwer do aplikacji Vue, co ułatwia wdrożenie wzorca BFF. Oficjalny przepis Nuxt na sesje i uwierzytelnianie korzysta z modułu nuxt-auth-utils, który przechowuje sesję w zaszyfrowanym, zapieczętowanym cookie, więc nie potrzebujesz bazy danych sesji.
Po stronie serwera setUserSession zapisuje użytkownika po udanym logowaniu, a requireUserSession odrzuca żądania bez prawidłowej sesji kodem 401. Po stronie klienta composable useUserSession udostępnia loggedIn, user i clear na potrzeby interfejsu. Moduł zawiera też obsługę OAuth dla popularnych dostawców oraz wsparcie dla WebAuthn, czyli passkeys. Jest jednak jedno ograniczenie: potrzebuje działającego serwera Nuxt, więc nie zadziała w całkowicie statycznej stronie wygenerowanej przez nuxt generate.
Uważaj na SDK auth działające wyłącznie po stronie klienta w renderowanej po stronie serwera aplikacji Nuxt. Na przykład Okta Vue SDK nie obsługuje renderowania po stronie serwera. Przy SSR wybierz podejście serwerowe albo bibliotekę stworzoną z myślą o Nuxt.
Jakie błędy bezpieczeństwa osłabiają uwierzytelnianie w Vue.js?
Te same kilka błędów stale wraca w kodzie auth dla Vue.js, a najbardziej szkodliwy z nich to cross-site scripting (XSS). Jeśli atakujący może uruchomić skrypt w twojej stronie, może działać jak zalogowany użytkownik niezależnie od tego, jak ostrożnie przechowujesz tokeny. Przewodnik Vue po bezpieczeństwie wyjaśnia, jak Vue domyślnie escapuje treść i gdzie możesz tę ochronę złamać:
Renderowanie niezaufanej treści za pomocą
v-htmlalbo jako szablonu. Pierwsza zasada bezpieczeństwa Vue mówi, by nigdy nie używać niezaufanej treści jako szablonu komponentu, bo jest to „równoznaczne z dopuszczeniem dowolnego wykonania JavaScriptu”. Każdy HTML pochodzący od użytkowników sanitizuj i nigdy nie montuj Vue na stronach renderowanych po stronie serwera, które zawierają treści od użytkowników.Umieszczanie sekretów w bundlu. Każda zmienna, którą build udostępnia klientowi, w Vite wszystko z prefiksem
VITE_, trafia do publicznego JavaScriptu. Identyfikatory klienta są w porządku, ale client secrets i klucze API już nie.Traktowanie frontendu jako strażnika. Strażnicy tras, sprawdzenia
v-ifi zdekodowane JWT są w pełni kontrolowane przez użytkownika. Każde żądanie do API autoryzuj po stronie serwera.Korzystanie z przestarzałych przepływów. OAuth Security Best Current Practice, RFC 9700, stwierdza, że password grant „NIE MOŻE być używany”, a RFC 10017 uznaje implicit grant za przestarzały. Korzystaj z authorization code flow z PKCE.
Ignorowanie aktualizacji zależności. SDK auth i samo Vue otrzymują poprawki bezpieczeństwa. Zespół Vue zaleca, by zawsze używać najnowszych wersji Vue i jego oficjalnych bibliotek. Starsze wtyczki społeczności, takie jak biblioteki uprawnień tylko dla Vue 2, często nie są już utrzymywane.
Najważniejsze wnioski
Vue nie ma wbudowanego uwierzytelniania; za realne zabezpieczenia odpowiadają twój backend i dostawca tożsamości.
W aplikacjach biznesowych stosuj backend-for-frontend z cookie HttpOnly, zgodnie z zaleceniem RFC 10017.
Strażnicy tras i sprawdzenia
v-ifto UX. Twoje API musi autoryzować każde żądanie.Nie przechowuj tokenów w
localStorage; XSS może je odczytać.Korzystaj z authorization code flow z PKCE i sprawdzaj uprawnienia, a nie nazwy ról.
Co jest potrzebne, by uwierzytelnianie w Vue.js pozostało bezpieczne także na dłuższą metę?
Bezpieczne uwierzytelnianie w Vue.js zależy znacznie bardziej od decyzji architektonicznych niż od biblioteki, którą zainstalujesz. Gdzie tylko możesz, trzymaj tokeny po stronie serwera, logowanie powierz sprawdzonemu dostawcy tożsamości, a wszystko w przeglądarce, od strażników tras po ukryte przyciski, traktuj jako wygodę, a nie ochronę. Dzięki temu aplikacja Vue ma wąski, jasny zakres zadań: obsłużyć proces logowania, utrzymywać niewielki store auth, chronić trasy i dostosowywać interfejs do uprawnień użytkownika.
Ta praca nie kończy się w dniu uruchomienia. Klienci klasy enterprise poproszą o SSO, audytorzy zapytają, jak kontrolowany jest dostęp, a SDK będą dalej otrzymywać aktualizacje bezpieczeństwa. Czytelny podział odpowiedzialności, czyli jeden store auth, jeden klient API i uprawnienia sprawdzane po nazwie, sprawia, że takie zmiany stają się rutyną, a nie źródłem ryzyka.
Jeśli planujesz produkt oparty na Vue.js albo potrzebujesz drugiej opinii o auth w istniejącym rozwiązaniu, zespół Vue.js w Monterail może przeanalizować twoją architekturę albo zbudować ją razem z tobą.





