affaan-m/ECC

quarkus-security

Quarkus認証、認可、JWT/OIDC、RBAC、入力検証、CSRF、シークレット管理、依存関係セキュリティのセキュリティベストプラクティス。

74CollectingNetwork access
See how to use itView GitHub source
npx skills add https://github.com/affaan-m/ECC --skill "docs/ja-JP/skills/quarkus-security"
Automated source guide

Source checked Jul 28, 2026·Refresh due Oct 26, 2026

Reorganized from the pinned upstream SKILL.md

Turn quarkus-security's source instructions into a guide you can follow

According to the pinned SKILL.md from affaan-m/ECC: 認証、認可、入力検証によってQuarkusアプリケーションを保護するためのベストプラクティス。

npx skills add https://github.com/affaan-m/ECC --skill "docs/ja-JP/skills/quarkus-security"
Check the pinned source

Best fit

  • Quarkus認証、認可、JWT/OIDC、RBAC、入力検証、CSRF、シークレット管理、依存関係セキュリティのセキュリティベストプラクティス。

Bring this context

  • A concrete task that matches the documented purpose of quarkus-security.
  • The files, examples, or context the task depends on.
  • Your constraints, target environment, and definition of done.

Expected outputs

  • A result that follows the pinned quarkus-security instructions.
  • A concise record of assumptions, inputs used, and unresolved questions.
  • A final check against the source workflow and relevant permission signals.

Key source sections

Read quarkus-security through these 5 source sections

Sections are extracted automatically from the pinned SKILL.md and link back to the source.

01

When to Activate

認証追加(JWT、OIDC、Basic認証)

SKILL.md · When to Activate
認証追加(JWT、OIDC、Basic認証)@RolesAllowedまたはSecurityIdentityで認可実装ユーザー入力検証(Bean Validation、カスタムバリデータ)
02

Authentication

Configuration (application.properties): properties mp.jwt.verify.publickey.location=publicKey.pem mp.jwt.verify.issuer=https://auth.example.com

SKILL.md · Authentication
Configuration (application.properties): properties mp.jwt.verify.publickey.location=publicKey.pem mp.jwt.verify.issuer=https://auth.example.com
03

JWT Authentication

Configuration (application.properties): properties mp.jwt.verify.publickey.location=publicKey.pem mp.jwt.verify.issuer=https://auth.example.com

SKILL.md · JWT Authentication
Configuration (application.properties): properties mp.jwt.verify.publickey.location=publicKey.pem mp.jwt.verify.issuer=https://auth.example.com
04

OIDC

quarkus.oidc.auth-server-url=https://auth.example.com/realms/myrealm quarkus.oidc.client-id=backend-service quarkus.oidc.credentials.secret=${OIDCSECRET} java @Provider @Priority(Priorities.AUTHENTICATION) public class CustomAuthFilter implements ContainerRequestFilter {

SKILL.md · OIDC
quarkus.oidc.auth-server-url=https://auth.example.com/realms/myrealm quarkus.oidc.client-id=backend-service quarkus.oidc.credentials.secret=${OIDCSECRET} java @Provider @Priority(Priorities.AUTHENTICATION) public class…@Inject SecurityIdentity identity;@Override public void filter(ContainerRequestContext requestContext) { String authHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
05

Custom Authentication Filter

Review the “Custom Authentication Filter” section in the pinned source before continuing.

SKILL.md · Custom Authentication Filter
Review and apply the “Custom Authentication Filter” source section.

SkillSignal prompt templates

Provide the task, context, and acceptance criteria

These prompts were written by SkillSignal from the source structure; they are not upstream text.

Task-start prompt

Confirm source fit, inputs, and outputs before acting.

Use quarkus-security to help me with: [specific task]. Context: [files, data, or background]. Constraints: [environment, scope, and prohibited actions]. Before acting, check the pinned SKILL.md and explain which sections apply, what inputs are still missing, and what you will deliver.

Source-guided execution

Make the Agent explicitly follow the key extracted sections.

Apply the pinned quarkus-security source to [task]. Pay particular attention to these source sections: “When to Activate”, “Authentication”, “JWT Authentication”, “OIDC”, “Custom Authentication Filter”. Preserve the important decision at each step. Mark facts not covered by the source as “needs confirmation” instead of inventing them. Then verify the result against my acceptance criteria: [criteria].

Result-review prompt

Check omissions, permissions, and source drift before delivery.

Review the current quarkus-security result: (1) does it satisfy the original task; (2) were any applicable steps or limits in the pinned SKILL.md missed; (3) did it perform any unauthorized file, command, network, or data action; and (4) which conclusions remain unverified? List issues first, then fix only what the source or user authorization supports.

Output checklist

Verify each item before delivery

The task matches the purpose documented in the SKILL.md.

The source section “When to Activate” has been checked.

The source section “Authentication” has been checked.

The source section “JWT Authentication” has been checked.

The source section “OIDC” has been checked.

Inputs, constraints, and acceptance criteria are explicit.

Unverified facts, compatibility, and outcome claims are clearly marked.

Any file, command, network, or data action has been reviewed.

Choose a different workflow

When another Skill is the better fit

FAQ

What does quarkus-security do?

認証、認可、入力検証によってQuarkusアプリケーションを保護するためのベストプラクティス。

How do I start using quarkus-security?

The catalog detected this source-specific install command: npx skills add https://github.com/affaan-m/ECC --skill "docs/ja-JP/skills/quarkus-security". Inspect the command and pinned source before running it.

Which Agent platforms does it declare?

No dedicated Agent platform is declared in the pinned source record.

Repository stars
234,327
Repository forks
35,711
Quality
74/100
Source repository last pushed

Quality breakdown

Based on traceable docs and repository signals; stars are not treated as quality.

74/100
Documentation28/30
Specificity11/25
Maintenance20/20
Trust signals15/25
View original Skill.mdThis page is parsed directly from the repository SKILL.md without editorial rewriting. Collected: Jul 28, 2026 · about 1 min

Quarkus Security Review

認証、認可、入力検証によってQuarkusアプリケーションを保護するためのベストプラクティス。

When to Activate

  • 認証追加(JWT、OIDC、Basic認証)
  • @RolesAllowedまたはSecurityIdentityで認可実装
  • ユーザー入力検証(Bean Validation、カスタムバリデータ)
  • CORS設定またはセキュリティヘッダー構成
  • シークレット管理(Vault、環境変数、設定ソース)
  • レート制限またはブルートフォース対策追加
  • CVEの依存関係スキャン
  • MicroProfile JWTまたはSmallRye JWT操作

Authentication

JWT Authentication

// 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();
  }
}

Configuration (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}

Custom Authentication Filter

@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;
  }
}

Authorization

Role-Based Access Control

@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();
  }

  private boolean isOwner(Long userId, String username) {
    return userService.isOwner(userId, username);
  }
}

Programmatic Security

@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);
  }
}

Input Validation

Bean Validation

// 悪い例:検証なし
@POST
public Response createUser(UserDto dto) {
  return Response.ok(userService.create(dto)).build();
}

// 良い例:検証DTO
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();
}

Custom Validators

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UsernameValidator.class)
public @interface ValidUsername {
  String message() default "Invalid username format";
  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}$");
  }
}

// 使用例
public record CreateUserDto(
    @ValidUsername String username,
    @NotBlank @Email String email
) {}

SQL Injection Prevention

Panache Active Record (Safe by Default)

// 良い例:Panacheでのパラメータ化クエリ
List<User> users = User.list("email = ?1 and active = ?2", email, true);

Optional<User> user = User.find("username", username).firstResultOptional();

// 良い例:名前付きパラメータ
List<User> users = User.list("email = :email and age > :minAge",
    Parameters.with("email", email).and("minAge", 18));

Native Queries (Use Parameters)

// 悪い例:文字列連結
@Query(value = "SELECT * FROM users WHERE name = '" + name + "'", nativeQuery = true)

// 良い例:パラメータ化ネイティブクエリ
@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();
  }
}

Password Hashing

@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);
  }
}

// サービスで使用
@ApplicationScoped
public class UserService {
  @Inject
  PasswordService passwordService;

  @Transactional
  public User register(CreateUserDto dto) {
    String hashedPassword = passwordService.hash(dto.password());
    User user = new User();
    user.email = dto.email();
    user.password = hashedPassword;
    user.persist();
    return user;
  }

