
Quarkus Security
- 2.2k installs
- 238k repo stars
- Updated August 5, 2026
- affaan-m/everything-claude-code
quarkus-security covers Quarkus auth, authorization, validation, and secrets best practices.
About
The quarkus-security skill documents security best practices for Quarkus applications covering authentication, authorization, input validation, and secrets management. It guides JWT and OIDC setup with @Authenticated resources, JsonWebToken injection, and application.properties issuer configuration. Authorization patterns use @RolesAllowed and SecurityIdentity checks. Bean Validation and custom validators protect user input; CORS and security headers harden HTTP surfaces. Secrets integrate via Vault or environment configuration sources with guidance on rate limiting and brute-force protection. Dependency scanning addresses CVE exposure in MicroProfile JWT and SmallRye JWT stacks. Trigger when adding auth, configuring OIDC realms, validating input, managing secrets, or scanning Quarkus dependencies for vulnerabilities during security reviews. JWT and OIDC authentication with @Authenticated and JsonWebToken. RBAC via @RolesAllowed and SecurityIdentity role checks. Bean Validation and custom input validators for user data. Secrets via Vault or env config sources with rate limiting guidance.
- JWT and OIDC authentication with @Authenticated and JsonWebToken.
- RBAC via @RolesAllowed and SecurityIdentity role checks.
- Bean Validation and custom input validators for user data.
- Secrets via Vault or env config sources with rate limiting guidance.
- Dependency CVE scanning for MicroProfile and SmallRye JWT stacks.
Quarkus Security by the numbers
- 2,240 all-time installs (skills.sh)
- +223 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #269 of 2,203 Security skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
quarkus-security capabilities & compatibility
- Capabilities
- jwt/oidc setup · rbac enforcement · input validation · secrets management
- Use cases
- security audit · api development
What quarkus-security says it does
Buenas prácticas para asegurar aplicaciones Quarkus con autenticación, autorización y validación de entrada.
Agregar autenticación (JWT, OIDC, Basic Auth)
npx skills add https://github.com/affaan-m/everything-claude-code --skill quarkus-securityAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2.2k |
|---|---|
| repo stars | ★ 238k |
| Security audit | 3 / 3 scanners passed |
| Last updated | August 5, 2026 |
| Repository | affaan-m/everything-claude-code ↗ |
How do I secure a Quarkus API with OIDC, RBAC, and safe secret handling?
Secure Quarkus apps with JWT/OIDC auth, RBAC, Bean Validation, CORS, secrets management, rate limiting, and dependency CVE scanning.
Who is it for?
Java teams hardening Quarkus microservices and REST endpoints.
Skip if: Non-Quarkus frameworks or infrastructure penetration testing.
When should I use this skill?
User adds Quarkus JWT, OIDC, @RolesAllowed, or secret management.
What you get
Configured auth, validated inputs, hardened headers, and scanned dependencies.
- Quarkus security review report
- Auth and secrets configuration recommendations
Files
Revisión de Seguridad Quarkus
Buenas prácticas para asegurar aplicaciones Quarkus con autenticación, autorización y validación de entrada.
Cuándo Activar
- Agregar autenticación (JWT, OIDC, Basic Auth)
- Implementar autorización con @RolesAllowed o SecurityIdentity
- Validar entrada de usuario (Bean Validation, validadores personalizados)
- Configurar CORS o cabeceras de seguridad
- Gestionar secretos (Vault, variables de entorno, fuentes de configuración)
- Agregar limitación de velocidad o protección contra fuerza bruta
- Escanear dependencias por CVEs
- Trabajar con MicroProfile JWT o SmallRye JWT
Autenticación
Autenticación JWT
// Recurso protegido con JWT
@Path("/api/protected")
@Authenticated
public class ProtectedResource {
@Inject
JsonWebToken jwt;
@Inject
SecurityIdentity securityIdentity;
@GET
public Response getData() {
String username = jwt.getName();
Set<String> roles = jwt.getGroups();
return Response.ok(Map.of(
"username", username,
"roles", roles,
"principal", securityIdentity.getPrincipal().getName()
)).build();
}
}Configuración (application.properties):
mp.jwt.verify.publickey.location=publicKey.pem
mp.jwt.verify.issuer=https://auth.example.com
# OIDC
quarkus.oidc.auth-server-url=https://auth.example.com/realms/myrealm
quarkus.oidc.client-id=backend-service
quarkus.oidc.credentials.secret=${OIDC_SECRET}Filtro de Autenticación Personalizado
@Provider
@Priority(Priorities.AUTHENTICATION)
public class CustomAuthFilter implements ContainerRequestFilter {
@Inject
SecurityIdentity identity;
@Override
public void filter(ContainerRequestContext requestContext) {
String authHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
return;
}
String token = authHeader.substring(7);
if (!validateToken(token)) {
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}
private boolean validateToken(String token) {
return true;
}
}Autorización
Control de Acceso Basado en Roles
@Path("/api/admin")
@RolesAllowed("ADMIN")
public class AdminResource {
@GET
@Path("/users")
public List<UserDto> listUsers() {
return userService.findAll();
}
@DELETE
@Path("/users/{id}")
@RolesAllowed({"ADMIN", "SUPER_ADMIN"})
public Response deleteUser(@PathParam("id") Long id) {
userService.delete(id);
return Response.noContent().build();
}
}
@Path("/api/users")
public class UserResource {
@Inject
SecurityIdentity securityIdentity;
@GET
@Path("/{id}")
@RolesAllowed("USER")
public Response getUser(@PathParam("id") Long id) {
if (!securityIdentity.hasRole("ADMIN") &&
!isOwner(id, securityIdentity.getPrincipal().getName())) {
return Response.status(Response.Status.FORBIDDEN).build();
}
return Response.ok(userService.findById(id)).build();
}
}Seguridad Programática
@ApplicationScoped
public class SecurityService {
@Inject
SecurityIdentity securityIdentity;
public boolean canAccessResource(Long resourceId) {
if (securityIdentity.isAnonymous()) {
return false;
}
if (securityIdentity.hasRole("ADMIN")) {
return true;
}
String userId = securityIdentity.getPrincipal().getName();
return resourceRepository.isOwner(resourceId, userId);
}
}Validación de Entrada
Bean Validation
// MAL: Sin validación
@POST
public Response createUser(UserDto dto) {
return Response.ok(userService.create(dto)).build();
}
// BIEN: DTO validado
public record CreateUserDto(
@NotBlank @Size(max = 100) String name,
@NotBlank @Email String email,
@NotNull @Min(18) @Max(150) Integer age,
@Pattern(regexp = "^\\+?[1-9]\\d{1,14}$") String phone
) {}
@POST
@Path("/users")
public Response createUser(@Valid CreateUserDto dto) {
User user = userService.create(dto);
return Response.status(Response.Status.CREATED).entity(user).build();
}Validadores Personalizados
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UsernameValidator.class)
public @interface ValidUsername {
String message() default "Formato de nombre de usuario inválido";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class UsernameValidator implements ConstraintValidator<ValidUsername, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) return false;
return value.matches("^[a-zA-Z0-9_-]{3,20}$");
}
}Prevención de Inyección SQL
Panache Active Record (Seguro por Defecto)
// BIEN: Consultas parametrizadas con Panache
List<User> users = User.list("email = ?1 and active = ?2", email, true);
Optional<User> user = User.find("username", username).firstResultOptional();
// BIEN: Parámetros nombrados
List<User> users = User.list("email = :email and age > :minAge",
Parameters.with("email", email).and("minAge", 18));Consultas Nativas (Usar Parámetros)
// MAL: Concatenación de cadenas
@Query(value = "SELECT * FROM users WHERE name = '" + name + "'", nativeQuery = true)
// BIEN: Consulta nativa parametrizada
@Entity
public class User extends PanacheEntity {
public static List<User> findByEmailNative(String email) {
return getEntityManager()
.createNativeQuery("SELECT * FROM users WHERE email = :email", User.class)
.setParameter("email", email)
.getResultList();
}
}Hash de Contraseñas
@ApplicationScoped
public class PasswordService {
public String hash(String plainPassword) {
return BcryptUtil.bcryptHash(plainPassword);
}
public boolean verify(String plainPassword, String hashedPassword) {
return BcryptUtil.matches(plainPassword, hashedPassword);
}
}Configuración de CORS
# application.properties
quarkus.http.cors=true
quarkus.http.cors.origins=https://app.example.com,https://admin.example.com
quarkus.http.cors.methods=GET,POST,PUT,DELETE
quarkus.http.cors.headers=accept,authorization,content-type,x-requested-with
quarkus.http.cors.access-control-allow-credentials=trueGestión de Secretos
# application.properties - SIN SECRETOS AQUÍ
# Usar variables de entorno
quarkus.datasource.username=${DB_USER}
quarkus.datasource.password=${DB_PASSWORD}
quarkus.oidc.credentials.secret=${OIDC_CLIENT_SECRET}
# O usar Vault
quarkus.vault.url=https://vault.example.com
quarkus.vault.authentication.kubernetes.role=my-roleLimitación de Velocidad
Nota de Seguridad: Nunca usar X-Forwarded-For directamente — los clientes pueden falsificarlo. Usar la dirección remota real de la solicitud servlet, o una identidad autenticada (clave API, subject del JWT) cuando esté disponible.
@ApplicationScoped
public class RateLimitFilter implements ContainerRequestFilter {
private final Map<String, RateLimiter> limiters = new ConcurrentHashMap<>();
@Inject
HttpServletRequest servletRequest;
@Override
public void filter(ContainerRequestContext requestContext) {
String clientId = getClientIdentifier();
RateLimiter limiter = limiters.computeIfAbsent(clientId,
k -> RateLimiter.create(100.0)); // 100 solicitudes por segundo
if (!limiter.tryAcquire()) {
requestContext.abortWith(
Response.status(429)
.entity(Map.of("error", "Demasiadas solicitudes"))
.build()
);
}
}
private String getClientIdentifier() {
// Usar la dirección remota provista por el contenedor (no X-Forwarded-For).
// Si está detrás de un proxy confiable, configurar
// quarkus.http.proxy.proxy-address-forwarding=true
// para que getRemoteAddr() retorne la IP real del cliente.
return servletRequest.getRemoteAddr();
}
}Cabeceras de Seguridad
@Provider
public class SecurityHeadersFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext request, ContainerResponseContext response) {
MultivaluedMap<String, Object> headers = response.getHeaders();
headers.putSingle("X-Frame-Options", "DENY");
headers.putSingle("X-Content-Type-Options", "nosniff");
headers.putSingle("X-XSS-Protection", "1; mode=block");
headers.putSingle("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
// CSP: evitar 'unsafe-inline' para script-src; usar nonces o hashes
headers.putSingle("Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'");
}
}Logging de Auditoría
@ApplicationScoped
public class AuditService {
private static final Logger LOG = Logger.getLogger(AuditService.class);
@Inject
SecurityIdentity securityIdentity;
public void logAccess(String resource, String action) {
String user = securityIdentity.isAnonymous()
? "anonymous"
: securityIdentity.getPrincipal().getName();
LOG.infof("AUDIT: user=%s action=%s resource=%s timestamp=%s",
user, action, resource, Instant.now());
}
}Escaneo de Seguridad de Dependencias
# Maven
mvn org.owasp:dependency-check-maven:check
# Gradle
./gradlew dependencyCheckAnalyze
# Verificar extensiones de Quarkus
quarkus extension list --installableBuenas Prácticas
- Siempre usar HTTPS en producción
- Habilitar JWT u OIDC para autenticación sin estado
- Usar
@RolesAllowedpara autorización declarativa - Validar toda entrada con Bean Validation
- Hashear contraseñas con BCrypt (nunca texto plano)
- Almacenar secretos en Vault o variables de entorno
- Usar consultas parametrizadas para prevenir inyección SQL
- Agregar cabeceras de seguridad a todas las respuestas
- Implementar limitación de velocidad para endpoints públicos
- Auditar operaciones sensibles
- Mantener dependencias actualizadas y escanear por CVEs
- Usar SecurityIdentity para verificaciones programáticas
- Establecer políticas CORS apropiadas
- Probar rutas de autenticación y autorización
Related skills
Forks & variants (1)
Quarkus Security has 1 known copy in the catalog totaling 1.4k installs. They canonicalize to this original listing.
- affaan-m - 1.4k installs
How it compares
Choose quarkus-security over generic Java security skills when the stack is specifically Quarkus with OIDC, SecurityIdentity, and Quarkus config sources.
FAQ
How is OIDC configured in Quarkus?
Set quarkus.oidc.auth-server-url, client-id, and credentials.secret in application.properties.
What validates user input?
Bean Validation annotations plus custom validators on request DTOs and resources.
When should dependency CVE scanning run?
When adding auth libraries or before release to catch known vulnerabilities.
Is Quarkus Security safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.