JWT 인증
본문
JWT
Traefik Hub 기능
이 미들웨어는 Traefik Hub에서만 사용할 수 있어요. Traefik Hub의 고급 기능에 대해 더 알아보세요.
JWT 미들웨어는 Authorization 헤더(Authorization: Bearer ***)에 유효한 JWT 토큰이 제공됐는지 검증합니다.
토큰을 Authorization 헤더로 전달할 수 없다면, 폼 데이터나 쿼리 파라미터로 전달할 수 있어요. 자세한 내용은 tokenKey 옵션을 참고하세요.
특별한 구성 없이 JWT 미들웨어는 JWT의 서명만 검증하고, 표준 클레임인 nbf, exp, iat(존재하는 경우)를 확인합니다. 커스텀 클레임 검증은 커스텀 클레임 검증에서 구성할 수 있어요.
구성 예시
Middleware JWT
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-jwt
spec:
plugin:
jwt:
signingSecret: my-secret
forwardHeaders:
Group: grp
Expires-At: exp
claims: Equals(`grp`, `admin`)
구성 옵션
| Field | Description | Default | Required |
| signingSecret | JWT 인증서에 서명하는 데 쓰는 비밀을 정의해요. 이후 미들웨어가 들어오는 요청을 검증할 때 사용됩니다. signingSecret, publicKey, jwksFile, jwksUrl 옵션 중 하나는 반드시 설정해야 해요. (자세한 내용은 여기) | "" | No |
| signingSecretBase64Encoded | signingSecret이 base64로 인코딩됐는지 여부를 정의해요. true로 설정하면 사용 전에 signingSecret을 base64 디코딩합니다. | false | No |
| publicKey | 들어오는 요청의 비밀 서명을 검증하는 데 사용하는 공개 키를 정의해요. 이 경우 사용자는 구성된 공개 키에 대응하는 개인 키로 토큰에 서명해야 합니다. signingSecret, publicKey, jwksFile, jwksUrl 옵션 중 하나는 반드시 설정해야 해요. | "" | No |
| jwksFile | JWT 서명 검증에 사용할 JWK 집합을 정의해요. 옵션은 API 게이트웨이에 마운트된 파일의 경로이거나 JWK 집합 파일의 내용 자체일 수 있어요. signingSecret, publicKey, jwksFile, jwksUrl 옵션 중 하나는 반드시 설정해야 해요. (자세한 내용은 여기) | "" | No |
| jwksUrl | JWK 집합을 제공하는 호스트의 URL을 정의해요. HTTP 캐시 제어(Cache Control)가 캐싱을 허용하면 키가 캐시됩니다. signingSecret, publicKey, jwksFile, jwksUrl 옵션 중 하나는 반드시 설정해야 해요. (자세한 내용은 여기) | "" | No |
| forwardAuthorization | 미들웨어가 요청을 승인한 뒤 authorization 헤더를 전달할지, 아니면 요청에서 제거할지 정의해요. | false | No |
| tokenKey | Authorization 헤더로 JWT를 전달할 수 없는 애플리케이션을 위해 JWT를 전달하는 데 쓰는 쿼리·폼 데이터 파라미터 이름을 정의해요. 이 옵션이 켜져 있어도 미들웨어는 항상 먼저 Authorization 헤더를 확인합니다. 이 옵션은 RFC에서 권장하지 않으므로, JWT를 Authorization 헤더로 전달할 수 없을 때만 켜야 해요. | "" | No |
| claims | 요청을 승인하기 위해 검증할 클레임을 정의해요. claims 옵션은 JWT 형식 토큰에서만 사용할 수 있어요. (자세한 내용은 여기) | "" | No |
| usernameClaim | 접근 로그의 clientusername을 채우는 데 평가할 클레임을 정의해요. usernameClaim 옵션은 JWT 형식 토큰에서만 사용할 수 있어요. | "" | No |
| forwardHeaders | 요청에 추가할 HTTP 헤더를 정의하고, 인증 서버가 반환한 접근 토큰 클레임에서 추출한 값으로 채웁니다. JWT에서 찾지 못한 전달 대상 클레임은 빈 헤더가 돼요. forwardHeaders 옵션은 JWT 형식 토큰에서만 사용할 수 있어요. | {} | No |
| clientConfig.tls.ca | 인증 서버와 TLS 연결을 맺는 데 사용하는 인증서 번들을 담은 PEM 인코딩 인증서 번들이나 비밀을 참조하는 URN (자세한 내용은 여기) | "" | No |
| clientConfig.tls.cert | Vault 서버와 TLS 연결을 맺는 데 사용하는 인증서를 담은 PEM 인코딩 인증서나 비밀을 참조하는 URN (자세한 내용은 여기) | "" | No |
| clientConfig.tls.key | Vault 서버와 TLS 연결을 맺는 데 사용하는 키를 담은 PEM 인코딩 키나 비밀을 참조하는 URN. (자세한 내용은 여기) | "" | No |
| clientConfig.tls.insecureSkipVerify | 인증 서버와 통신할 때 TLS 인증서 검증을 끕니다. 테스트 목적으로는 유용하지만 프로덕션에는 강력히 권장되지 않아요. (자세한 내용은 여기) | false | No |
| clientConfig.timeoutSeconds | 인증 서버에 대한 요청을 포기하기 전의 시간을 정의해요. | 5 | No |
| clientConfig.maxRetries | 실패한 인증 서버 요청에 대한 재시도 횟수를 정의해요. | 3 | No |
claims
문법
claims에서 지원하는 함수는 다음과 같아요:
| Function | Description | Example |
| Equals | key의 값이 value와 같은지 검증해요. | Equals(grp, admin) |
| Prefix | key의 값이 value를 접두사로 갖는지 검증해요. | Prefix(referrer, http://example.com) |
| Contains (string) | key의 값이 value를 포함하는지 검증해요. | Contains(referrer, /foo/) |
| Contains (array) | key 배열이 value를 포함하는지 검증해요. | Contains(areas, home) |
| SplitContains | key의 값을 구분자로 나눴을 때 value를 포함하는지 검증해요. | SplitContains(scope, , writer) |
| OneOf | key 배열이 values 중 하나를 포함하는지 검증해요. | OneOf(areas, office, lab) |
모든 함수는 불리언 연산자로 결합할 수 있어요. 지원되는 연산자는 다음과 같아요:
| Operand | Description | Example |
| && | 두 함수를 비교해서 둘 다 참일 때만 참을 반환해요. | Equals(grp, admin) && Equals(active, true) |
| || | 두 함수를 비교해서 둘 중 하나라도 참이면 참을 반환해요. | Equals(grp, admin) || Equals(active, true) |
| ! | 함수가 참이면 false를, 그 외에는 참을 반환해요. | !Equals(grp, testers) |
다음 데이터 구조에서는 모든 예시가 참을 반환해요:
JSON
{
"active": true,
"grp": "admin",
"scope": "reader writer deploy",
"referrer": "http://example.com/foo/bar",
"areas": [
"office",
"home"
]
}
중첩 클레임 (Nested Claims)
키 사이에 .를 사용해 중첩 클레임을 지원해요. 예를 들어:
Key
user.name
Claims
{
"active": true,
"grp": "admin",
"scope": "reader writer deploy",
"referrer": "http://example.com/foo/bar",
"areas": [
"office",
"home"
],
"user": {
"name": "John Snow",
"status": "undead"
}
}
Result
John Snow
.을 포함하는 키 처리
key에 점이 포함되어 있으면 \.로 이스케이프할 수 있어요.
\를 포함하는 키 처리
key에 \가 포함되어 있으면 \\로 두 번 적어야 합니다.
clientConfig
API 게이트웨이를 Identity Provider 같은 서드파티 소프트웨어에 연결하는 데 사용하는 구성을 정의해요.
clientConfig.tls
Kubernetes secret에 비밀 값 저장하기
tls.ca, tls.cert, tls.key를 구성할 때, Middleware와 같은 네임스페이스에 정의된 Kubernetes secret을 참조할 수 있어요. Kubernetes secret에 대한 참조는 URN 형식을 취합니다:
urn:k8s:secret:[name]:[valueKey]
Middleware JWT
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-jwt
spec:
plugin:
jwt:
clientConfig:
tls:
ca: "urn:k8s:secret:tls:ca"
cert: "urn:k8s:secret:tls:cert"
key: "urn:k8s:secret:tls:key"
insecureSkipVerify: true
Kubernetes TLS Secret
apiVersion: v1
kind: Secret
metadata:
name: tls
stringData:
ca: |-
-----BEGIN CERTIFICATE-----
MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
98TwDIK/39WEB/V607As+KoYazQG8drorw==
-----END CERTIFICATE-----
cert: |-
-----BEGIN CERTIFICATE-----
MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
98TwDIK/39WEB/V607As+KoYazQG8drorw==
-----END CERTIFICATE-----
key: |-
[REDACTED PRIVATE KEY]
jwksFile
JWT 헤더 키 ID
JWT 헤더에 kid 헤더가 있으면, 미들웨어는 JWK를 찾을 것으로 기대해요. JWK를 찾지 못하면 401 Unauthorized 오류를 반환합니다.
jwksUrl
JWT 헤더 키 ID
JWT 헤더에 kid 헤더가 있으면, 미들웨어는 JWK를 찾을 것으로 기대해요. JWK를 찾지 못하면 401 Unauthorized 오류를 반환합니다.
JWT 발급자 클레임
jwksUrl이 경로로 설정되어 있고, 검증하려는 JWT에 iss 속성이 없으면, 미들웨어는 401 Unauthorized 오류를 반환합니다.
signingSecret
Kubernetes secret에 비밀 값 저장하기
signingSecret을 구성할 때, Middleware와 같은 네임스페이스에 정의된 Kubernetes secret을 참조할 수 있어요. Kubernetes secret에 대한 참조는 URN 형식을 취합니다:
urn:k8s:secret:[name]:[valueKey]
Traefik OSS를 프로덕션에서 사용하시나요?
직장에서 Traefik을 사용한다면, 엔터프라이즈급 API 게이트웨이 기능이나 Traefik OSS 상용 지원을 추가하는 것을 고려해 보세요.
-
API Gateway 데모 영상 보기
-
24/7/365 OSS 지원 요청
Traefik OSS에 API 게이트웨이 기능을 추가하는 것은 빠르고 매끄러워요. 기존 구성을 교체하거나(rip and replace) 버릴 필요 없이 그대로 유지됩니다. 짧은 영상으로 직접 확인해 보세요.