인증 헤더 만들기
REST API 요청 포맷
REST API는 HTTP를 통해 호출이 이루어집니다.
POST, PUT, DELETE 요청에 body가 존재하는 경우 JSON 형식으로 파라미터를 전송해야 합니다.
유효한 컨텐츠 타입의 예시는 다음과 같으며, 각 프로그래밍 언어 라이브러리에 따라 약간의 차이가 있을 수 있습니다.
Content-Type: application/json; charset=utf-8
JWT 인증 토큰 만들기
REST API 요청시, 발급받은 API Key
와 Secret Key
로 토큰을 생성하여 Authorization
헤더를 통해 전송합니다. 토큰은 JWT(https://jwt.io) 형식을 따릅니다.
서명 방식은 HS256
을 권장하며, 서명에 사용할 Secret은 발급받은 Secret Key
를 사용합니다.
페이로드의 구성은 다음과 같습니다.
Private API 요청 시 발급받은 API Key
와 Secret Key
를 이용하여 5개의 파라미터를 헤더에 추가하여 전송합니다.
요청 변수 | 설명 | 타입 |
---|---|---|
access_key | 사용자 API Key | String / 필수 |
nonce | 무작위의 UUID 문자열 | String / 필수 |
timestamp | 현재의 시간을 밀리초 (millisecond, ms)로 표현한 값 (예 : 1655280216476) | Number / 필수 |
query_hash | 해싱된 query string (파라미터가 있을 경우 필수) | String / 옵션 |
query_hash_alg | query_hash를 생성하는 데에 사용한 알고리즘 (기본값 : SHA512) | String / 옵션 |
생성된 인증 헤더의 페이로드 예시입니다.
{
"access_key": "L7rVaYfBIc2BDsnlQGfkR93d6DoOAJCw7mJr5Eso",
"nonce": "6f5570df-d8bc-4daf-85b4-976733feb624",
"timestamp": 1712230310689,
"query_hash": "1c2362ca9d79947582cae192acf63efb8756caa49af1eb64b12ba45617165431a3dd3e47d0476bc2a347b7a1ea512db7f316f56144084b1493166e3c9113a8eb",
"query_hash_alg": "SHA512"
}
(예시) 파라미터가 없을 경우
const jwt = require('jsonwebtoken')
const { v4: uuidv4 } = require('uuid')
const accessKey = '발급받은 API KEY'
const secretKey = '발급받은 SECRET KEY'
const payload = {
access_key: accessKey,
nonce: uuidv4(),
timestamp: Date.now()
};
console.log(payload);
const jwtToken = jwt.sign(payload, secretKey)
const authorizationToken = `Bearer ${jwtToken}`
console.log(authorizationToken);
# Python 3
# pip3 installl pyJwt
import jwt
import uuid
import time
accessKey = "발급받은 API KEY"
secretKey = "발급받은 SECRET KEY"
payload = {
'access_key': accessKey,
'nonce': str(uuid.uuid4()),
'timestamp': round(time.time() * 1000)
}
print(payload, "\n")
jwt_token = jwt.encode(payload, secretKey)
authorization_token = 'Bearer {}'.format(jwt_token)
print(authorization_token)
// https://mvnrepository.com/artifact/com.auth0/java-jwt
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.UUID;
public class OpenAPIAuthSampleNoArgs {
public static void main(String[] args) {
String accessKey = "발급받은 API KEY";
String secretKey = "발급받은 SECRET KEY";
Algorithm algorithm = Algorithm.HMAC256(secretKey);
String jwtToken = JWT.create()
.withClaim("access_key", accessKey)
.withClaim("nonce", UUID.randomUUID().toString())
.withClaim("timestamp", System.currentTimeMillis())
.sign(algorithm);
String authenticationToken = "Bearer " + jwtToken;
System.out.println(authenticationToken);
}
}
(예시) 파라미터가 있는 경우
HTTP 쿼리 문자열, 혹은 body를 통해 파라미터를 전달하는 경우 모두 JWT 페이로드의 query_hash 값을 설정해야합니다.
파라미터의 자료형 중 배열이 존재하는 경우, 올바른 query string의 형태는 다음과 같습니다.
key[]=value1&key[]=value2 ...
이와 다른 형태로 요청하면 토큰 검증에 실패할 수 있으니 유의하시기 바랍니다.
const jwt = require('jsonwebtoken');
const { v4: uuidv4 } = require('uuid');
const crypto = require('crypto');
const querystring = require('querystring');
const accessKey = '발급받은 API KEY'
const secretKey = '발급받은 SECRET KEY'
// GET (query parameters)
// const query = 'string=abc&number=123'
// POST (request body)
const query = querystring.encode({
string: 'abc',
number: 123
})
const alg = 'SHA512'
const hash = crypto.createHash(alg)
const queryHash = hash.update(query, 'utf-8').digest('hex')
const payload = {
access_key: accessKey,
nonce: uuidv4(),
timestamp: Date.now(),
query_hash: queryHash,
query_hash_alg: alg
};
console.log(payload);
const jwtToken = jwt.sign(payload, secretKey)
const authorizationToken = `Bearer ${jwtToken}`
console.log(authorizationToken);
# Python 3
# pip3 installl pyJwt
import jwt
import uuid
import hashlib
import time
from urllib.parse import urlencode
accessKey = "발급받은 API KEY"
secretKey = "발급받은 SECRET KEY"
# GET (query parameters)
# query = 'string=abc&number=123'.encode()
# POST (request body)
query = urlencode(dict( string="abc", number=123 )).encode()
hash = hashlib.sha512()
hash.update(query)
query_hash = hash.hexdigest()
payload = {
'access_key': accessKey,
'nonce': str(uuid.uuid4()),
'timestamp': round(time.time() * 1000),
'query_hash': query_hash,
'query_hash_alg': 'SHA512',
}
print(payload, "\n")
jwt_token = jwt.encode(payload, secretKey)
authorization_token = 'Bearer {}'.format(jwt_token)
print(authorization_token)
// https://mvnrepository.com/artifact/com.auth0/java-jwt
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
// https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class OpenAPIAuthSampleArgs {
public static void main(String[] args) throws NoSuchAlgorithmException {
String accessKey = "발급받은 API KEY";
String secretKey = "발급받은 SECRET KEY";
// GET (query parameters)
// String query = "string=abc&number=123";
// POST (request body)
List<NameValuePair> queryParams = new ArrayList<>();
queryParams.add(new BasicNameValuePair("string", "abc"));
queryParams.add(new BasicNameValuePair("number", "123"));
String query = URLEncodedUtils.format(queryParams, StandardCharsets.UTF_8);
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(query.getBytes(StandardCharsets.UTF_8));
String queryHash = String.format("%0128x", new BigInteger(1, md.digest()));
Algorithm algorithm = Algorithm.HMAC256(secretKey);
String jwtToken = JWT.create()
.withClaim("access_key", accessKey)
.withClaim("nonce", UUID.randomUUID().toString())
.withClaim("timestamp", System.currentTimeMillis())
.withClaim("query_hash", queryHash)
.withClaim("query_hash_alg", "SHA512")
.sign(algorithm);
String authenticationToken = "Bearer " + jwtToken;
System.out.println(authenticationToken);
}
}
Updated 5 months ago