Dasturchilarga

Mars ID'ni o'z
loyihangizga ulash

O'z ro'yxatdan o'tish formangiz o'rniga Telegram orqali kirish. Bizning hostingda ham, sizniki'da ham ishlaydi — Vercel, Render, VPS, farqi yo'q. Bepul, kalitlarni bir soatda beramiz.

OpenID Connect JWT · HS256 .marshub.uz'dagi cookie Telegram Mini App
1-yo'l

Tayyor saytga qulf

Sayt deploy qilingan, kodga tegishni istamaysiz, lekin uni hamma ko'rmasligi kerak. Tekshiruvni so'rov sizning fayllaringizga yetib borgunicha bizning proksi bajaradi.

Butun sayt nom.marshub.uz

Bizga subdomen nomini va kimlarni kiritish kerakligini — Telegram ID ro'yxatini yozing. Qulfni bazada yoqamiz: restart ham, kodni o'zgartirish ham shart emas.

  • ro'yxat bo'sh = Mars ID'ga kirgan har kimni kiritamiz
  • ID ro'yxati = faqat o'shalarni kiritamiz, qolganlarga 403
  • qulfsiz sayt avvalgidek ochiq qoladi

Kirmagan mehmonni id.marshub.uz/login ga o'zi olib o'tadi va sahifangizga qaytaradi.

Bitta sahifa pages.marshub.uz

Bu yerda hammasini o'zingiz qilasiz, bizsiz. Har bir chop etilgan sahifaning kirish sozlamasi bor:

  • public — hammaga ochiq
  • password — umumiy parol, akkaunt kerak emas
  • marsid — Telegram orqali kirish, ID ro'yxati bilan ham bo'ladi

marshub_set_page_access MCP-vositasi orqali buni sizning AI-agentingiz ham qiladi.

Bu nimani uddalay olmaydi: qulf faqat «kiritish kerakmi yoki yo'qmi» degan savolga javob beradi. Agar ichkarida rollar, shaxsiy kabinet yoki «bu buyurtma meniki» kerak bo'lsa — backend kerak, bu 2-yo'l.

3-yo'l

O'z hostingingiz, istalgan domen

Cookie faqat .marshub.uz da yashaydi — tashqarida u yo'q. Shuning uchun Vercel, Render, o'z VPS'ingiz yoki localhost'dagi loyiha uchun standart OpenID Connect ishlaydi. Mars ID — to'liq huquqli OIDC-provayder, uni deyarli har qanday avtorizatsiya kutubxonasi qutidan chiqqan holda tushunadi.

1-qadam — kalitlarni olish

@marvinaka ga yozing va uchta narsani yuboring:

Loyiha nomi

Mijozlar ro'yxatida qanday nomlanadi

Callback URL

Foydalanuvchini qaytaradigan aniq manzil. Bir nechta bo'lishi mumkin: prod, staging, localhost

Kimga ruxsat

Mars ID'si borlarning hammasiga / faqat o'quvchilarga / faqat xodimlarga

Javobiga client_id va client_secret keladi. Callback harfma-harf solishtiriladi — niqob ham, «shu bilan boshlanadi» ham yo'q: oxiridagi ortiqcha slash ham boshqa manzil hisoblanadi.

2-qadam — kutubxona uchun sozlamalar

Agar frameworkingiz OIDC'ni bilsa (NextAuth/Auth.js, Passport, Authlib, Spring Security, Keycloak-adapter, Grafana, Forgejo, GlitchTip…) — shu qiymatlarni qo'ying, kod deyarli kerak bo'lmaydi.

ParametrQiymat
Issuerhttps://id.marshub.uz
Discovery / well-knownhttps://id.marshub.uz/.well-known/openid-configuration
Authorization URLhttps://id.marshub.uz/oauth/authorize
Token URLhttps://id.marshub.uz/oauth/token
UserInfo URLhttps://id.marshub.uz/oauth/userinfo
Scopesopenid profile email
Response typecode
id_token algoritmiHS256 (imzo — sizning client_secret bilan)
Mijoz autentifikatsiyasiclient_secret_post yoki client_secret_basic

