토큰 갱신

엔드포인트

POST /v1/oauth/token

주의: 이 엔드포인트는 토큰 교환(/v1/oauth/token)과 동일한 통합 엔드포인트입니다. grant_type 파라미터로 구분됩니다.

설명

Refresh Token을 사용하여 새로운 Access Token과 Refresh Token을 발급받습니다. Access Token이 만료되었을 때(1시간 후) 사용자가 다시 로그인하지 않고도 새로운 Access Token을 받을 수 있습니다.

Refresh Token은 30일의 유효기간을 가지며, 갱신 시 새로운 Refresh Token도 함께 발급됩니다.

client_secret 선택사항

client_id는 필수이며, client_secret는 선택사항입니다. client_secret을 제공하면 서버가 시크릿까지 함께 검증합니다.

요청 파라미터

모든 파라미터는 JSON 형식으로 요청 본문(body)에 포함되어야 합니다.

파라미터타입필수 여부설명예시
grant_typeString필수요청 타입 (refresh_token 고정)refresh_token
refresh_tokenString필수이전에 발급받은 Refresh TokeneyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
client_idString필수DataGSM에서 발급받은 클라이언트 IDyour-client-id
client_secretString선택DataGSM에서 발급받은 클라이언트 시크릿your-client-secret

응답

성공 응답 (200 OK)

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "scope": "self:read"
}
필드타입설명
access_tokenString새로 발급된 JWT 형식의 Access Token (1시간 유효)
token_typeString토큰 타입 (Bearer 고정)
expires_inIntAccess Token의 만료 시간 (초 단위, 3600 = 1시간)
refresh_tokenString새로 발급된 Refresh Token (30일 유효)
scopeString발급된 권한 범위 (공백으로 구분)

오류 응답

상태 코드설명원인
400 Bad Request잘못된 요청필수 파라미터 누락 또는 잘못된 형식, Refresh Token이 유효하지 않거나 만료됨
401 Unauthorized인증 실패Client ID가 존재하지 않거나 Client Secret이 올바르지 않음

요청 예시

cURL

curl -X POST "https://oauth.data.hellogsm.kr/v1/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "refresh_token",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "client_id": "your-client-id"
  }'

응답 예시

성공

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "scope": "self:read"
}

실패 (400 Bad Request)

{
  "error": "invalid_grant",
  "error_description": "Refresh Token이 유효하지 않거나 만료되었습니다."
}

실패 (401 Unauthorized)

{
  "error": "invalid_client",
  "error_description": "클라이언트 인증에 실패했습니다."
}

사용 예제

다음은 여러 언어에서 토큰을 갱신하는 예제입니다.

async function refreshAccessToken(refreshToken, clientId) {
try {
  const response = await fetch('https://oauth.data.hellogsm.kr/v1/oauth/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      grant_type: 'refresh_token',
      refresh_token: refreshToken,
      client_id: clientId,
    }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error_description || 'Failed to refresh token');
  }

  const data = await response.json();
  return {
    accessToken: data.access_token,
    refreshToken: data.refresh_token,
    expiresIn: data.expires_in,
  };
} catch (error) {
  console.error('Error:', error.message);
  throw error;
}
}

// 사용 예시
const oldRefreshToken = localStorage.getItem('refreshToken');
const tokens = await refreshAccessToken(oldRefreshToken, 'your-client-id');

// 새 토큰 저장
sessionStorage.setItem('accessToken', tokens.accessToken);
localStorage.setItem('refreshToken', tokens.refreshToken);

console.log('Access Token refreshed successfully');

자동 토큰 갱신 구현

Access Token이 만료되기 전에 자동으로 갱신하는 로직을 구현하는 것이 좋습니다.

JavaScript 예제 (타이머 기반)

class TokenManager {
  constructor() {
    this.accessToken = null;
    this.refreshToken = null;
    this.refreshTimer = null;
  }

  setTokens(accessToken, refreshToken, expiresIn) {
    this.accessToken = accessToken;
    this.refreshToken = refreshToken;

    // Access Token 만료 5분 전에 자동 갱신
    const refreshTime = (expiresIn - 300) * 1000; // 5분 = 300초
    this.scheduleRefresh(refreshTime);
  }

  scheduleRefresh(delay) {
    if (this.refreshTimer) {
      clearTimeout(this.refreshTimer);
    }

    this.refreshTimer = setTimeout(async () => {
      try {
        const tokens = await refreshAccessToken(this.refreshToken, 'your-client-id');
        this.setTokens(tokens.accessToken, tokens.refreshToken, tokens.expiresIn);
        console.log('Access Token refreshed automatically');
      } catch (error) {
        console.error('Failed to refresh token:', error);
        // 갱신 실패 시 재로그인 유도
        window.location.href = '/login';
      }
    }, delay);
  }

  getAccessToken() {
    return this.accessToken;
  }
}

// 사용 예시
const tokenManager = new TokenManager();
tokenManager.setTokens(accessToken, refreshToken, 3600);

보안 주의사항

Refresh Token 보호

  • Refresh Token은 30일 동안 유효하므로 안전하게 저장해야 합니다.
  • 권장: HttpOnly 쿠키 또는 서버 세션에 저장
  • 주의: localStorage는 XSS 공격에 취약

토큰 로테이션

  • 토큰 갱신 시 새로운 Refresh Token도 함께 발급됩니다.
  • 이전 Refresh Token은 무효화되므로, 항상 새로 발급된 Refresh Token을 사용하세요.

만료 처리

  • Refresh Token이 만료되면 (400 Bad Request) 사용자는 다시 로그인해야 합니다.
  • 만료 30일 전에 사용자에게 재로그인을 안내하는 것을 권장합니다.

다음 단계

토큰 갱신에 성공했다면, 새로운 Access Token으로 API를 호출할 수 있습니다.

실전 구현 예제가 필요하면 Examples 기술 문서를 참고하세요.