dshs.app 로그인 연동
dshs.app 계정으로 로그인은 https://id.dshs.app에서 제공하며, OpenID Connect의 인증 코드 방식(Authorization Code flow)을 따릅니다. 이 페이지에서는 앱 종류에 따른 연동 방법과 코드 예제를 안내합니다. 파라미터, 토큰, 오류에 대한 자세한 설명은 로그인 API 문서를 참고하세요.
앱 종류 선택
서버 앱 (confidential Client): 서버가
client_secret으로 인증하고, 인증 코드를 토큰으로 교환합니다. PKCE는 선택 사항이지만 사용을 권장합니다.SPA·네이티브 앱 (public Client): 브라우저나 기기에서 인증 코드를 토큰으로 교환합니다. 비밀 키를 사용하지 않으므로 PKCE(S256)가 필수입니다.
백엔드가 있다면 서버 앱으로 등록하세요. 동의 화면이 표시되는 시점 등 나머지 차이는 로그인 API 문서의 Client 종류 표에서 확인할 수 있습니다.
로그인부터 API 호출까지
로그인 화면으로 이동합니다.
client_id,redirect_uri,scope,state를 넣은GET /auth주소로 사용자의 브라우저를 보냅니다. 사용자는 id.dshs.app에서 로그인하고, 계정에 연결된 사용자 중 하나를 선택한 뒤 앱이 요청한 권한에 동의합니다.인증 코드를 토큰으로 교환합니다. 로그인이 끝나면 브라우저가
code와state를 받아 앱의redirect_uri로 돌아옵니다.code는 60초 동안 유효하며 한 번만 사용할 수 있습니다. 이 코드를POST /token에 보내세요. 서버 앱은client_secret으로 인증하고, PKCE를 사용하는 앱은code_verifier를 함께 보냅니다. 학교 API를 사용하려면resource=https://api.dshs.app도 넣으세요. 응답으로access_token,id_token을 받고,offline_access를 요청해 동의받았다면refresh_token도 받습니다.로그인한 사용자를 확인합니다.
id_token은 JWT 형식이며,sub에 사용자 id가 담겨 있습니다.profileScope에 동의했다면name,role,school도 포함됩니다. 토큰은GET /jwks의 공개 키로 서명을 검증한 뒤 사용하세요. 공개 키의 주소는 discovery 문서에도 나와 있습니다.학교 API를 호출합니다.
Authorization: Bearer <token>헤더에 액세스 토큰을 넣습니다. 예를 들어GET /v2/users/me로 내 정보를 조회할 수 있습니다. 자세한 방법은 학교 API 사용하기를 참고하세요.토큰이 만료되면 갱신합니다. 액세스 토큰의 유효 기간은 15분입니다. 학교 API가
401을 반환하면POST /token에 리프레시 토큰을 보내 새 토큰을 발급받고, 원래 요청을 다시 보냅니다. 아래의 401 응답 시 토큰 갱신하기를 참고하세요.
코드 예제
아래 예제는 별도 라이브러리 없이 fetch로 요청을 보냅니다. timetable-web, redirect URI, Scope는 관리자에게 등록한 값으로 바꾸세요. scope에는 openid를 반드시 포함하고, 필요에 따라 profile, offline_access, 앱에서 사용할 학교 API Scope를 추가합니다.
전역 fetch를 지원하는 Node.js 18 이상에서 실행할 수 있습니다. 리프레시 토큰은 서버에 보관하고, 브라우저에는 앱의 세션 쿠키만 전달합니다.
브라우저에서 실행하는 예제입니다. Web Crypto API로 PKCE에 필요한 verifier와 challenge를 만들고, 인증 코드를 교환할 때 비밀 키 대신 code_verifier를 보냅니다.
액세스 토큰의 종류
/token을 호출할 때 resource를 지정했는지에 따라 발급되는 액세스 토큰이 달라집니다.
resource=https://api.dshs.app을 지정한 경우: 학교 API용 JWT를 받습니다. 유효 기간은 15분이며,aud에는 학교 API 주소가,scope에는 사용자가 동의한 학교 API 권한이 담깁니다.resource를 생략한 경우:GET /userinfo에서만 사용할 수 있는 불투명(opaque) 토큰을 받습니다.
학교 API를 사용하는 앱은 resource를 지정하세요. profile Scope에 동의했다면 사용자 정보는 id_token에도 포함되므로 보통 /userinfo를 따로 호출할 필요가 없습니다. 자세한 내용은 로그인 API 문서의 access token의 종류를 참고하세요.
401 응답 시 토큰 갱신하기
만료 시각을 따로 추적할 필요 없이, 학교 API가 401을 반환하면 /token에서 토큰을 갱신한 뒤 같은 요청을 한 번 더 보내면 됩니다. 갱신도 invalid_grant로 실패하면 다시 로그인해야 합니다. 30일 동안 사용하지 않았거나, 동의 철회·로그아웃·이전 리프레시 토큰 재사용 등으로 토큰이 무효가 된 경우입니다. offline_access를 요청하지 않은 앱은 리프레시 토큰이 없으므로 바로 로그인을 다시 시작합니다.
갱신할 때마다 새 리프레시 토큰이 발급됩니다. 새 토큰을 저장하고 이전 토큰은 삭제하세요. 아래 함수는 앞의 서버 앱 또는 SPA 예제에 있는 refresh()와 함께 사용합니다.
LoginRequired를 잡은 곳에서 1단계의 로그인 절차를 다시 시작하세요.
로그아웃
앱에서 로그아웃할 때는 저장한 토큰을 삭제하고, POST /token/revocation으로 리프레시 토큰을 무효화하세요. 학교 API용 JWT는 개별적으로 무효화할 수 없으며, 발급 후 15분이 지나면 만료됩니다.
사용자가 dshs.app에서도 로그아웃하길 원하면 id_token_hint를 넣어 브라우저를 GET /session/end로 보냅니다. 확인 화면이 한 번 표시됩니다. 로그아웃 후 앱으로 돌아오게 하려면 관리자에게 로그아웃 후 돌아올 주소도 미리 등록해야 합니다.