Bizda nima yo'q: PKCE, refresh-tokenlar va RS256/JWKS. Tokenlar bir soat yashaydi, kod 5 daqiqa ichida bir marta almashtiriladi. Backendsiz SPA uchun bu shuni anglatadi: kodni server almashtirishi kerak, client_secret ni brauzerga qo'yish mumkin emas.

3-qadam — qo'lda yozsangiz

// 1. Foydalanuvchini Mars ID'ga yuboramiz
app.get('/login', (req, res) => {
  const state = crypto.randomBytes(16).toString('hex');
  req.session.state = state;                     // qaytganda tekshiramiz

  const u = new URL('https://id.marshub.uz/oauth/authorize');
  u.searchParams.set('client_id', process.env.MARS_CLIENT_ID);
  u.searchParams.set('redirect_uri', 'https://myapp.uz/callback');
  u.searchParams.set('response_type', 'code');
  u.searchParams.set('scope', 'openid profile email');
  u.searchParams.set('state', state);
  res.redirect(u.toString());
});

// 2. Foydalanuvchi kod bilan qaytdi — kodni tokenlarga almashtiramiz
app.get('/callback', async (req, res) => {
  if (req.query.state !== req.session.state) return res.status(400).send('bad state');

  const tokens = await fetch('https://id.marshub.uz/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      grant_type:    'authorization_code',
      code:          req.query.code,
      redirect_uri:  'https://myapp.uz/callback',   // 1-qadamdagining aynan o'zi
      client_id:     process.env.MARS_CLIENT_ID,
      client_secret: process.env.MARS_CLIENT_SECRET,
    }),
  }).then(r => r.json());

  // 3. Bu kim — id_token'dan (sizning client_secret bilan imzolangan) yoki so'rov orqali:
  const user = await fetch('https://id.marshub.uz/oauth/userinfo', {
    headers: { Authorization: `Bearer ${tokens.access_token}` },
  }).then(r => r.json());

  // user = { sub, name, preferred_username, handle, email,
  //          role, tg, is_staff, is_student, core_id }
  req.session.user = user;
  res.redirect('/');
});
4-yo'l

Telegram Mini App

Telegram ichida odam allaqachon tanilgan — kirish tugmasini ko'rsatish ortiqcha. Telegram imzolangan initData qatorini beradi, siz uni bizga yuborasiz, biz imzoni tekshirib, o'sha __mars_id cookie'sini qo'yamiz.

// Mini App'da, ishga tushishi bilanoq
const tg = window.Telegram.WebApp;

const me = await fetch('https://id.marshub.uz/api/auth/telegram-webapp', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include',                // aks holda cookie saqlanmaydi
  body: JSON.stringify({ initData: tg.initData }),
}).then(r => r.json());

// me = { id, name, handle, role, tg, needs_handle }
// needs_handle: true → odam hali o'ziga nom tanlamagan

So'rov begona domendan keladi, shuning uchun Mini App'ingiz origin'ini oq ro'yxatga kiritish kerak — bizga manzilni yozing. initData imzosi bir kun davomida amal qiladi.

Ma'lumotnoma

Nima qayerda

Manzillar

EndpointMetodNima qiladi
/login?next=URLGETKirish sahifasi, muvaffaqiyatdan keyin URL'ga qaytaradi
/logoutGETCookie'ni o'chirish
/api/verifyGETAuthorization: Bearer dagi yoki cookie'dagi tokenni tekshirish → { id, name, role, tg }
/api/meGETXuddi shu, lekin faqat cookie bo'yicha. Boshqa domendagi brauzerdan — origin'lar oq ro'yxati kerak
/api/auth/telegram-webappPOSTMini App initData → cookie
/.well-known/openid-configurationGETOIDC Discovery
/oauth/authorizeGETOAuth-oqimning boshlanishi
/oauth/tokenPOSTcode → access_token + id_token
/oauth/userinfoGETBearer access_token bo'yicha ma'lumotlar
/healthGETXizmat tirikmi

