블로그 | NGINX

JWT 및 NGINX Plus를 사용하여 API 클라이언트 인증

NGINX-F5-수평-검정-유형-RGB의 일부
리엄 크릴리 썸네일
리암 크릴리
2021년 12월 2일 게시

JSON 웹 토큰(JWT, "조트"로 발음)은 신원 정보를 교환하는 간편하고 휴대성이 뛰어난 수단입니다. 그 JWT 사양 의 중요한 토대가 되었습니다. 오픈아이디 커넥트OAuth 2.0 생태계에 대한 단일 로그인 토큰을 제공합니다. JWT는 그 자체로 인증 자격 증명으로 사용할 수도 있으며 기존 API 키보다 웹 기반 API에 대한 액세스를 제어하는 더 나은 방법입니다.

NGINX Plus R10 이상에서는 JWT를 직접 검증할 수 있습니다. 이 블로그 게시물에서는 NGINX Plus를 API 게이트웨이로 사용하여 API 엔드포인트에 대한 프런트엔드를 제공하고 JWT를 사용하여 클라이언트 애플리케이션을 인증하는 방법을 설명합니다.

네이티브 JWT 지원은 NGINX Plus에서만 제공되며 NGINX Open Source에서는 제공되지 않습니다.

편집자 – 이 블로그 게시물은 업데이트됨 2021년 12월에 사용하기 위해 인증_jwt_요구 지침이 도입됨 NGINX 플러스 R25. 해당 지침에 대한 자세한 내용은 NGINX Plus R25를 발표하는 블로그의 사용자 지정 JWT 검증 규칙을 참조하세요.

NGINX Plus R15 이상은 또한 대부분의 주요 ID 공급자와의 통합을 가능하게 하는 OpenID Connect 1.0의 "인증 코드 흐름"을 제어할 수 있습니다. 자세한 내용은 NGINX Plus R15 발표<.htmlspan>를 참조하세요.

JWT의 해부학

JWT는 헤더, 페이로드, 서명의 세 부분으로 구성됩니다. 전송 시 다음과 같이 보입니다. 가독성을 위해 줄 바꿈을 추가했고(실제 JWT는 단일 문자열임) 세 부분을 구분하기 위해 색상 코딩을 추가했습니다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 .ewogICAgInN1YiI6ICJsYzEiLAogICAgImVtYWlsIjogImxpYW0uY3JpbGx5QG5naW54LmNvbSIsCn0 = .VGYHWPterIaLjRi0LywgN3jnDUQbSsFptUw99g2slfc

표시된 대로 마침표( . )는 헤더, 페이로드 및 서명을 구분합니다. 헤더와 페이로드는 Base64로 인코딩된 JSON 객체입니다. 서명은 alg 헤더에서 지정한 알고리즘을 사용하여 암호화됩니다. 이는 샘플 JWT를 디코딩하면 확인할 수 있습니다.

  인코딩됨 디코딩됨
헤더 eyJhbGciOiJIUzI1NiIsInR5cCI6Ik
pXVCJ9
{
"알그": "HS256",
"일반": "JWT"
}
유효 탑재량 ewogICAgInN1YiI6ICJsYzEiLAogICAgImVtYWlsIjogImxpYW0uY3JpbGx5QG5naW54LmNvbSIsCn0= {
"sub": "lc1",
"이메일": "liam.crilly@nginx.com",
}

JWT 표준은 여러 가지 서명 알고리즘을 정의합니다. 우리 예제에서 HS256 값은 HMAC SHA‑256을 참조하는데, 이 블로그 게시물의 모든 샘플 JWT에 이 값을 사용합니다. NGINX Plus는 표준 에 정의된 HS xxx , RS xxx , ES xxx 시그니처 알고리즘을 지원합니다. JWT에 암호화 서명을 할 수 있는 기능은 인증 자격 증명으로 사용하기에 이상적입니다.

API 키로서의 JWT

API 클라이언트(API 리소스를 요청하는 원격 소프트웨어 클라이언트)를 인증하는 일반적인 방법은 일반적으로 API 키 라고 하는 공유 비밀을 사용하는 것입니다. 기존 API 키는 기본적으로 클라이언트가 각 요청에 추가 HTTP 헤더로 전송하는 길고 복잡한 비밀번호입니다. 제공된 API 키가 유효한 키 목록에 있는 경우 API 엔드포인트는 요청된 리소스에 대한 액세스를 부여합니다. 일반적으로 API 엔드포인트는 API 키를 직접 검증하지 않습니다. 대신 API 게이트웨이가 인증 프로세스를 처리하고 각 요청을 적절한 엔드포인트로 라우팅합니다. 계산적 오프로드 외에도 이는 높은 가용성 및 여러 API 엔드포인트에 대한 부하 분산과 같은 역방향 프록시와 함께 제공되는 이점을 제공합니다.

