인증 흐름 시작

엔드포인트

GET /v1/oauth/authorize

설명

OAuth 인증 흐름의 진입점입니다. 클라이언트가 사용자를 이 엔드포인트로 리다이렉트하면, DataGSM OAuth 서버가 검증 후 DataGSM 로그인 페이지로 안내합니다. 사용자가 로그인에 성공하면 redirect_uri로 Authorization Code가 전달됩니다.

PKCE 사용 권장

code_challengecode_challenge_method를 포함하면 Authorization Code 탈취 공격을 방지할 수 있습니다. 자세한 내용은 PKCE 가이드를 참고하세요.

요청 파라미터

모든 파라미터는 쿼리 스트링(Query String)으로 전달합니다.

파라미터타입필수 여부설명예시
client_idString필수DataGSM에서 발급받은 클라이언트 IDyour-client-id
redirect_uriString필수인증 완료 후 code를 전달받을 URI (사전 등록 필요)https://your-app.com/callback
response_typeString선택응답 타입 (code 고정, 기본값 code)code
stateString선택 (권장)CSRF 공격 방지용 임의 문자열. 콜백 시 그대로 반환됨randomString123
code_challengeString선택 (PKCE)PKCE Code Verifier를 SHA-256 해싱 후 Base64URL 인코딩한 값E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
code_challenge_methodString선택 (PKCE)Challenge 생성 방법 (S256 권장, plain 지원)S256

응답

성공 응답 (302 Found)

DataGSM 로그인 페이지로 리다이렉트됩니다. 서버 내부적으로 인증 상태 토큰이 생성되어 로그인 페이지에 전달되며, 유효 시간은 10분입니다.

사용자가 로그인에 성공하면 아래 형태로 redirect_uri에 Authorization Code가 전달됩니다.

https://your-app.com/callback?code={authorization_code}&state={state}
파라미터설명
codeAuthorization Code (5분 유효, 일회성)
state요청 시 전달한 state 값 (생략한 경우 포함되지 않음)

오류 응답

상태 코드설명원인
400 Bad Request잘못된 요청response_typecode가 아님, 등록되지 않은 redirect_uri, code_challenge 없이 code_challenge_method만 전달
401 Unauthorized인증 실패존재하지 않는 client_id

요청 예시

URL 구성 (PKCE)

// 1. PKCE code_verifier 생성
function generateCodeVerifier() {
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  const base64 = btoa(String.fromCharCode(...array));
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

// 2. code_challenge 생성 (SHA-256)
async function generateCodeChallenge(verifier) {
  const data = new TextEncoder().encode(verifier);
  const hash = await crypto.subtle.digest('SHA-256', data);
  const base64 = btoa(String.fromCharCode(...new Uint8Array(hash)));
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

// 3. state 생성 및 저장
const state = crypto.randomUUID();
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);

sessionStorage.setItem('oauth_state', state);
sessionStorage.setItem('oauth_code_verifier', codeVerifier);

// 4. 인증 URL 구성 후 리다이렉트
const params = new URLSearchParams({
  client_id: 'your-client-id',
  redirect_uri: 'https://your-app.com/callback',
  response_type: 'code',
  state,
  code_challenge: codeChallenge,
  code_challenge_method: 'S256',
});

window.location.href = `https://oauth.data.hellogsm.kr/v1/oauth/authorize?${params}`;

URL 구성 (state만 사용)

const state = crypto.randomUUID();
sessionStorage.setItem('oauth_state', state);

const params = new URLSearchParams({
  client_id: 'your-client-id',
  redirect_uri: 'https://your-app.com/callback',
  response_type: 'code',
  state,
});

window.location.href = `https://oauth.data.hellogsm.kr/v1/oauth/authorize?${params}`;

콜백 처리 예시

// redirect_uri 페이지에서 code와 state 수신
const params = new URLSearchParams(window.location.search);
const code = params.get('code');
const returnedState = params.get('state');

// state 검증 (CSRF 방지)
const savedState = sessionStorage.getItem('oauth_state');
if (returnedState !== savedState) {
  throw new Error('State mismatch - possible CSRF attack');
}
sessionStorage.removeItem('oauth_state');

// code로 토큰 교환 진행
const codeVerifier = sessionStorage.getItem('oauth_code_verifier');
sessionStorage.removeItem('oauth_code_verifier');
// → POST /v1/oauth/token 으로 교환

다음 단계

Authorization Code를 발급받았다면, 토큰 교환을 진행하세요.

토큰 교환— Authorization Code를 Access Token으로 교환