인증 가능한 요청 만들기

REST API 요청 포맷

REST API는 HTTP를 통해 호출이 이루어집니다.

POST, PUT, DELETE 요청에 body가 존재하는 경우 JSON 형식으로 파라미터를 전송해야 합니다.
유효한 컨텐츠 타입의 예시는 다음과 같으며, 각 프로그래밍 언어 라이브러리에 따라 약간의 차이가 있을 수 있습니다.

Content-Type: application/json; charset=utf-8

❗️

v1.3.0 업데이트 : urlencoded form 지원 종료 (2022. 3. 1.)

2022년 3월부터 urlencoded form 형식을 이용한 HTTP body 요청은 지원이 종료되었습니다.
이에 따라 urlencoded form 형식에 대한 기능 추가 및 개발자 센터 지원은 더 이상 이루어지지 않습니다.

안정적인 서비스 이용을 위하여 빠른 시일 내에 JSON 형식으로의 전환을 부탁드립니다.

자세한 변경사항은 공지사항을 참조해주세요.

JWT 인증 토큰 만들기

REST API 요청시, 발급받은 access keysecret key로 토큰을 생성하여 Authorization 헤더를 통해 전송합니다. 토큰은 JWT(https://jwt.io) 형식을 따릅니다.

서명 방식은 HS256 을 권장하며, 서명에 사용할 secret은 발급받은 secret key를 사용합니다.
페이로드의 구성은 다음과 같습니다.

{
  "access_key": "발급 받은 acccess key (필수)",
  "nonce": "무작위의 UUID 문자열 (필수)",
  "query_hash": "해싱된 query string (파라미터가 있을 경우 필수)",
  "query_hash_alg": "query_hash를 생성하는 데에 사용한 알고리즘 (기본값 : SHA512)"
}

❗️

v1.3.0 업데이트 : 기존 인증방식 지원 종료 (2022. 3. 1.)

2022년 3월부터 query 필드를 이용한 JWT 페이로드 생성 방식은 지원이 종료되었습니다.
query_hashquery_hash_alg 필드를 이용한 생성 방식을 이용해주시기 바랍니다.

자세한 변경사항은 공지사항을 참조해주세요.

🚧

페이로드의 query_hash 값을 생성할 때 사용하는 쿼리는 인코딩 되지 않은 쿼리 문자열 형식이어야 합니다. JSON 및 기타 포멧은 허용되지 않습니다.

🚧

Signature 생성시 secret 인코딩 옵션을 확인해주세요. 발급된 secret key는 base64로 encoding 되어있지 않습니다. JWT 관련 library를 사용하신다면 해당 옵션을 확인해주세요.

(예시) 파라미터가 없을 경우

const jwt = require("jsonwebtoken");
const uuidv4 = require("uuid/v4");

const payload = {
  access_key: "발급받은 Access key",
  nonce: uuidv4(),
};

const jwtToken = jwt.sign(payload, "발급받은 Secret key");
const authorizationToken = `Bearer ${jwtToken}`;
# Python 3

import jwt   # PyJWT 
import uuid

payload = {
    'access_key': '발급받은 Access Key',
    'nonce': str(uuid.uuid4()),
}

jwt_token = jwt.encode(payload, '발급받은 Secret Key')
authorization_token = 'Bearer {}'.format(jwt_token)
#!/usr/bin/env ruby

require 'securerandom'
require 'bundler/inline'
gemfile do
  source 'https://rubygems.org'
  gem 'jwt'
end

payload = {
    access_key: '발급받은 Access key',
    nonce: SecureRandom.uuid,
}

jwt_token = JWT.encode(payload, '발급받은 Secret key', 'HS256')
authorize_token = "Bearer #{jwt_token}"
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

import java.util.UUID;

public class OpenApiSample {

    public static void main(String[] args) {
        String accessKey = "발급받은 Access key";
        String secretKey = "발급받은 Secret key";

        Algorithm algorithm = Algorithm.HMAC256(secretKey);

        String jwtToken = JWT.create()
                             .withClaim("access_key", accessKey)
                             .withClaim("nonce", UUID.randomUUID().toString())
                             .sign(algorithm);

        String authenticationToken = "Bearer " + jwtToken;
    }
}
using System;
using System.Text;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;

public class OpenAPISample {
    public static void Main() {
        var payload = new JwtPayload
        {
            { "access_key", "발급받은 Access Key" },
            { "nonce", Guid.NewGuid().ToString() },
            { "query_hash", queryHash },
            { "query_hash_alg", "SHA512" }
        };

        byte[] keyBytes = Encoding.Default.GetBytes("발급받은 Secret Key");
        var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyBytes);
        var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, "HS256");
        var header = new JwtHeader(credentials);
        var secToken = new JwtSecurityToken(header, payload);

        var jwtToken = new JwtSecurityTokenHandler().WriteToken(secToken);
        var authorizationToken = "Bearer " + jwtToken;
    }
}

