인증 흐름 시작
엔드포인트
GET /v1/oauth/authorize설명
OAuth 인증 흐름의 진입점입니다. 클라이언트가 사용자를 이 엔드포인트로 리다이렉트하면, DataGSM OAuth 서버가 검증 후 DataGSM 로그인 페이지로 안내합니다. 사용자가 로그인에 성공하면 redirect_uri로 Authorization Code가 전달됩니다.
PKCE 사용 권장
code_challenge와
code_challenge_method를 포함하면 Authorization Code 탈취 공격을 방지할 수 있습니다.
자세한 내용은 PKCE 가이드를 참고하세요.
요청 파라미터
모든 파라미터는 쿼리 스트링(Query String)으로 전달합니다.
| 파라미터 | 타입 | 필수 여부 | 설명 | 예시 |
|---|---|---|---|---|
client_id | String | 필수 | DataGSM에서 발급받은 클라이언트 ID | your-client-id |
redirect_uri | String | 필수 | 인증 완료 후 code를 전달받을 URI (사전 등록 필요) | https://your-app.com/callback |
response_type | String | 선택 | 응답 타입 (code 고정, 기본값 code) | code |
state | String | 선택 (권장) | CSRF 공격 방지용 임의 문자열. 콜백 시 그대로 반환됨 | randomString123 |
code_challenge | String | 선택 (PKCE) | PKCE Code Verifier를 SHA-256 해싱 후 Base64URL 인코딩한 값 | E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM |
code_challenge_method | String | 선택 (PKCE) | Challenge 생성 방법 (S256 권장, plain 지원) | S256 |
scope | String | 선택 | 요청할 OAuth Scope 목록 (공백으로 구분). 미지정 시 클라이언트에 등록된 권한 범위 전체가 부여됨 | {applicationId}:{scopeName} |
Scope 사용 방식
모든 권한 범위는 {applicationId}:{scopeName} 형식입니다. DataGSM 기본 권한 범위도 예외가 아니며, 사용자 정보 조회 권한은 datagsm:self_read입니다. 이 권한이 있어야 사용자 데이터 조회 엔드포인트에서 사용자 기본 정보와 학생 상세 데이터를 조회할 수 있습니다.
scope 파라미터는 생략하는 것을 권장합니다. 생략하면 클라이언트에 등록된 권한 범위 전체가 부여되므로, Application ID를 애플리케이션 코드에 넣지 않아도 됩니다.
명시적으로 전달할 경우 클라이언트에 등록된 권한 범위의 부분집합이어야 합니다. 등록되지 않은 값이 하나라도 포함되면 400 invalid_scope로 거부됩니다. 정확한 문자열은 클라이언트 등록 화면에서 확인할 수 있습니다.
여러 권한 범위를 요청하는 경우 공백으로 구분하며, URL에서는 공백을 %20으로 인코딩합니다.
응답
성공 응답 (302 Found)
DataGSM 로그인 페이지로 리다이렉트됩니다. 서버 내부적으로 인증 상태 토큰이 생성되어 로그인 페이지에 전달되며, 유효 시간은 10분입니다.
사용자가 로그인에 성공하면 아래 형태로 redirect_uri에 Authorization Code가 전달됩니다.
https://your-app.com/callback?code={authorization_code}&state={state}
| 파라미터 | 설명 |
|---|---|
code | Authorization Code (5분 유효, 일회성) |
state | 요청 시 전달한 state 값 (생략한 경우 포함되지 않음) |
오류 응답
| 상태 코드 | 설명 | 원인 |
|---|---|---|
400 Bad Request | 잘못된 요청 | response_type이 code가 아님, 등록되지 않은 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: 'datagsm: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를 발급받았다면, 토큰 교환을 진행하세요.