Hammasi https://id.marshub.uz ga nisbatan

Token ichida nima bor

MaydonBu nima
subFoydalanuvchi UUID'si, o'zgarmaydi
nameTelegram'dagi ism
handleNik (aziz), onboardinggacha null bo'lishi mumkin
rolemember · student · intern · tutor · mentor · team · admin
tgTelegram ID, son
emailhandle@marshub.uz
is_staffMaktab xodimi (HR-bazadan)
is_studentAmaldagi o'quvchi (Core'dan)
core_idMaktabning asosiy bazasidagi ID, agar bog'langan bo'lsa
exp30 kun yashaydi

role — bu «odam kim», «unga nima mumkin» emas. Huquqlarni o'zingizda saqlang: qo'pol ajratish uchun is_staff/is_student, aniq ajratish uchun — o'z ro'yxatingiz.

Hamma qoqiladigan tirmalar

  • 01Cookie httpOnly. Uni JavaScript'dan o'qib bo'lmaydi — kerak ham emas. Tekshiruv faqat serverda.
  • 02Localhost'ga cookie kelmaydi. U .marshub.uz ga bog'langan. Lokal ishlab chiqish uchun callback'i localhost'da bo'lgan OIDC oling — shundayini ro'yxatdan o'tkazamiz.
  • 03Algoritmni tekshiring. Imzoni o'zingiz tekshirsangiz — har doim HS256 ni aniq ko'rsating, aks holda kutubxona imzosiz tokenni ham qabul qilishi mumkin.
  • 04Frontendga ishonmang. Rol, id va «men adminman» tokendan, serverda olinadi. Brauzer so'rov tanasida yuborgan hamma narsa — dalil emas.
  • 05Huquqlar bir zumda o'zgarmaydi. Token 30 kun yashaydi: rolni olib tashladingiz — eski tokenda u hali bor. Muhim bo'lsa, /api/verify ni chaqiring yoki bekor qilishni o'zingizda saqlang.
  • 06next'ni kodlang. Qaytish manzilini encodeURIComponent orqali bering, aks holda ? dan keyingi parametrlar yo'qoladi.
AI bilan yozasizmi

Vazifani agentga bering

Claude Code, Cursor, Mars Code — istalgan agentga bitta faktlar sahifasi yetadi. Unga havola va vazifani tashlang, qolganini o'zi qiladi.

Borligicha nusxalasa bo'ladigan prompt:

Loyihamga Mars ID orqali kirishni ulab ber.

Faktlar va endpointlarni shu yerdan ol: https://marshub.uz/id/llms.txt
Loyiham: <stek, framework>
Joylashgan: <nom.marshub.uz | tashqi hosting | Telegram Mini App>

Talablar:
- agar loyiha *.marshub.uz da bo'lsa — __mars_id cookie'sini o'qish va uni
  https://id.marshub.uz/api/verify ga so'rov bilan tekshirish (Authorization: Bearer),
  umumiy AUTH_SECRET ishlatilmasin;
- agar loyiha tashqi domenda bo'lsa — OAuth2 authorization code
  (issuer https://id.marshub.uz), client_id/secret muhit o'zgaruvchilaridan,
  PKCE va refresh-tokensiz — provayderda ular yo'q;
- avtorizatsiyadan o'tmaganni
  https://id.marshub.uz/login?next=<url-encoded qaytish manzili> ga yo'naltirish;
- rol va huquqlar faqat serverda tekshirilsin, frontendga ishonilmasin;
- https://id.marshub.uz/logout ga chiqish havolasi qo'shilsin.

Kalitlar yoki maslahat kerakmi?

OIDC-mijozni ro'yxatdan o'tkazish, saytga qulf, o'z subdomeningiz, Mini App uchun oq ro'yxat — bularning hammasini qo'lda va tez qilamiz. Nimani ulayotganingizni yozing.