Документация

OAuth

Быстрый старт по OAuth

OAuth-приложения позволяют внешнему сервису определить пользователя Chattr.

Важное ограничение

Сторонние OAuth-приложения получают только идентификационные поля:

  • chattr_user_id
  • nickname
  • name
  • avatar_url

Они не получают делегированный доступ к управлению пользователем.

Поток авторизации

  1. Перенаправьте пользователя на /oauth/authorize
  2. Получите временный code на вашем redirect URI
  3. Обменяйте код на POST /oauth/token

Шаг 1 — Перенаправление на авторизацию

https://chattr.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&state=RANDOM_NONCE

Шаг 2 — Обмен кода на идентификацию

После одобрения Chattr перенаправляет на ваш redirect_uri с ?code=TEMP_CODE&state=RANDOM_NONCE. Обменяйте код:

Примеры кода

cURL

curl -X POST "https://chattr.example.com/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": APP_ID,
    "client_secret": "YOUR_CLIENT_SECRET",
    "code": "TEMP_CODE",
    "redirect_uri": "https://example.com/callback"
  }'

JavaScript (Node.js)

const CHATTR   = "https://chattr.example.com";
const APP_ID   = 7;
const SECRET   = "YOUR_CLIENT_SECRET";
const REDIRECT = "https://example.com/callback";

// Шаг 1 — собираем URL авторизации
const authorizeUrl = `${CHATTR}/oauth/authorize`
  + `?client_id=${APP_ID}`
  + `&redirect_uri=${encodeURIComponent(REDIRECT)}`
  + `&state=RANDOM_NONCE`;

// Перенаправьте пользователя на authorizeUrl...

// Шаг 2 — обмен кода на callback-эндпоинте
async function exchangeCode(code) {
  const res = await fetch(`${CHATTR}/oauth/token`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      client_id: APP_ID,
      client_secret: SECRET,
      code,
      redirect_uri: REDIRECT
    })
  });

  const user = await res.json();
  console.log(user.chattr_user_id, user.nickname, user.avatar_url);
  return user;
}

Python

import requests

CHATTR   = "https://chattr.example.com"
APP_ID   = 7
SECRET   = "YOUR_CLIENT_SECRET"
REDIRECT = "https://example.com/callback"

# Шаг 1 — собираем URL авторизации
authorize_url = (
    f"{CHATTR}/oauth/authorize"
    f"?client_id={APP_ID}"
    f"&redirect_uri={requests.utils.quote(REDIRECT, safe='')}"
    f"&state=RANDOM_NONCE"
)

# Перенаправьте пользователя на authorize_url...

# Шаг 2 — обмен кода на callback-эндпоинте
def exchange_code(code):
    res = requests.post(f"{CHATTR}/oauth/token", json={
        "client_id": APP_ID,
        "client_secret": SECRET,
        "code": code,
        "redirect_uri": REDIRECT
    })

    user = res.json()
    print(user["chattr_user_id"], user["nickname"], user["avatar_url"])
    return user

Go

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const (
	chattr   = "https://chattr.example.com"
	appID    = 7
	secret   = "YOUR_CLIENT_SECRET"
	redirect = "https://example.com/callback"
)

// Шаг 1 — собираем URL авторизации
func authorizeURL() string {
	return fmt.Sprintf(
		"%s/oauth/authorize?client_id=%d&redirect_uri=%s&state=RANDOM_NONCE",
		chattr, appID, url.QueryEscape(redirect),
	)
}

// Шаг 2 — обмен кода
func exchangeCode(code string) (map[string]any, error) {
	body, _ := json.Marshal(map[string]any{
		"client_id":     appID,
		"client_secret": secret,
		"code":          code,
		"redirect_uri":  redirect,
	})

	resp, err := http.Post(chattr+"/oauth/token", "application/json", bytes.NewReader(body))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	raw, _ := io.ReadAll(resp.Body)
	var user map[string]any
	json.Unmarshal(raw, &user)
	return user, nil
}

PHP

$chattr   = "https://chattr.example.com";
$appId    = 7;
$secret   = "YOUR_CLIENT_SECRET";
$redirect = "https://example.com/callback";

// Шаг 1 — собираем URL авторизации
$authorizeUrl = $chattr . "/oauth/authorize?"
    . http_build_query([
        "client_id"    => $appId,
        "redirect_uri" => $redirect,
        "state"        => "RANDOM_NONCE"
    ]);

// Перенаправьте пользователя на $authorizeUrl...

// Шаг 2 — обмен кода на callback-эндпоинте
function exchangeCode(string $code) {
    global $chattr, $appId, $secret, $redirect;

    $ch = curl_init("$chattr/oauth/token");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        "client_id"     => $appId,
        "client_secret" => $secret,
        "code"          => $code,
        "redirect_uri"  => $redirect
    ]));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    curl_close($ch);

    $user = json_decode($response, true);
    echo $user["chattr_user_id"] . " " . $user["nickname"];
    return $user;
}

Права доступа

Создать OAuth-приложение может любой пользователь Chattr с подтверждённым телефоном. Управлять приложением (редактировать или удалять) может только его владелец — серверные права не требуются.

Формат ответа

{
  "chattr_user_id": 42,
  "nickname": "player1",
  "name": "Player One",
  "avatar_url": "https://chattr.example.com/media/avatars/42.webp"
}