JWT Authentication with Micronaut: A Complete Guide with Code Examples

Modern applications require secure ways to manage user identities and protect API endpoints. One of the most popular and efficient mechanisms is JWT (JSON Web Token) authentication. If you’re building cloud-native or microservice-based apps using Micronaut, securing your services with JWT Authentication with Micronaut is both straightforward and powerful.

In this guide, we’ll explore how to configure JWT-based authentication in a Micronaut application. All examples will use the package: com.kscodes.micronaut.security.

JWT Authentication with Micronaut

πŸ“¦ What is JWT?

JWT (JSON Web Token) is a compact, URL-safe means of representing claims transferred between two parties. It’s commonly used for stateless authentication in APIs, and consists of:

  • Header – metadata (type + signing algorithm)
  • Payload – user claims (e.g., sub, exp, roles)
  • Signature – verifies data integrity

Micronaut provides seamless JWT integration via its micronaut-security-jwt module.

πŸ“ Project Setup

1. Add Dependencies

For Gradle:


dependencies {
    implementation("io.micronaut.security:micronaut-security-jwt")
}

For Maven:



  io.micronaut.security
  micronaut-security-jwt


βš™οΈ JWT Configuration (application.yml)


micronaut:
  application:
    name: jwt-auth-demo
  security:
    enabled: true
    authentication: bearer
    token:
      jwt:
        signatures:
          secret:
            generator:
              secret: "jwt-secret-key"

authentication: bearer: Enables JWT bearer token.

jwt-secret-key: Change in production to something secure (or use Vault).

πŸ‘€ Custom Authentication Provider

File: com.kscodes.micronaut.security.CustomAuthProvider.java


package com.kscodes.micronaut.security;

import io.micronaut.security.authentication.*;
import jakarta.inject.Singleton;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
import java.util.List;

@Singleton
public class CustomAuthProvider implements AuthenticationProvider {

    @Override
    public Publisher authenticate(AuthenticationRequest request) {
        String username = request.getIdentity().toString();
        String password = request.getSecret().toString();

        if ("user1".equals(username) && "pass123".equals(password)) {
            return Mono.just(AuthenticationResponse.success(username, List.of("ROLE_USER")));
        }

        return Mono.just(new AuthenticationFailed());
    }
}

πŸ”‘ Creating a Login Endpoint to Issue JWT

File: com.kscodes.micronaut.security.LoginController.java


package com.kscodes.micronaut.security;

import io.micronaut.http.annotation.*;
import io.micronaut.security.authentication.UsernamePasswordCredentials;
import io.micronaut.security.token.jwt.render.BearerAccessRefreshToken;
import io.micronaut.security.token.jwt.generator.JwtTokenGenerator;
import jakarta.inject.Inject;
import reactor.core.publisher.Mono;

@Controller("/auth")
public class LoginController {

    @Inject
    JwtTokenGenerator tokenGenerator;

    @Post("/login")
    public Mono login(@Body UsernamePasswordCredentials creds) {
        // In a real app, delegate to auth service
        if ("user1".equals(creds.getUsername()) && "pass123".equals(creds.getPassword())) {
            String token = tokenGenerator.generateToken(creds).orElse("");
            return Mono.just(new BearerAccessRefreshToken("jwt-demo", creds.getUsername(), null, token, null));
        }
        return Mono.error(new RuntimeException("Invalid credentials"));
    }
}

πŸ”’ Protecting Routes with JWT

File: com.kscodes.micronaut.security.SecureController.java


package com.kscodes.micronaut.security;

import io.micronaut.http.annotation.*;
import io.micronaut.security.annotation.Secured;

@Controller("/secure")
public class SecureController {

    @Secured("ROLE_USER")
    @Get("/profile")
    public String getProfile() {
        return "This is a protected profile endpoint!";
    }
}

πŸ” Sample Request-Response Flow

  1. Login Request:

curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"user1","password":"pass123"}'

2. Get Token from Response

3. Access Secured Endpoint:


curl -H "Authorization: Bearer " http://localhost:8080/secure/profile

βœ… Tips for Production Use

  • Use HTTPS to transmit JWTs securely.
  • Store secrets in a secure store (Vault, AWS Secrets Manager).
  • Use refresh tokens or short-lived tokens with auto-renewal.
  • Add exp and iat claims to control token lifecycle.
  • Don’t store sensitive info (like passwords) inside JWT.

πŸ“š External References

🧩 Conclusion

Implementing JWT Authentication with Micronaut is efficient, secure, and fits perfectly within microservice architectures. You’ve now seen how to set up JWT security, write custom authentication logic, issue tokens, and protect endpoints.

By using the package com.kscodes.micronaut.security, this guide offers a solid foundation for real-world JWT-based authentication in Micronaut.

This post equips you to move forward confidently in building secure, scalable Micronaut applications with modern authentication techniques.