이 문서는 커뮤니티에 의해 번역되었습니다. 번역 제출은 Crowdin에서 받고 있습니다. 여러분의 도움을 부탁드립니다 🙏
OAuth 방식의 액세스 토큰 획득 방식
애플리케이션을 이용하는 사용자(이하 단순히 '사용자'라 칭함)의 액세스 토큰을 발급받으려면 아래 절차에 따라 발급을 요청합니다.
아래 설명할 방법은 OAuth 2.0이라는 방법입니다.일반 OAuth는 앱을 만들어야 하지만, IndieAuth의 확장으로 앱을 만들지 않고도 사용할 수 있도록 되어 있습니다.
OAuth 방식은 사용할 수 있는 라이브러리가 많기 때문에 가능하면 라이브러리를 사용하는 것을 추천합니다.
현재 이 방식을 사용하려면 웹페이지가 필요합니다.웹페이지를 준비할 수 없거나 Misskey 2023.9.0 이전 버전을 지원하고자 하는 경우, 아래의 방법을 사용하시기 바랍니다.
Step 1
앱 소개를 위한 웹페이지를 만듭니다.페이지가 HTTPS 주소로 접속할 수 있어야 합니다.페이지 어딘가에 아래와 같은 HTML 코드를 작성합니다.
<!-- (필수항목) href의 주소가 인증코드의 전송처가 됩니다. -->
<link rel='redirect_uri' href='/redirect'>
<!-- 사용자에게 보여줄 앱의 이름입니다. 없으면 이 페이지의 주소가 이름이 됩니다. -->
<div class='h-app'>
<a href="/" class="u-url p-name">My Misskey App</a>
</div>
나중에 redirect_uri
주소로 인증 코드가 전송됩니다.
Step 2
PKCE code_verifier
와 code_challenge
문자열, 그리고 state
문자열을 생성합니다.
- code_verifier
의 경우 최소 43자, 최대 128자로 알파벳 대/소문자 및
-. _~` 안에 있는 문자로 제한됩니다. - code_challenge
문자열은
code_verifier` 문자열을 SHA256 알고리즘으로 해시하여 base64url로 인코딩한 결과를 사용합니다. state
문자열에는 특별한 제한이 없습니다. 임의의 문자열을 사용합니다.
이 문자열은 매번 생성해야 하며, 반복해서 사용하지 마십시오.
pkce-challenge와 같은 라이브러리를 사용하거나 OAuth 라이브러리의 PKCE 기능을 사용하는 것을 추천합니다.
import crypto from "node:crypto";
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~";
const codeVerifier = new Array(128)
.fill(0)
.map(() => chars[Math.floor(chars.length * Math.random())])
.join("");
console.log('code_verifier', codeVerifier);
const codeChallenge = crypto
.createHash("sha256")
.update(codeVerifier, "ascii")
.digest("base64url");
console.log('code_challenge', codeChallenge);
const state = crypto.randomUUID();
console.log('state', state);
Step 3
상대 서버의 OAuth 정보를 가져옵니다. 데이터는 JSON 형식으로 되어 있습니다.
https://{host}/.well-known/oauth-authorization-server
{host}
부분은 사용자 서버의 호스트로 대체합니다.보통 호스트는 사용자가 입력합니다.
여기서는 authorization_endpoint
와 token_endpoint
를 사용합니다.
다음 단계에서 사용되는 scope
에 대한 정보도 scopes_supported
에서 확인할 수 있습니다.
Step 4
애플리케이션 인증 양식을 사용자의 브라우저에 표시합니다.인증 양식은 다음 형식의 URL로 열 수 있습니다.
{authorization_endpoint}?client_id={client_id}&response_type=code&redirect_uri={redirect_uri}&scope={scope}&code_challenge={code_challenge}&code_challenge_method=S256&state={state}
여기서,
{authorization_endpoint}
부분은 이전 정보 획득에서 얻은 주소로 대체합니다.{client_id}
부분은 앱 소개 페이지의 주소로 대체합니다.{code_challenge}
부분은 앞서 생성한code_challenge
문자열로 대체합니다.code_challenge_method
부분은 항상S256
으로 합니다.{redirect_uri}
부분은 소개 페이지에서 사용하고 있는 전송처 주소로 대체합니다.{scope}
부분은 애플리케이션이 요청하는 권한으로 대체합니다.요청하는 권한을 ``로 구분하여 열거합니다.권한 목록은 여기에서 확인할 수 있습니다.{state}
부분은 앞서 생성한state
문자열로 대체합니다.
https://misskey.local/oauth/authorize?client_id=http%3A%2F%2Fexample.com&code_challenge=C6hwMO2bmIzg3nqppTE9b79fvuOjlrKmH2xNiZSMHzw&code_challenge_method=S256&response_type=code&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect&scope=write%3Anotes&state=87c11f05-86eb-4eb2-9057-f6a98fc5e9ab
Step 5
사용자가 애플리케이션 접근을 허용하면 redirect_uri
주소로 인증 코드가 URL 파라미터 형태로 전송됩니다.
이름 | 설명 |
---|---|
code | 사용자 인증 코드. |
state | 인증 요청에 사용된 state 문자열. |
https://example.com/redirect?code=...&state=87c11f05-86eb-4eb2-9057-f6a98fc5e9ab
state
문자열이 제대로 일치하는지 확인하고 다음 단계로 넘어갑니다.
Step 6
전송된 인증 코드를 사용하여 POST로 액세스 토큰을 요청합니다.요청 대상은 token_endpoint
가 됩니다.데이터 형식은 application/json
과 application/x-wwww-form-urlencoded
를 사용할 수 있습니다.각 매개변수는 다음과 같습니다.
이름 | 설명 |
---|---|
grant_type | 항상 authorization_code 로 설정합니다. |
client_id | 인증 요청에 사용되는 client_id 문자열. |
redirect_uri | 인증 요청에 사용된 redirect_uri 문자열. |
scope | 인증 요청에 사용된 scope 문자열. |
code | 획득한 인증 코드. |
code_verifier | 앞서 생성한 code_verifier 문자열. |
const res = await fetch(endpoint, {
method: "POST",
body: JSON.stringify({
grant_type: "authorization_code",
client_id: "https://example.com",
redirect_uri: "https://example.com/redirect",
scope: "write:notes",
code: "...",
code_verifier: "hjjbCYDmDpSLjirkO-PrfWKsRhDdJr-PAEGRClRwzUKlmFIIIrZNmSvUIraeIa~WqbqQnfbJV-Hc_IfuQkesBYUpukUi~lInDfU_AZjoZqbU.ioQTRzaFfZFfGnT-OAA",
}),
headers: {
"Content-Type": "application/json"
}
});
응답은 JSON 객체 형태로, 거기서 access_token
을 가져와서 사용합니다.