Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JWT authentication in Spring Boot (rookie‑friendly, no code dump)

This project shows a minimal, production‑style way to secure a Spring Boot API using JWT (JSON Web Token) and Spring Security’s OAuth2 Resource Server support. This README explains the moving parts by naming the classes and describing their roles, without pasting the full source code.

What you get

  • Login endpoint: POST /authenticate (public)
  • Protected endpoint: GET /posts (requires a valid Bearer token)
  • In‑memory demo user: user/password with ROLE_USER
  • HS256 (HMAC‑SHA256) symmetric signing for JWTs, using a base64‑encoded secret

Server default port: 8080

Dependencies

  • spring-boot-starter-web: MVC/JSON to expose REST endpoints.
  • spring-boot-starter-security: core security filters and authentication/authorization infrastructure.
  • spring-boot-starter-oauth2-resource-server: JWT validation machinery, so the app can accept and validate Bearer tokens.

Why “Resource Server”? Because it gives you robust JWT validation (signature + claims) with minimal setup and first‑class Spring Security integration.

JWT in a nutshell

  • A JWT is a compact string like header.payload.signature.
  • Client authenticates once, server issues a signed token; the client then sends it in Authorization: Bearer on subsequent requests.
  • The server validates the signature and checks claims like expiration for every request.
  • This demo uses HS256 (symmetric): one shared secret is used to sign and verify. Keep it safe and base64‑encoded.

Configuration overview (class‑level guide)

  • SecurityConfiguration

    • Enables CORS defaults, disables CSRF (stateless API), permits POST /authenticate, and requires authentication for other endpoints.
    • Activates OAuth2 Resource Server with JWT so incoming Bearer tokens are decoded and validated.
  • JwtConfiguration

    • Reads base64 secret from app.jwt.private-key (application.properties).
    • Exposes JwtEncoder (to issue tokens) and JwtDecoder (to validate tokens) using Nimbus.
    • Uses HS256 (MacAlgorithm.HS256) for signing and verification.
  • DomainUserDetailService

    • Provides a single in‑memory user for the demo: username: user, password: password, role: ROLE_USER.
    • Note: {noop} is used for the demo; use a PasswordEncoder (e.g., BCrypt) in real apps.
  • JwtTokenService

    • Authenticates username/password using Spring’s AuthenticationManager.
    • If successful, builds a JWT with claims:
      • sub: username
      • iat/exp: issued‑at and expiration (30 minutes)
      • auth: space‑separated authorities (e.g., ROLE_USER)
    • Signs the token with HS256 via JwtEncoder and returns it.
  • AuthenticationController

    • Exposes POST /authenticate (consumes application/json with {"email","password"}).
    • On success, returns the token as { "id_token": "<jwt>" } and also sets the Authorization response header to Bearer <jwt>.
  • PostController

    • Exposes GET /posts. Due to the security rules, this endpoint requires a valid Bearer token and returns sample data.
  • LoginRequest

    • Simple request body contract for /authenticate: email and password.
  • JwtToken

    • Simple response body contract for /authenticate: id_token field containing the JWT.

Application settings

in application.properties file:

spring.application.name=jwt-autentication-demo
app.jwt.private-key=<your‑base64‑secret>

Important : app.jwt.private-key must be a base64‑encoded secret. Generate one, for example with:

  • OpenSSL (macOS/Linux): openssl rand -base64 32
  • Java: Base64.getEncoder().encodeToString(SecureRandom.generateSeed(32))

Do not commit real secrets to version control. Use environment variables or your secrets manager in real deployments.

Run the app

  1. Set a proper base64 secret in src/main/resources/application.properties: app.jwt.private-key=<paste-your-base64-secret>
  2. Build and run:
    ./mvnw spring-boot:run
  3. Server listens on http://localhost:8080

Try it with curl

  1. Get a token:
   curl -i -X POST http://localhost:8080/authenticate \
        -H 'Content-Type: application/json' \
        -d '{"email":"user", "password":"password"}'

Copy id_token from the JSON response body (it also appears in the Authorization header).

  1. Call a protected endpoint:
   TOKEN="<paste-id_token>"
   curl -i http://localhost:8080/posts \
        -H "Authorization: Bearer $TOKEN"

You should receive 200 OK with a JSON array containing one sample post.

Common pitfalls and tips

  • 401 Unauthorized on protected endpoints: ensure you send Authorization: Bearer and the token is not expired.
  • 401 on /authenticate: verify SecurityConfiguration permits POST /authenticate (it does in this project).
  • Secrets: use different secrets per environment; rotate regularly.
  • Passwords: never use {noop} in production; enable a strong PasswordEncoder and store hashed passwords.

How the flow fits together

  1. Client submits credentials to /authenticate.
  2. JwtTokenService authenticates using the configured UserDetailsService, builds claims, and signs a JWT.
  3. Client calls protected endpoints with Authorization: Bearer .
  4. Resource server filters validate the token and populate the SecurityContext; the controller executes if valid.

Extend this demo

  • Switch to RSA (RS256) with private/public keys for signing/verification.
  • Back your users with a database and add a proper PasswordEncoder.
  • Add fine‑grained authorization (e.g., role‑based rules per endpoint).
  • Introduce refresh tokens or token revocation depending on your requirements.

About

A demonstration project showcasing basic JWT (JSON Web Token) authentication implementation using Spring Boot and Spring Security. This project serves as a learning resource for developers looking to understand how JWT authentication works in a Spring ecosystem.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages