contexa-identity

인증

각 인증 방법에 대한 DSL 옵션 및 코드 예제입니다. Identity DSL에서 .form(), .rest(), .ott(), .passkey()를 통해 설정하는 인증 방법에 대한 상세 레퍼런스입니다.

개요

Contexa Identity는 4가지 인증 방법을 제공합니다. 각 방법은 독립적인 SecurityFilterChain을 생성하며, 우선순위는 order()를 통해 제어됩니다.

인증 방법DSL 메서드기본 Order용도
Form Login.form()100기존 웹 폼 로그인 (서버 렌더링)
REST API.rest()200JSON 기반 API 인증 (SPA, 모바일)
One-Time Token.ott()300매직 링크 / 이메일 인증
WebAuthn / Passkey.passkey()400생체 인증 / 하드웨어 키

모든 인증 방법은 rawHttp()를 통해 전체 Spring Security API에 접근할 수 있으며, 공통 옵션(order, CSRF, CORS, 헤더, 로그아웃 등)을 지원합니다.

이러한 인증 방법을 MFA (Multi-Factor Authentication)와 함께 사용하는 방법은 적응형 MFA 문서를 참조하세요. URL, 어댑터 및 상태 관리는 단일 인증과 MFA 플로우에서 다르게 동작합니다.

Form Login

기존 웹 폼 기반 로그인입니다. DSL을 통해 Spring Security의 formLogin()을 설정합니다. 기본 order는 100입니다.

전체 옵션

메서드타입기본값설명
loginPage(String)String단일 인증에서는 미설정, MFA 빌더에서는 기본 1차 로그인 페이지 적용로그인 페이지 URL
usernameParameter(String)String"username"사용자명 파라미터 이름
passwordParameter(String)String"password"비밀번호 파라미터 이름
loginProcessingUrl(String)StringAuthUrlProvider.getSingleFormLoginProcessing()로그인 처리 URL
defaultSuccessUrl(String)String-로그인 성공 후 리다이렉트 URL
defaultSuccessUrl(String, boolean)String, boolean-성공 URL + alwaysUse 플래그
failureUrl(String)String-로그인 실패 시 리다이렉트 URL
permitAll()-false로그인 페이지에 대한 미인증 접근 허용
successHandler(PlatformAuthenticationSuccessHandler)Handler자동 선택커스텀 성공 핸들러
failureHandler(PlatformAuthenticationFailureHandler)Handler자동 선택커스텀 실패 핸들러
securityContextRepository(SecurityContextRepository)Repository상태 유형에 따라 자동 선택보안 컨텍스트 리포지토리
rawFormLogin(SafeHttpFormLoginCustomizer)Customizer-formLogin() 내부 직접 커스터마이제이션
rawHttp(SafeHttpCustomizer<HttpSecurity>)Customizer-전체 Spring Security API 접근 (누적)
order(int)int100Filter Chain 우선순위
asep(Customizer<FormAsepAttributes>)Customizer-ASEP 어노테이션 속성 설정

기본 설정

registry
    .form(form -> form
        .loginPage("/login")
        .defaultSuccessUrl("/home")
        .failureUrl("/login?error")
        .permitAll()
    )
    .session(Customizer.withDefaults())
    .build();

커스텀 핸들러

registry
    .form(form -> form
        .loginPage("/login")
        .usernameParameter("email")
        .passwordParameter("passwd")
        .successHandler(customSuccessHandler)
        .failureHandler(customFailureHandler)
    )
    .session(Customizer.withDefaults())
    .build();

고급 설정 (rawHttp + rawFormLogin)

registry
    .form(form -> form
        .order(20)
        .loginPage("/admin/login")
        .rawFormLogin(formLogin -> formLogin
            .usernameParameter("admin_user")
            .passwordParameter("admin_pass"))
        .rawHttp(http -> http
            .securityMatcher("/admin/**")
            .sessionManagement(session -> session
                .maximumSessions(1)
                .maxSessionsPreventsLogin(true)))
    )
    .session(Customizer.withDefaults())
    .build();
rawFormLogin() vs rawHttp()
rawFormLogin()HttpSecurity.formLogin()의 내부만 커스터마이즈합니다. rawHttp()는 전체 Spring Security API(sessionManagement, securityMatcher, 커스텀 필터 등록 등)에 대한 접근을 제공합니다. 두 메서드 모두 누적 호출을 지원합니다.

REST API 인증

JSON 기반 REST API 인증입니다. SPA와 모바일 앱 같은 프론트엔드 클라이언트에서 JSON 페이로드로 인증합니다. 기본 order는 200입니다.

전체 옵션

메서드타입기본값설명
loginProcessingUrl(String)StringAuthUrlProvider.getSingleRestLoginProcessing()REST 로그인 처리 URL
defaultSuccessUrl(String)String-성공 후 리다이렉트 URL
defaultSuccessUrl(String, boolean)String, boolean-성공 URL + alwaysUse 플래그
failureUrl(String)String-실패 시 리다이렉트 URL
successHandler(PlatformAuthenticationSuccessHandler)Handler자동 선택커스텀 성공 핸들러
failureHandler(PlatformAuthenticationFailureHandler)Handler자동 선택커스텀 실패 핸들러
securityContextRepository(SecurityContextRepository)Repository상태 유형에 따라 자동 선택보안 컨텍스트 리포지토리
rawHttp(SafeHttpCustomizer<HttpSecurity>)Customizer-전체 Spring Security API 접근 (누적)
order(int)int200Filter Chain 우선순위
asep(Customizer<RestAsepAttributes>)Customizer-ASEP 어노테이션 속성 설정

기본 설정

registry
    .rest(rest -> rest
        .loginProcessingUrl("/api/auth/login")
    )
    .oauth2(Customizer.withDefaults())
    .build();

Stateless API 설정 (rawHttp)

registry
    .rest(rest -> rest
        .order(50)
        .loginProcessingUrl("/api/auth")
        .rawHttp(http -> http
            .securityMatcher("/api/**")
            .sessionManagement(session ->
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)))
    )
    .oauth2(Customizer.withDefaults())
    .build();
REST + OAuth2 조합
REST API 인증은 일반적으로 Stateless JWT 기반 운영을 위해 .oauth2()와 결합됩니다. .session()과도 결합할 수 있지만, API 서버에는 OAuth2를 권장합니다.

One-Time Token (매직 링크)

이메일 또는 SMS로 전송되는 일회용 토큰을 통한 인증입니다. 매직 링크 방식의 비밀번호 없는 인증입니다. 기본 order는 300입니다.

전체 옵션

메서드타입기본값설명
tokenGeneratingUrl(String)String-토큰 생성 요청 URL
defaultSubmitPageUrl(String)String-토큰 입력 페이지 URL
parameter namesString"username" / "token"현재 공개 OTT DSL은 기본 파라미터 이름을 사용합니다. 다른 이름이 필요하면 하위 옵션 커스터마이징이 필요합니다.
showDefaultSubmitPage(boolean)booleantrue기본 토큰 제출 페이지 표시 여부
tokenService(OneTimeTokenService)Service애플리케이션 컨텍스트의 Bean토큰 생성/검증 서비스 구현 (필수)
tokenGenerationSuccessHandler(OneTimeTokenGenerationSuccessHandler)Handler-토큰 생성 성공 핸들러 (예: 이메일 발송)
loginProcessingUrl(String)StringAuthUrlProvider.getSingleOttLoginProcessing()토큰 검증 처리 URL
successHandler(PlatformAuthenticationSuccessHandler)Handler자동 선택인증 성공 핸들러
failureHandler(PlatformAuthenticationFailureHandler)Handler자동 선택인증 실패 핸들러
rawHttp(SafeHttpCustomizer<HttpSecurity>)Customizer-전체 Spring Security API 접근 (누적)
order(int)int300Filter Chain 우선순위
asep(Customizer<OttAsepAttributes>)Customizer-ASEP 어노테이션 속성 설정

기본 설정

registry
    .ott(ott -> ott
        .tokenService(customTokenService)
        .tokenGenerationSuccessHandler(emailSendingHandler)
    )
    .session(Customizer.withDefaults())
    .build();

커스텀 페이지 + 이메일 발송 핸들러

registry
    .ott(ott -> ott
        .tokenGeneratingUrl("/auth/magic-link/request")
        .defaultSubmitPageUrl("/auth/magic-link/verify")
        // 현재 공개 OTT DSL은 기본 token 파라미터 이름("token")을 사용합니다.
        .showDefaultSubmitPage(false)
        .tokenService(jpaOneTimeTokenService)
        .tokenGenerationSuccessHandler((request, response, token) -> {
            String email = request.getParameter("username");
            emailService.sendMagicLink(email, token.getTokenValue());
            response.sendRedirect("/auth/magic-link/sent");
        })
    )
    .session(Customizer.withDefaults())
    .build();

WebAuthn / Passkey

