# springboot-jwt-starter wires JWT into Spring Security for you

> springboot-jwt-starter is a Spring Boot starter kit that puts a JSON Web Token filter, a token helper and a refresh endpoint into a working project. It is built on AngularJS and Spring Security, the token lifetime is ten minutes, and the only release is 0.0.1 from 2017.

**bfwg/springboot-jwt-starter** — A Spring Boot JWT starter kit for stateless and token-based authentication apps.

- Repository: https://github.com/bfwg/springboot-jwt-starter
- Website: https://jwt.fanjin.io
- Stars: 850 · Forks: 285
- Language: Java
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/bfwg-springboot-jwt-starter

## A starter kit to read, not a dependency to add

springboot-jwt-starter is described as a Spring Boot token based security starter kit. That word, starter, does a lot of work here. The project is not a library you add to your build and configure through properties. It is a complete small application that you clone, run and read.

That reading is how the repository presents itself. The quick start tells you to clone the repo, install it with Maven and start the server, and the file structure section maps out the whole source tree with a comment on what each class does. The website hosts a live demo, and the project quotes Auth0's explanation of why JWT is the common case: once the user is logged in, each subsequent request carries the token, which allows access to routes, services and resources permitted with that token, and the same properties make single sign on across domains practical.

The intended reader is a developer who already knows Spring Boot and wants to see how token authentication is wired together in a codebase they can step through. The related project angular-spring-starter is pointed at for anyone who wants Angular 4 rather than AngularJS, which tells you the AngularJS frontend is the older half of the offer.

The licence is MIT and the homepage is jwt.fanjin.io.

## Running it locally with Maven and the two demo accounts

The quick start asks for Maven and Java 1.7 or greater, then walks through four steps. The clone uses a shallow history, the build installs the project, and the server is started with the Spring Boot run goal:

```bash
# clone our repo
# --depth 1 removes all but one .git commit history
git clone --depth 1 https://github.com/bfwg/springboot-jwt-starter.git

# change directory to our repo
cd springboot-jwt-starter

# install the repo with mvn
mvn install

# start the server
mvn spring-boot:run
```

The app then listens on port 8080, and two built in user accounts exist to demonstrate the different access levels of the endpoints:

```bash
# the app will be running on port 8080
# there are two built-in user accounts to demonstrate the differing levels of access to the endpoints:
# - User - user:123
# - Admin - admin:123
```

Those credentials are the quickest way to see the authorisation model work, and they are also the clearest signal about the intended use. This is a demonstration account set, not a user store you would expose. A real deployment replaces the in memory setup with a real user repository and a real password encoder.

The build also works with Docker, since the repository carries a Dockerfile and a docker-compose.yml. The compose file defines a single service built from the current directory and maps port 8080 on the host to 8080 in the container.

## The filter chain is where the token logic lives

The file structure is the clearest map of the mechanism, and it is annotated with what each piece does. Under security/auth there are four classes. JwtAuthenticationRequest is the login request object holding a username and password. RestAuthenticationEntryPoint handles authentication exceptions such as an invalid token. TokenAuthenticationFilter is the JWT token filter, configured in WebSecurityConfig. TokenBasedAuthentication is the custom Authentication class, extending AbstractAuthenticationToken.

Alongside them sits TokenHelper.java, the token helper class. That helper is the piece that creates and validates tokens, and WebSecurityConfig.java is the server side authentication configuration that wires the filter into the Spring Security chain.

The supporting layers follow the usual Spring layout. The model package holds User, Authority and UserTokenState, the latter described as the JWT model. The repository package has UserRepository for database access, the rest package has AuthenticationController for the authentication flow including the refresh token endpoint, and UserController for user related requests. The service package contains a UserService interface, a UserServiceImpl and a CustomUserDetailsService, which is the implementation that tells formLogin where to check the username and password.

The result is a conventional token flow rather than a novel one, which is the point of a starter kit: every part sits where a Spring developer would expect to find it.

## Ten minute tokens and a refresh endpoint

The configuration section names three things you would change first.

WebSecurityConfig.java holds the server side authentication configuration. application.yml holds the application level properties, the token expire time and the token secret among them, with a reference to the Spring Boot common application properties documentation for the full list. And the JWT token TTL is set at ten minutes, with the note that you can get a new token by signing in again.

A ten minute lifetime is short, and the refresh endpoint is what makes it workable. The AuthenticationController is described as handling auth related REST requests including the refresh token endpoint, so the pattern is the familiar one: a short lived access token, a refresh token used to obtain a new one without re-entering credentials.

The secret is the other thing worth looking at. It lives in application.yml as an application property, and in a project shaped like this it will be a placeholder value shipped in the repository. Moving it to the environment or a secret store is the first change a deployment needs, and the documentation points at application.yml rather than describing a secret management mechanism.

The database is the third. The starter uses an embedded H2 database that Spring Boot configures automatically, with import.sql holding the H2 query for table creation.

## Switching to MySQL is a configuration edit

The documentation shows how to point the project at another database, and the change is a block of YAML in the resource directory of application.yml:

```yaml
spring:
  jpa:
    hibernate:
      # possible values: validate | update | create | create-drop
      ddl-auto: create-drop
  datasource:
    url: jdbc:mysql://localhost/myDatabase
    username: myUser
    password: myPassword
    driver-class-name: com.mysql.jdbc.Driver
```

Two details in that snippet deserve attention rather than copying. The ddl-auto value of create-drop drops and recreates the schema on every start, which is convenient for a demo and destructive for anything real. The other databases listed as possible values are validate, update and create, and validate is the one to reach for when the schema is managed elsewhere.