기존 API 키를 사용한 API 클라이언트 및 JWT 인증
API 게이트웨이는 요청을 전달하기 전에 키 레지스트리를 참조하여 API 키를 검증합니다.
API 엔드포인트로

다양한 API 클라이언트에 서로 다른 액세스 제어 및 정책을 적용하는 것은 일반적입니다. 기존 API 키를 사용하는 경우 API 키와 속성 집합을 일치시키기 위해 조회가 필요합니다. 각 요청마다 이러한 조회를 수행하면 시스템의 전체 지연 시간에 당연히 영향을 미칩니다. JWT를 사용하면 이러한 속성이 내장되므로 별도로 조회할 필요가 없습니다.

JWT를 API 키로 사용하면 기존 API 키에 비해 성능이 뛰어난 대안을 제공하며, 모범 사례 인증 기술과 ID 속성을 교환하기 위한 표준 기반 스키마를 결합합니다.

JWT 및 NGINX Plus를 사용한 API 클라이언트 및 JWT 인증
NGINX Plus는 요청을 API 엔드포인트로 전달하기 전에 JWT를 검증합니다.

NGINX Plus를 인증 API 게이트웨이로 구성

JWT를 검증하기 위한 NGINX Plus 구성은 매우 간단합니다.

업스트림 api_server {
서버 10.0.0.1;
서버 10.0.0.2;
}

server {
listen 80;

location /products/ {
auth_jwt "제품 API";
auth_jwt_key_file conf/api_secret.jwk;
proxy_pass http://api_server;
}
}

가장 먼저 하는 일은 업스트림 블록에서 API 엔드포인트를 호스팅하는 서버의 주소를 지정하는 것입니다. 위치 블록은 /products/ 로 시작하는 URL에 대한 모든 요청이 인증되어야 함을 지정합니다. auth_jwt 지시문은 반환될 인증 영역을 정의합니다.401 인증이 실패하면 상태 코드가 반환됩니다.

auth_jwt_key_file 지시어는 NGINX Plus에 JWT의 서명 요소를 검증하는 방법을 알려줍니다. 이 예제에서는 HMAC SHA‑256 알고리즘을 사용하여 JWT에 서명하므로 서명에 사용되는 대칭 키를 포함하기 위해 conf/api_secret.jwk 에 JSON 웹 키를 생성해야 합니다. 해당 파일은 JSON 웹 키 사양 에 기술된 형식을 따라야 합니다. 예시는 다음과 같습니다.

{"키":
[{
"k":"ZmFudGFzdGljand0",
"kty":"10월",
"아이":"0001"
}]
}

대칭 키는 k 필드에 정의되어 있으며 여기는 평문 문자열 fantasticjwtBase64URL로 인코딩된 값입니다. 다음 명령을 실행하여 인코딩된 값을 얻었습니다.

$ echo -n fantasticjwt | base64 | tr '+/' '-_' | tr -d '='

kty 필드는 키 유형을 대칭 키(옥텟 시퀀스)로 정의합니다. 마지막으로, kid (키 ID) 필드는 이 JSON 웹 키에 대한 일련 번호를 정의합니다.0001 이를 통해 동일한 파일( auth_jwt_key_file 지시문으로 명명)에서 여러 키를 지원하고 해당 키와 해당 키로 서명된 JWT의 수명 주기를 관리할 수 있습니다.

이제 API 클라이언트에 JWT를 발행할 준비가 되었습니다.

API 클라이언트에 JWT 발급

샘플 API 클라이언트로서, "견적 시스템" 애플리케이션을 사용하고 API 클라이언트에 대한 JWT를 생성하겠습니다. 먼저 JWT 헤더를 정의합니다.

{
"typ":"JWT",
"alg":"HS256",
"kid":"0001"
}

typ 필드는 유형을 JSON 웹 토큰으로 정의하고, alg 필드는 JWT가 HMAC SHA256 알고리즘으로 서명되었음을 지정하고, kid 필드는 JWT가 해당 일련 번호가 있는 JSON 웹 키로 서명되었음을 지정합니다.

