컨텐츠를 불러오는 중...
.
으로 각 줄이 구분이 되어 있는 것을 확인할 수 있습니다. 위에서 부터 header, payload, signature에 해당합니다.signed
할 경우 데이터를 encrypted
, decrypted
하는 경우 사용이 됩니다.type
헤더는 JWT 자체의 미디어 타입을 설정하는 헤더 속성입니다. JOSE(Javascript Object Signing and Encryption) 헤더
를 포함하는 다른 객체들과 JWT가 혼합될 가능성이 있는 경우를 돕기 위한 용도로 사용이 됩니다. 하지만 실제로 이러한 경우는 거의 발생하지 않습니다.cty
헤더는 콘텐츠 타입을 설정하는 헤더 속성입니다. 대부분의 JWT는 특정 클레임(Claim)과 임이의 데이터를 페이로드로 포함합니다. 이러한 경우 cty
클레임은 설정이 되지 않아야 합니다. cty
를 설정하는 경우는 페이로드에 또 다른 JWT를 중첩하여 사용하는 경우 반드시 cty
를 JWT로 설정 해주어야 합니다.클레임(Claim)
을 표준화한다는 점에 있다. JWT는 Payload에 특정 정보를 담는 구조를 가지고 있으며, 이때 담기는 정보를 클레임(Claim)
이라고 표현합니다.sub 클레임
입니다.sub claim
은 JWT가 나타내는 대상(Subject)
을 식별하는 역할을 수행합니다. sub claim
은 인증 및 권한 부여 시스템에서 사용자의 ID나 엔터티를 명확하게 식별하는 역할을 수행합니다.JSON Web Signatures(JWS)
를 이용하여 서명을 할 수 있으며, 또한 JSON Web Encryption
을 사용하여 JWT를 암호화할 수도 있습니다.웹에서Signing(셔명)
하는 것의 의미 웹에서 서명은 데이터의 무결성과 인증을 보장하기 위해 디지털 서명을 추가하는 과정을 의미합니다. 즉, 데이터가 변겨오디지 않았음을 증명하고, 특정한 주체가 생성했다는 것을 보장하는 방식을 이야기 합니다.
header
, payload
, signature
로 구성이 되어 있다. 이 세가지 부분은 서로 다르게 인코딩이 진행이 된다. 이 3가지 파트 중 signature
를 삭제하여 헤더를 변경하여 JWT가 unsigned
한 것처럼 속일 수 있습니다.user
였지만 admin
으로 수정하여 사용이 가능하기 때문입니다.unsigned
일 경우 절대 유효한 경우로 판단하지 않으면 됩니다. 또한 JWT를 신뢰할 수 없는 환경, 클라이언트에 저장하지 않으면 됩니다.img
태그에 포함되어 있는 페이지가 로드될 때 마다 http://target.site.com/add-user?user=name&grant=admin
으로 요청을 보냅니다. 만약 사용자가 이전에 target.site.com
에 로그인했고, 해당 사이트가 쿠키를 이용해 세션을 유지할 경우 이 요청과 함께 로그인된 세션 쿠키도 같이 전송이 될 것입니다.CSRF 방어 기법
에 대해서 설명해보겠습니다. 특정 HTTP 헤더를 요청에 추가하여 올바른 출처에서 수행된 요청인지 확인하는 방법이 있습니다. 이 특정 HTTP 헤더를 요청에 추가하고 검증하는 과정은 세션을 생성 헀던 서버에서만 포함이 되기 때문에 공격하는 서버에는 포함이 되지 않아 검증 과정을 가질 수 있습니다.Expire
또는 Max-Age
속성을 설정하지 않는 것입니다. 브라우저는 이 속성이 없는 쿠키를 세션 쿠키로 인식하고 브라우저 종료 시 삭제하게 됩니다.XSS
공격을 당할 수 있습니다.https://cloud.digitalocean.com/v1/oauth/authorize
: API의 인가 엔드포인트(Authorization Endpoint)client_id=CLIENT_ID
: 애플리케이션의 클라이언트 ID(API가 애플리케이션을 식별하는 방식)redirect_uri=CALLBACK_URL
: 사용자가 애플리케이션을 승인한 후 리디렉션될 URIresponse_type=code
: 애플리케이션이 인가 코드(Authorization Code) 부여 유형을 요청하고 있음을 나타냄scope=read
: 애플리케이션이 요청하는 액세스 범위(예: 읽기 권한)example.com
일 경우 위와 같은 형태의 리다이렉션이 발생합니다.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9. TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
Figure 1: Abstract Protocol Flow
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(B)
+----|-----+ Client Identifier +---------------+
| -+----(A)-- & Redirection URI ---->| |
| User- | | Authorization |
| Agent -+----(B)-- User authenticates --->| Server |
| | | |
| -+----(C)-- Authorization Code ---<| |
+-|----|---+ +---------------+
| | ^ v
(A) (C) | |
| | | |
^ v | |
+---------+ | |
| |>---(D)-- Authorization Code ---------' |
| Client | & Redirection URI |
| | |
| |<---(E)----- Access Token -------------------'
+---------+ (w/ Optional Refresh Token)
Note: The lines illustrating steps (A), (B), and (C) are broken into
two parts as they pass through the user-agent.
Figure 3: Authorization Code Flow
https://cloud.digitalocean.com/v1/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read
API authorization endpoint/client_id/redirect_id/response_type/scope 로 구성됩니다
https://example.com/callback?code=AUTHORIZATION_CODE
{
"alg": "HS256",
"type": "JWT", // optional
"cty": "JWT" // optional
}
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
{
"alg" : "HS256",
"typ" : "JWT"
}
{
"sub": "1234567890", "name": "John Doe", "admin": true
}
{
"iss": "auth.example.com", // 토큰 발급자 (Issuer)
"sub": "user-12345", // 이 토큰의 주체 (Subject) -> 사용자 ID
"aud": "my-app", // 이 토큰을 사용할 대상 (Audience)
"exp": 1717045200 // 만료 시간 (Expiration)
}
{
"access_token": "ACCESS_TOKEN",
"token_type": "bearer",
"expires_in": 2592000,
"refresh_token": "REFRESH_TOKEN",
"scope": "read",
"uid": 100101,
"info": {
"name": "Mark E. Mark",
"email": "mark@thefunkybunch.com"
}
}
<!-- 이 태그가 악성 사이트에 삽입됨 -->
<img src="http://target.site.com/add-user?user=name&grant=admin" />