  public boolean authenticate(String email, String password) {
    return User.find("email", email)
        .firstResultOptional()
        .map(u -> passwordService.verify(password, u.password))
        .orElse(false);
  }
}

CORS Configuration

# 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.exposed-headers=Content-Disposition
quarkus.http.cors.access-control-max-age=24H
quarkus.http.cors.access-control-allow-credentials=true

Secrets Management

# application.properties - シークレットはここに置かない

# 環境変数を使用
quarkus.datasource.username=${DB_USER}
quarkus.datasource.password=${DB_PASSWORD}
quarkus.oidc.credentials.secret=${OIDC_CLIENT_SECRET}

# またはVaultを使用
quarkus.vault.url=https://vault.example.com
quarkus.vault.authentication.kubernetes.role=my-role

HashiCorp Vault Integration

@ApplicationScoped
public class SecretService {

  @ConfigProperty(name = "api-key")
  String apiKey; // Vault から取得

  public String getSecret(String key) {
    return ConfigProvider.getConfig().getValue(key, String.class);
  }
}

Rate Limiting

セキュリティ注意: X-Forwarded-For を直接使用しないでください — クライアントで偽装できます。 サーブレットリクエストからの実際のリモートアドレスを使用するか、利用可能な場合は認証ID(APIキー、JWTサブジェクト)を使用します。

@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)); // 1秒あたり100リクエスト

    if (!limiter.tryAcquire()) {
      requestContext.abortWith(
          Response.status(429)
              .entity(Map.of("error", "Too many requests"))
              .build()
      );
    }
  }

  private String getClientIdentifier() {
    // コンテナが提供するリモートアドレスを使用(X-Forwarded-Forではない)
    // 信頼されたプロキシの背後にある場合、quarkus.http.proxy.proxy-address-forwarding=trueを設定して
    // getRemoteAddr()が実クライアントIPを返すようにします
    return servletRequest.getRemoteAddr();
  }
}

Security Headers

@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");

    // XSS保護
    headers.putSingle("X-Content-Type-Options", "nosniff");
    headers.putSingle("X-XSS-Protection", "1; mode=block");

    // HSTS
    headers.putSingle("Strict-Transport-Security", "max-age=31536000; includeSubDomains");

    // CSP — script-src用の'unsafe-inline'は避けてください。XSS保護を無効化します。
    // 代わりにnoncesまたはhashesを使用します。CSSフレームワークが必要な場合、
    // style-srcの'unsafe-inline'は許容ですが、可能な場合はnoncesを優先してください。
    headers.putSingle("Content-Security-Policy",
        "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'");
  }
}

Audit Logging

@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());
  }
}

// リソースでの使用
@Path("/api/sensitive")
public class SensitiveResource {
  @Inject
  AuditService auditService;

  @GET
  @RolesAllowed("ADMIN")
  public Response getData() {
    auditService.logAccess("sensitive-data", "READ");
    return Response.ok(data).build();
  }
}

Dependency Security Scanning

# Maven
mvn org.owasp:dependency-check-maven:check

# Gradle
./gradlew dependencyCheckAnalyze

# Quarkus拡張機能チェック
quarkus extension list --installable

Best Practices

  • 本番環境では常にHTTPSを使用
  • ステートレス認証にはJWTまたはOIDCを有効化
  • 宣言的認可に@RolesAllowedを使用
  • Bean Validationで全入力検証
  • BCryptでパスワードハッシュ化(プレーンテキスト厳禁)
  • VaultまたはLambda環境変数でシークレット保存
  • SQLインジェクション防止にパラメータ化クエリを使用
  • 全レスポンスにセキュリティヘッダー追加
  • 公開エンドポイントにレート制限実装
  • 機密操作を監査ログに記録
  • 依存関係を最新に保ちCVEスキャン実施
  • プログラム的チェックにSecurityIdentityを使用
  • 適切なCORSポリシー設定
  • 認証・認可経路をテスト
Source repo
affaan-m/ECC
Skill path
docs/ja-JP/skills/quarkus-security/SKILL.md
Commit SHA
4e973d3eaf92
Repository license
MIT
Data collected