다음으로 JWT 페이로드를 정의합니다.

{
"name":"견적 시스템",
"sub":"인용문",
"iss":"내 API 게이트웨이"
}

하위 (제목) 필드는 이름 필드의 전체 값에 대한 고유 식별자입니다. iss 필드는 JWT 발급자를 설명하는 데, 이는 API 게이트웨이가 타사 발급자 또는 중앙 집중식 ID 관리 시스템의 JWT도 허용하는 경우에 유용합니다.

이제 JWT를 만드는 데 필요한 모든 것을 갖추었으므로 다음 단계에 따라 JWT를 올바르게 인코딩하고 서명합니다. 명령과 인코딩된 값은 가독성을 위해 여러 줄에 나타납니다. 실제로는 각각이 한 줄로 입력되거나 나타납니다.

  1. 헤더와 페이로드를 별도로 평면화하고 Base64URL로 인코딩합니다.

     

    $ echo -n '{"typ":"JWT","alg":"HS256","kid":"0001"}' | base64 | tr '+/' '-_' | tr -d '=' eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjAwMDEifQ $ echo -n '{"name":"견적 시스템","sub":"인용문","iss":"내 API 게이트웨이"}' | base64 | tr '+/' '-_' | tr -d '=' eyJuYW1lIjoiUXVvdGF0aW9uIFN5c3RlbSIsInN1YiI6InF1b3RlcyIsImlzcyI6Ik 15IEFQSSBHYXRld2F5In0
    
  2. 인코딩된 헤더와 페이로드를 마침표(.)로 연결하고 그 결과를 HEADER_PAYLOAD 변수에 할당합니다.

    $ 헤더 페이로드=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjAwMDEifQ.eyJuYW1lIjoiUXVvdGF0aW9uIFN5c3RlbSIsInN1YiI6InF1b3RlcyIsIm lzcyI6Ik15IEFQSSBHYXRld2F5In0
    
  3. 헤더와 페이로드에 대칭 키로 서명하고 서명을 Base64URL로 인코딩합니다.

    $ echo -n $HEADER_PAYLOAD | openssl dgst -binary -sha256 -hmac fantasticjwt | base64 | tr '+/' '-_' | tr -d '=' ggVOHYnVFB8GVPE-VOIo3jD71gTkLffAY0hQOGXPL2I
    
  4. 인코딩된 서명을 헤더와 페이로드에 추가합니다.

    $ echo $HEADER_PAYLOAD.ggVOHYnVFB8GVPE-VOIo3jD71gTkLffAY0hQOGXPL2I > quotes.jwt
    
  5. API 게이트웨이에 인증된 요청을 만들어 테스트합니다(이 예에서 게이트웨이는 로컬호스트에서 실행 중입니다).

    $ curl -H "권한 부여: 전달자 `cat quotes.jwt`" http://localhost/products/widget1
    

5단계의 curl 명령은 JWT를 Bearer Token 형태로 NGINX Plus에 전송하는데, 이는 NGINX Plus가 기본적으로 기대하는 것입니다. NGINX Plus는 쿠키나 쿼리 문자열 매개변수에서 JWT를 얻을 수도 있습니다. 이를 구성하려면 auth_jwt 지시문에 token= 매개변수를 포함합니다. 예를 들어, 다음 구성을 사용하면 NGINX Plus는 이 curl 명령으로 전송된 JWT를 검증할 수 있습니다.

