Skip to main content

Command Palette

Search for a command to run...

How I Secured My Vue + Spring Boot Application with JWT

When I first connected Vue with Spring Boot, everything worked—but there was one big problem: anyone could access my APIs.

Published
3 min read
How I Secured My Vue + Spring Boot Application with JWT

In the previous post, I connected a Vue frontend with a Spring Boot backend. That worked fine for basic communication, but there was one major gap—anyone could access the APIs.

In this article, I’ll walk through how I added authentication using JWT so that only logged-in users can interact with the backend.


🔐 Why I Chose JWT

When I started looking into authentication, I had two main options:

  1. Session-based authentication

  2. Token-based authentication

I went with JWT because:

  • I didn’t want to maintain sessions on the server

  • It works cleanly with frontend frameworks like Vue

  • It’s easier to scale later

The idea is simple - once the user logs in, the server gives a token, and that token is used for every request after that.


How the Flow Works

Here’s the flow I implemented:

  1. User enters username and password

  2. Backend verifies the credentials

  3. Backend generates a token

  4. Vue stores the token in the browser

Every API call includes that token in the header

If the token is valid, the request is allowed. Otherwise, it’s rejected.


⚙️ Backend Changes (Spring Boot)

On the backend side, I didn’t build everything from scratch. I focused on three key parts:

1). Generating the token

After a successful login, I generate a token that contains the username and an expiration time. This token is signed using a secret key.


String token = Jwts.builder()

.setSubject(username)

.setIssuedAt(new Date())

.setExpiration(new Date(System.currentTimeMillis() + 3600000))

.signWith(SignatureAlgorithm.HS256, "secret")
.compact();

2). Validating requests

For every request (except login), I check:

Does it have a token?

Is the token valid?

If both conditions pass, the request continues. Otherwise, it’s blocked.

3). Securing endpoints

I configured security so that:

/login is public

Everything else requires authentication


🌐 Frontend Changes (Vue)

On the Vue side, the implementation was pretty straightforward.

Storing the token after login:


axios.post("/login", credentials)

.then(res => {

localStorage.setItem("token", res.data);

});

Sending the token automatically

Instead of adding the token manually every time, I used an interceptor:


axios.interceptors.request.use(config => {

const token = localStorage.getItem("token");

if (token) {

config.headers.Authorization = \`Bearer ${token}\`;

}

return config;

});

This way, every request includes the token without repeating code.


🔒 Protecting Frontend Routes

I also added route protection so users can’t access certain pages without logging in.

If there’s no token, the user is redirected back to the login page.


⚠️ Things I Learned Along the Way

  1. A few things that tripped me up:

  2. Hardcoding the secret key is fine for testing, but not for production

  3. Token expiration is important—without it, users stay logged in forever

  4. Storing tokens in localStorage is simple, but has security trade-offs


✅ Final Result

After putting this together:

  • Users must log in before accessing Apis

  • Unauthorized requests are blocked

  • The frontend automatically handles authentication

It’s a big step toward making the app production-ready.


🚀 What I’ll Cover Next

Now that authentication is working, the next step is to actually use it in a real application.

In the next post, I’ll build a complete CRUD app with protected APIs using this setup.


💬 Closing Thoughts

Adding authentication changed how the whole app behaves. It’s no longer just a frontend calling an API—it’s a system with controlled access.

If you’re building something beyond a demo project, this is a must-have.