Skip to content
Back to skills

Jwt Auth

ASecurity

Scaffold JWT bearer authentication for a stateless JSON API. Recommends Spring Security's resource server (framework verifies signature + exp); also ships a custom OncePerRequestFilter using jjwt for teams that need it — it verifies the signature, rejects alg=none, checks exp/nbf, and returns 401 JSON on failure. Secret from env. Trigger phrases: "jwt auth", "bearer token", "validate jwt", "secure my api with tokens", "jwt filter", "resource server".

  • 10 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added August 31, 2026
developmentrustgojavaspringapisecurity

Works with

  • api

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned August 31, 2026

npx -y skills add ShipWithAI/shipwithai-plugins --skill jwt-auth --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Jwt Auth?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Jwt Auth
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/shipwithai-jwt-auth/badge)](https://www.skillsdirectory.com/skills/shipwithai-jwt-auth)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: jwt-auth
description: >
  Scaffold JWT bearer authentication for a stateless JSON API. Recommends Spring
  Security's resource server (framework verifies signature + exp); also ships a custom
  OncePerRequestFilter using jjwt for teams that need it — it verifies the signature,
  rejects alg=none, checks exp/nbf, and returns 401 JSON on failure. Secret from env.
  Trigger phrases: "jwt auth", "bearer token", "validate jwt", "secure my api with
  tokens", "jwt filter", "resource server".
argument-hint: "[base-package]"
---

# JWT Auth — Scaffold

Bearer-token auth for a stateless API. The cardinal rule: **never read claims from a
token you have not verified.** Prefer the framework path; the custom filter is a
fallback, not the default.

## Step 1 — Detect conventions

- Confirm a `SecurityFilterChain` exists (use the `security-filter-chain` skill first);
  JWT auth plugs into it with `SessionCreationPolicy.STATELESS` and CSRF disabled.
- Check for an issuer/JWKS endpoint (Auth0/Keycloak/Cognito) → strongly favors Option 1.
- Confirm the signing secret/JWKS URI is in config/env, never in source.

## Step 2 — Option 1 (RECOMMENDED): Spring Security resource server

Let Spring validate the token — signature, `exp`, `nbf`, issuer — no hand-rolled crypto:

```java
// build.gradle: implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
http.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));

@Bean // JWKS (asymmetric) — the usual case with an external IdP:
JwtDecoder jwtDecoder(@Value("${security.jwt.jwks-uri}") String jwksUri) {
    return NimbusJwtDecoder.withJwkSetUri(jwksUri).build();
}
// HMAC (shared secret) variant:
//   NimbusJwtDecoder.withSecretKey(new SecretKeySpec(secret.getBytes(UTF_8), "HmacSHA256"))
//       .macAlgorithm(MacAlgorithm.HS256).build();
```

Map scopes/roles with a `JwtAuthenticationConverter` if needed. Choose this whenever an
IdP issues the tokens — you maintain zero verification code.

## Step 3 — Option 2 (only if you must): custom filter

For teams that issue their own tokens and can't add the resource server. Render from
`assets/`, substitute `{{PACKAGE}}`:
- `JwtService.java.tmpl` → `<pkg>/security/JwtService.java` (issue + **verify** via jjwt)
- `JwtAuthenticationFilter.java.tmpl` → `<pkg>/security/JwtAuthenticationFilter.java`
- `JwtAuthenticationEntryPoint.java.tmpl` → `<pkg>/security/JwtAuthenticationEntryPoint.java`

Requires jjwt: `io.jsonwebtoken:jjwt-api` + runtime `jjwt-impl`, `jjwt-jackson`.

What the templates guarantee:
- `Jwts.parser().verifyWith(key).build().parseSignedClaims(token)` — verifies the
  signature, **rejects `alg=none`** and algorithm-confusion, and enforces `exp`/`nbf`.
- The filter only trusts a token after `verify` returns; on any `JwtException` it clears
  the context and returns **401 JSON** via the entry point — never partially authenticated.
- The secret is injected from `${security.jwt.secret}` (env), HS256 key >= 256 bits.
- Authorities are mapped from a `roles` claim (fallback `ROLE_USER`) in the filter's
  `authorities(...)` helper — adjust the claim name/prefix to match your issuer so
  `hasRole(...)` / `@PreAuthorize` reflect real token roles.

Wire the filter in `SecurityConfig`:
```java
http.exceptionHandling(e -> e.authenticationEntryPoint(jwtAuthenticationEntryPoint))
    .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
```

## Step 4 — Report

List created files and state which option was used. For Option 2, confirm: signature
verified, `alg=none` rejected, `exp` checked, secret from env, 401 JSON on failure.

## Failure modes — do NOT

- Do NOT read claims from an unverified token, and do NOT call a "parse without verify" API.
- Do NOT accept `alg=none` or let the token's header pick the algorithm (algorithm confusion).
- Do NOT hardcode the signing secret — inject from env/config (`sec-hardcoded-secret`).
- Do NOT skip the `exp` check or set tokens that never expire.
- Do NOT hand-roll Base64 + HMAC parsing — use the resource server or a vetted library (jjwt).
- Do NOT return 200/HTML on auth failure — return 401 JSON for an API.

Files in this skill

  • SKILL.md4.1 KB
  • assets/JwtAuthenticationEntryPoint.java.tmpl1.4 KB
  • assets/JwtAuthenticationFilter.java.tmpl3.7 KB
  • assets/JwtService.java.tmpl1.8 KB
  • evals.json2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.