$ curl http://localhost/products/widget1?apijwt=`cat quotes.jwt`
서버 { 수신 80; 위치 /products/ { auth_jwt "제품 API" 토큰=$arg_apijwt ; auth_jwt_key_file conf/api_secret.jwk; proxy_pass http://api_server; } }

NGINX Plus를 구성하고 위에 표시된 대로 JWT를 생성하고 검증하면 JWT를 API 클라이언트 개발자에게 보내고 각 API 요청과 함께 JWT를 제출하는 데 사용할 메커니즘에 동의할 준비가 됩니다.

로깅 및 속도 제한을 위한 JWT 클레임 활용

인증 자격 증명으로서 JWT의 주요 장점 중 하나는 JWT 및 해당 페이로드와 관련된 엔터티(예: 발급자, 발급된 사용자, 의도된 수신자)를 나타내는 "클레임"을 전달한다는 것입니다. NGINX Plus는 JWT를 검증한 후 헤더와 페이로드에 있는 모든 필드에 변수로 접근할 수 있습니다. 원하는 필드 앞에 $jwt_header_ 또는 $jwt_claim_을 접두사로 붙여서 접근합니다(예: 하위 클레임의 경우 $jwt_claim_sub ). 즉, API 자체에서 JWT 처리를 구현할 필요 없이 JWT에 포함된 정보를 API 엔드포인트에 매우 쉽게 프록시할 수 있다는 의미입니다.

이 구성의 예는 일부 고급 기능을 보여줍니다.

log_format jwt '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" "$http_user_agent" ' '$jwt_header_alg $jwt_claim_sub' ; limit_req_zone $jwt_claim_sub zone=10rps_per_client:1m rate=10r/s; server { listen 80; location /products/ { auth_jwt "제품 API"; auth_jwt_key_file conf/api_secret.jwk; limit_req zone=10rps_per_client; proxy_pass http://api_server; proxy_set_header API-클라이언트 $jwt_claim_sub; access_log /var/log/nginx/access_jwt.log jwt; } }

log_format 지시어는 jwt 라는 새로운 형식을 정의하는데, 이는 두 개의 추가 필드인 $jwt_header_alg$jwt_claim_sub 로 공통 로그 형식을 확장합니다. 위치 블록 내에서 access_log 지시어를 사용하여 검증된 JWT에서 얻은 값으로 로그를 작성합니다.

이 예에서는 IP 주소가 아닌 API 클라이언트별로 API 속도 제한을 제공하기 위해 클레임 기반 변수를 사용하고 있습니다. 이 기능은 여러 API 클라이언트가 단일 포털에 내장되어 있고 IP 주소로 구분할 수 없는 경우에 특히 유용합니다. limit_req_zone 지시어는 JWT 하위 클레임을 키로 사용하여 속도 제한을 계산한 다음 limit_req 지시어를 포함하여 위치 블록에 적용합니다.

마지막으로 요청이 API 엔드포인트로 프록시될 때 JWT 주제를 새로운 HTTP 헤더로 제공합니다. proxy_set_header 지시문은 API 엔드포인트가 쉽게 사용할 수 있는 API‑Client 라는 HTTP 헤더를 추가합니다. 따라서 API 엔드포인트는 JWT 처리 로직을 구현할 필요가 없습니다. API 엔드포인트 수가 늘어날수록 이러한 기능은 점점 더 중요해집니다.

JWT 취소

때때로 API 클라이언트의 JWT를 취소하거나 다시 발급해야 할 수 있습니다. 간단한 블록을 auth_jwt_require 지시어와 결합하면 JWT의 만료 날짜( exp 클레임에 표현됨)에 도달할 때까지 JWT를 유효하지 않은 것으로 표시하여 API 클라이언트에 대한 액세스를 거부할 수 있습니다. 이 시점에서 해당 JWT에 대한 항목을 안전하게 제거할 수 있습니다.

이 예에서 우리는 $jwt_status 변수를 다음과 같이 설정합니다.0 또는1 토큰의 하위 클레임 값에 따라( $jwt_claim_sub 변수에서 캡처한 대로) 그런 다음 위치 블록에서 auth_jwt_require 지시어를 사용하여 토큰을 추가로 검증(또는 거부)합니다. 유효하려면 $jwt_상태 변수는 비어있거나 동일할 수 없습니다. 에게 0 (영).

지도 $jwt_claim_sub $jwt_status { "인용" 0; "테스트" 0; 기본값 1; } 서버 { 수신 80; 위치 /products/ { auth_jwt "제품 API"; auth_jwt_key_file conf/api_secret.jwk; auth_jwt_require $jwt_status; proxy_pass http://api_server; } }

요약

JSON 웹 토큰은 API에 대한 인증된 액세스를 제공하는 데 적합합니다. API 클라이언트 개발자 입장에서는 기존 API 키와 마찬가지로 쉽게 처리할 수 있으며, 데이터베이스 조회가 필요한 ID 정보를 API 게이트웨이에 제공합니다. NGINX Plus는 JWT 자체에 포함된 정보를 기반으로 JWT 인증 및 정교한 구성 솔루션을 지원합니다. NGINX Plus를 다른 API 게이트웨이 기능과 결합하면 속도, 안정성, 확장성, 보안을 갖춘 API 기반 서비스를 제공할 수 있습니다.

NGINX Plus에서 JWT를 직접 사용해보려면 오늘 무료 30일 평가판을 시작하거나 저희에게 문의하여 사용 사례에 대해 논의하세요 .


"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."