D

인증 흐름 시작

엔드포인트

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
scopeString선택요청할 OAuth Scope 목록 (공백으로 구분). 미지정 시 기본 사용자 정보 조회 흐름으로 처리self:read

Scope 사용 방식

DataGSM OAuth의 기본 사용자 정보 조회 권한 범위는 self:read입니다. 이 권한으로 사용자 데이터 조회 엔드포인트에서 사용자 기본 정보와 학생 상세 데이터를 조회할 수 있습니다.

신규 OAuth 연동에서 사용자 본인 정보만 필요하다면 scope 파라미터를 생략할 수 있습니다. 명시적으로 표현하고 싶다면 scope=self:read를 전달하세요.

서드파티 애플리케이션이 직접 정의한 권한 범위를 요청해야 할 때만 해당 애플리케이션의 Application ID를 앞에 붙인 {applicationId}:{scopeName} 형식을 사용합니다. 여러 권한 범위를 요청하는 경우 공백으로 구분하며, URL에서는 공백을 %20으로 인코딩합니다.

응답

성공 응답 (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,
  scope: 'self:read',
  code_challenge: codeChallenge,
  code_challenge_method: 'S256',
});

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

URL 구성 (scope 생략)

사용자 본인 정보만 조회하는 기본 흐름에서는 scope 파라미터를 생략할 수 있습니다.

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.authorization.datagsm.kr/v1/oauth/authorize?${params}`;

URL 구성 (서드파티 권한 범위)

외부 애플리케이션이 자체 권한 범위를 정의한 경우에는 해당 애플리케이션의 Application ID를 포함해 {applicationId}:{scopeName} 형식으로 전달합니다.

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

window.location.href = `https://oauth.authorization.datagsm.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으로 교환