The driver class name com.mysql.jdbc.Driver is the old MySQL driver identifier, which has been deprecated in favour of com.mysql.cj.jdbc.Driver in newer MySQL connectors. If you paste this into a current project and the driver fails to load, that line is the first thing to change.

The documentation also notes a second wrinkle for MySQL: sequences do not work for ID generation, so the GenerationType in the entity beans has to be changed to AUTO or IDENTITY. That is a code change, not a configuration change, and it is the kind of detail that a starter kit cannot fully hide.

## The Docker build runs on Java 17 in an Alpine image

The Dockerfile is a two stage build. The first stage uses a maven image, creates /usr/src/app, copies pom.xml in and resolves the dependencies with the Docker Maven settings file, then copies the rest of the source and packages it. The second stage is the runtime, based on openjdk:17-alpine, with a dedicated user added, the packaged jar copied to /app, and a java -jar entrypoint.

```dockerfile
FROM maven AS maven-container

RUN mkdir /usr/src/app
WORKDIR /usr/src/app

COPY pom.xml .
RUN mvn -B -f pom.xml -s /usr/share/maven/ref/settings-docker.xml dependency:resolve
COPY . .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml package
```

Splitting the build from the runtime means the final image carries the jar and a JRE rather than the whole Maven toolchain, which is the ordinary reason for the pattern. The dependency resolve step after copying only pom.xml is there so that the layer is reused when only the source changes.

There is a gap between this Dockerfile and the quick start. The quick start asks for Java 1.7 or greater, and the container runs on Java 17, while the frontend is AngularJS served as static assets from the resources directory. The build will work, but the age gap between the two toolchains is a fair signal of the project's vintage.

The container runs the app as a user called bfwg rather than root, and the compose file publishes port 8080.

## A 2017 release, and a repository that still moves

The release history is thin. The only tag listed is 0.0.1, named Affogato, dated 2017-06-27. There is no version 1.0 and no newer tag in the repository.

The repository itself is not archived, and the last push was on 2026-04-23, so the code is being touched even though nothing has been versioned since 2017. That combination tells you where the project stands. It is not a maintained library with a release cadence; it is a codebase that gets occasional commits, with the shipped version of the artefact frozen at an early number.

The practical consequence for anyone picking it up is that there is no upgrade path to follow. There is no changelog between versions, no migration notes, and no statement of which Spring Boot version the code targets. The Travis CI badge in the README and the .travis.yml file at the root also place it in the era when that was the standard CI service for a Java project, which is a small but real signal about the surrounding infrastructure.

Because the licence is MIT, you can take the code into your own project and maintain it yourself, and for a reference implementation that is often the intended ending anyway. Any specific compliance question about the licence belongs with your own counsel.

## A browser based session layer rather than an API

One structural decision shapes everything else about the project, and it is worth naming before anyone adopts it. The static folder holds the Angular assets and the HTML templates that Spring serves, and the AngularJS frontend talks to the REST endpoints behind the token filter. This is a server rendered session application with a token API behind it, not a headless service for a mobile client or a single page app of your own making.

That choice makes the demo meaningful and the starter less portable. The included frontend handles login, holds the token and attaches it to requests, which is exactly what you want to see working. If your own client is a React app or a native mobile app, the Angular half is dead weight you would delete, and you would keep the security package, the token helper and the refresh endpoint.

The comparison worth making is with doing the same work yourself against Spring Security directly. The difference in approach is that this project has already written the filter, the authentication entry point, the custom Authentication class and the refresh endpoint, and left them in plain, commented Java. Reading those four classes is likely faster than writing them, and copying them is likely faster still, as long as you are prepared to own them afterwards.

## Conclusion

springboot-jwt-starter suits a Spring Boot team that wants a readable reference implementation of JWT authentication, since the whole chain from the security filter to the refresh endpoint sits in a handful of named classes you can copy into your own project. It is not a dependency to add to a modern application, because it ships an AngularJS frontend, its only release is 0.0.1 from 2017 and the last push was on 2026-04-23. Before using it, read WebSecurityConfig.java and TokenHelper.java, decide whether the ten minute token lifetime fits your refresh flow, and expect to replace the AngularJS frontend, the H2 schema and the built in demo credentials before it goes anywhere near production.

## FAQ

### How do I run springboot-jwt-starter locally?

Clone the repository, run mvn install, then mvn spring-boot:run. The app listens on port 8080, and two built in accounts exist to show the different access levels, User with user:123 and Admin with admin:123.

### How long do the JWT tokens last in springboot-jwt-starter?

The README states that JWT tokens are configured to expire after 10 minutes, and that you can get a new token by signing in again. The token expire time and the token secret are set in application.yml.

### Can I use MySQL instead of the embedded H2 database in springboot-jwt-starter?

Yes. The README shows a configuration block for application.yml with a datasource url, username, password and driver class, and notes that for MySQL sequences do not work for ID generation, so the GenerationType in the entity beans must be changed to AUTO or IDENTITY.

## Sources

- [bfwg/springboot-jwt-starter on GitHub](https://github.com/bfwg/springboot-jwt-starter)
- [License: MIT](https://github.com/bfwg/springboot-jwt-starter/blob/master/LICENSE)
- [Project website](https://jwt.fanjin.io)
- [README](https://github.com/bfwg/springboot-jwt-starter/blob/master/README.md)
- [Releases](https://github.com/bfwg/springboot-jwt-starter/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bfwg-springboot-jwt-starter