(예시) 파라미터가 있는 경우

HTTP 쿼리 문자열, 혹은 body를 통해 파라미터를 전달하는 경우 모두 JWT 페이로드의 query_hash 값을 설정해야합니다.

파라미터의 자료형 중 배열이 존재하는 경우, 올바른 query string의 형태는 다음과 같습니다.

key[]=value1&key[]=value2 ...

이와 다른 형태로 요청하면 토큰 검증에 실패할 수 있으니 유의하시기 바랍니다.

const jwt = require("jsonwebtoken");
const uuidv4 = require("uuid/v4");
const crypto = require('crypto');
const querystring = require("querystring");

const query = querystring.queryEncode({/* 요청할 파라미터 */});

const hash = crypto.createHash('sha512');
const queryHash = hash.update(query, 'utf-8').digest('hex');

const payload = {
  access_key: "발급받은 Access key",
  nonce: uuidv4(),
  query_hash: queryHash,
  query_hash_alg: 'SHA512',
};

const jwtToken = jwt.sign(payload, "발급받은 Secret key");
const authorizationToken = `Bearer ${jwtToken}`;
# Python 3

import jwt    # PyJWT 
import uuid
import hashlib
from urllib.parse import urlencode

# query는 dict 타입입니다.
m = hashlib.sha512()
m.update(urlencode(query).encode())
query_hash = m.hexdigest()

payload = {
    'access_key': '발급받은 Access Key',
    'nonce': str(uuid.uuid4()),
    'query_hash': query_hash,
    'query_hash_alg': 'SHA512',
}
    
jwt_token = jwt.encode(payload, '발급받은 Secret Key')
authorization_token = 'Bearer {}'.format(jwt_token)
#!/usr/bin/env ruby

require 'securerandom'
require 'bundler/inline'
gemfile do
  source 'https://rubygems.org'
  gem 'jwt'
end

params = {} #요청할 파라미터

query_string = URI.encode_www_form(params)
query_hash = Digest::SHA512.hexdigest(query_string)

payload = {
    access_key: '발급받은 Access key',
    nonce: SecureRandom.uuid,
    query_hash: query_hash,
    query_hash_alg: 'SHA512',
}

jwt_token = JWT.encode(payload, '발급받은 Secret key', 'HS256')
authorize_token = "Bearer #{jwt_token}"
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

public class OpenApiSample {

    public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        String accessKey = "발급받은 Access key";
        String secretKey = "발급받은 Secret key";

        String queryString = "query string 생성";

        MessageDigest md = MessageDigest.getInstance("SHA-512");
        md.update(queryString.getBytes("utf8"));

        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("query_hash", queryHash)
                             .withClaim("query_hash_alg", "SHA512")
                             .sign(algorithm);

        String authenticationToken = "Bearer " + jwtToken;
    }

}
using System;
using System.Text;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;

public class OpenAPISample {
    public static void Main() {
        // parameter가 Dictionary<string, string> 일 경우
        StringBuilder builder = new StringBuilder();
        foreach (KeyValuePair<string, string> pair in parameters)
        {
            builder.Append(pair.Key).Append("=").Append(pair.Value).Append("&");
        }
        string queryString = builder.ToString().TrimEnd('&');

        SHA512 sha512 = SHA512.Create();
        byte[] queryHashByteArray = sha512.ComputeHash(Encoding.UTF8.GetBytes(queryString));
        string queryHash = BitConverter.ToString(queryHashByteArray).Replace("-", "").ToLower();

        var payload = new JwtPayload
        {
            { "access_key", "발급받은 Access Key" },
            { "nonce", Guid.NewGuid().ToString() },
            { "query_hash", queryHash },
            { "query_hash_alg", "SHA512" }
        };

        byte[] keyBytes = Encoding.Default.GetBytes("발급받은 Secret Key");
        var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyBytes);
        var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, "HS256");
        var header = new JwtHeader(credentials);
        var secToken = new JwtSecurityToken(header, payload);

        var jwtToken = new JwtSecurityTokenHandler().WriteToken(secToken);
        var authorizationToken = "Bearer " + jwtToken;
    }
}