FIDO2 WebAuthn 기반 생체 인증 및 하드웨어 보안 키 인증입니다. 가장 안전한 비밀번호 없는 인증 방식입니다. 기본 order는 400입니다.

전체 옵션

메서드타입기본값설명
rpName(String)String"contexa-identity"Relying Party 이름 (사용자에게 표시)
rpId(String)String"localhost"Relying Party ID (도메인)
allowedOrigins(Set<String>)Set<String>["http://localhost:${server.port}"] (명시적 설정이 없을 때의 fallback)허용 오리진 목록
allowedOrigins(String...)String...-허용 오리진 (varargs)
assertionOptionsEndpoint(String)StringAuthUrlProvider.getSinglePasskeyAssertionOptions()Assertion 옵션 엔드포인트
loginProcessingUrl(String)StringAuthUrlProvider.getSinglePasskeyLoginProcessing()인증 처리 URL
successHandler(PlatformAuthenticationSuccessHandler)Handler자동 선택인증 성공 핸들러
failureHandler(PlatformAuthenticationFailureHandler)Handler자동 선택인증 실패 핸들러
rawHttp(SafeHttpCustomizer<HttpSecurity>)Customizer-전체 Spring Security API 접근 (누적)
order(int)int400Filter Chain 우선순위
asep(Customizer<PasskeyAsepAttributes>)Customizer-ASEP 어노테이션 속성 설정

기본 설정

registry
    .passkey(passkey -> passkey
        .rpName("My Application")
        .rpId("example.com")
        .allowedOrigins("https://example.com")
    )
    .session(Customizer.withDefaults())
    .build();

Passkey 등록 플로우

Passkey 등록은 3단계로 진행됩니다. 서버는 Spring Security의 UserCredentialRepository를 통해 자격 증명을 저장합니다.


  Client                         Server
    |                               |
    |  1. POST /webauthn/register   |
    |        /options               |
    |  ---------------------------> |
    |                               | PublicKeyCredentialCreationOptions
    |  <--------------------------- | (rpId, rpName, userId, challenge)
    |                               |
    |  2. navigator.credentials     |
    |        .create(options)       |
    |  [Browser WebAuthn API]       |
    |                               |
    |  3. POST /webauthn/register   |
    |  ---------------------------> |
    |  (AuthenticatorAttestation    | Verify + Store in
    |   Response)                   | UserCredentialRepository
    |                               |
    |  <--- 201 Created ----------- |

Passkey 관리 REST API

메서드URL설명
POST/webauthn/register/options등록 옵션 생성 (PublicKeyCredentialCreationOptions)
POST/webauthn/register자격 증명 등록 (AuthenticatorAttestationResponse 검증)
POST/webauthn/authenticate/options인증 챌린지 생성 (assertionOptionsEndpoint)
DELETE/webauthn/register/{id}자격 증명 삭제

단일 인증 vs MFA 2차 요소

Passkey는 단일 인증과 MFA 2차 요소 인증에서 완전히 다른 URL, 어댑터 및 상태 관리를 사용합니다.

측면단일 인증MFA 2차 요소
인증 URL/login/webauthn/login/mfa-webauthn
어댑터PasskeyAuthenticationAdapterMfaPasskeyAuthenticationAdapter
필터Spring Security 내장MfaPasskeyAuthenticationFilter
상태 관리SecurityContextRepositoryMFA 상태 머신
DSL 설정.passkey().mfa(m -> m.passkey())

자동 핸들러 선택

인증 방법에 커스텀 핸들러가 지정되지 않으면, 인증 플로우와 상태 유형에 따라 적절한 핸들러가 자동으로 선택됩니다.

성공 / 실패 핸들러 선택 규칙

플로우상태 유형성공 핸들러실패 핸들러
단일 인증SessionSpring Security 기본값Spring Security 기본값
단일 인증OAuth2OAuth2SingleAuthSuccessHandlerOAuth2SingleAuthFailureHandler
MFA 1차모두PrimaryAuthenticationSuccessHandlerUnifiedAuthenticationFailureHandler
MFA 후속모두MfaFactorProcessingSuccessHandlerUnifiedAuthenticationFailureHandler

SecurityContextRepository 선택 규칙

플로우단계리포지토리
단일 인증SessionHttpSessionSecurityContextRepository
단일 인증OAuth2NullSecurityContextRepository
MFA1차 (최종 아님)NullSecurityContextRepository
MFA최종 단계상태 유형에 따라 자동 선택
MFA중간 단계NullSecurityContextRepository

커스텀 핸들러 구현에 대해서는 적응형 MFA 문서의 확장 포인트 섹션을 참조하세요.