1. Ümumiyyətlə ChatGPT App-də autentifikasiya niyə lazımdır
Əsasdan başlayaq: ChatGPT-dəki istifadəçi ≠ sizin servisinizdəki istifadəçi.
ChatGPT-nin öz istifadəçi hesabı var. Sizin servisinizdə — öz userId, tenantId, rollar, billinq, sifarişlər var. Onlar arasında susmaya görə heç bir sehrli əlaqə yoxdur. Əgər sadəcə MCP serverini qaldırıb bir neçə aləti (tools) təsvir etmisinizsə, ChatGPT onları abstrakt bir müştəri kimi çağıracaq.
Şərti GiftGenius tətbiqimizi yada salaq — hədiyyə seçməyə və wish-listləri idarə etməyə kömək edən ChatGPT App. Nələri bacarmaq istəyirik:
- İstifadəçiyə onun saxlanmış hədiyyə siyahılarını göstərmək.
- Hədiyyələri “alınıb” və ya “qəbul edilib” kimi işarələməyə icazə vermək.
- Sifariş tarixçəsini göstərmək (xüsusən də sonra commerce/ACP-ə gedəcəyiksə).
Autentifikasiya olmadan MCP server ümumiyyətlə “bu kimdir” bilmir. Maksimum gördüyü — bir sıra texniki bağlantı identifikatorları və OpenAI tərəfindən identifikasiya və rate-limit-lər üçün verilən anonim subject-dir; ancaq açıq-aydın xəbərdarlıq edilir ki, bunu avtorizasiya üçün istifadə etmək olmaz.
Autentifikasiya vs avtorizasiya
İki anlayışı dərhal ayırmaq çox faydalıdır.
- Autentifikasiya (AuthN) belə bir sualı cavablayır: bu kimdir?
- Avtorizasiya (AuthZ) cavablayır: bu “kimə” nə etməyə icazə verilir?
ChatGPT App üçün sxem təxminən belədir:
- Əvvəlcə OAuth vasitəsilə təsdiqləyirsiniz ki, istifadəçi həqiqətən sizin Identity Provider-ə (IdP) (məsələn, Keycloak/Auth0) daxil olub və onun identifikatoru olan tokeni alırsınız. Bu — autentifikasiyadır.
- Daha sonra MCP server tokeni oxuyur, oradan sub, rollar və digər claims-ləri çıxarır və bu istifadəçinin konkret aləti (list_orders, delete_profile və s.) çağıra bilib-bilməyəcəyinə qərar verir. Bu — avtorizasiyadır.
Kod səviyyəsində bunu (sadələşdirilmiş) belə təsəvvür etmək olar:
// MCP serverinin istifadəçi haqqında bilmək istədiyi məlumat tipi
export interface AuthContext {
userId: string;
roles: string[];
}
// Tool handler-də istifadə nümunəsi
async function listGiftLists(auth: AuthContext | null) {
if (!auth) {
throw new Error("User is not authenticated");
}
// Yalnız bu istifadəçiyə aid siyahıları DB-dən götürürük
return db.giftLists.findMany({ where: { ownerId: auth.userId } });
}
userId və rollar olmadan düzgün biznes məntiqi yaza bilməyəcəksiniz. Hər şey “hamı üçün bir böyük ümumi hesab”a çevriləcək.
2. Niyə “API açarı .env-də” həll deyil
Bizdə, developer-lərdə, təbii bir refleks var: “API açarı yaradar, .env-ə qoyaram və hər şey işləyər”. Doğrudur, servis–servis daxili inteqrasiyalar üçün API açarları normal alətdir. Amma real istifadəçilər və ChatGPT App işə qarışan kimi “hamı üçün bir açar” yanaşması sıradan çıxır.
Erkən modullardan tipik bir koda baxaq, burada MCP-dən sadəcə öz backend-imizə vururduq:
// mcp/backendClient.ts
export const backendClient = new BackendClient({
baseUrl: process.env.BACKEND_URL!,
apiKey: process.env.BACKEND_API_KEY!, // bütün ChatGPT üçün bir açar
});
Backend baxımından indi bütün sorğular eyni görünür: “bu, ChatGPT inteqrasiyasıdır”. Masha ilə Pasha arasında heç bir fərq yoxdur. Nəticə:
- “Şəxsi kabinet” göstərmək olmur — server onun kimə məxsus olduğunu bilmir.
- Hüquqları bölmək olmur: “bu istifadəçi yalnız oxuya bilər, o isə həm də ala bilər”.
- Sifarişləri əsas sisteminizdə konkret şəxsə bağlamaq olmur.
MCP dünyasında bu həm də təhlükəsiz deyil. Spesifikasiya HTTP autentifikasiyasından (Bearer, API açarları və s.) Streamable HTTP vasitəsilə istifadəni tövsiyə edir, amma vurğulayır ki, istifadəçilərin qorunan resurslara tam girişi üçün bir servis açarı deyil, OAuth və tokenlər üzərində qurulmuş tam mexanizm daha doğrudur.
Üstəlik, OpenAI siyasəti baxımından, yaxşı tətbiq yalnız həqiqətən lazım olan məlumatları istəməli və istifadəçiyə App ilə nə paylaşdığını idarə etmək imkanı verməlidir. Bu, OAuth scope-lar modelinə əla uyğun gəlir, amma “hər şeyi bacaran super-açar” yanaşması ilə qətiyyən uyğunlaşmır.
ChatGPT kontekstində servis açarı niyə pisdir
Servis API açarı servisin şəxsiyyətini ifadə edir, istifadəçininkini yox. Onunla MCP serverinizdən daxili servislərə və ya xarici API-lərə (məsələn, OpenAI API) çağırışları imzalaya bilərsiniz, amma “Budur, bu Vasya-dır, onun sifariş tarixçəsini göstər” deyə bilməzsiniz.
Ən sadə anti-nümunə:
// Pis variant: istifadəçini "aldatma"
async function getMyOrdersFromBackend() {
// MCP server backend-də /orders/me çağırışı edir
const res = await fetch(`${BACKEND_URL}/orders/me`, {
headers: {
Authorization: `Bearer ${process.env.BACKEND_API_KEY}`,
},
});
// backend hesab edir ki, "me" — bu hansısa inteqrasiya servisidir, insan yox
return res.json();
}
Anonim bir userId-ni sorğunun gövdəsinə süni şəkildə yerləşdirməyə çalışsanız belə, bu yenə də “kustar velosiped” olaraq qalacaq. Sizə yenə də lazım olacaq:
- Backend-ə “bu həqiqətən Vasya-dır, başqası yox”u sübut etməyin etibarlı üsulu.
- Konkret istifadəçinin hüquqlarını məhdudlaşdırma üsulu.
- Bütün istifadəçilər üçün yox, məhz konkret istifadəçi üçün girişin geri çağırılması (revoke) mexanizmi.
Məhz burada OAuth səhnəyə çıxır.
3. Mini-lüğət: giriş sistemindən ümumiyyətlə nə istəyirik
OAuth tarixçəsinə atılmadan əvvəl, gəlin sadəcə ChatGPT App üçün “normal” autentifikasiya sistemindən tələbləri formalaşdıraq.
Bizə elə bir üsul lazımdır ki:
- Xarici IdP-miz (Keycloak, Auth0, Hydra+Kratos və s.) real istifadəçini bilsin: login, email, userId, bəlkə də tenant.
- Bu IdP qısaömürlü token versin, hansı ki, ChatGPT onu təhlükəsiz şəkildə MCP serverinə HTTP başlığında Authorization: Bearer <token> ötürə bilsin.
- MCP server tokeni oxuyub imzanı, issuer-i, audience-i, etibarlılıq müddətini və scopes-ları yoxlayıb sub-u (istifadəçi identifikatoru) çıxarsın və bunun əsasında istifadəçini öz entitilərinə map etsin (accountId, tenantId).
- Eyni scopes-lar hüquqları incə idarə etməyə imkan versin: bir token yalnız read:gifts versin, digərində isə əlavə write:gifts və ya checkout olsun.
- Əgər token yoxdur və ya lazım olan scopes yoxdur, server xəta qaytara bilsin və _meta["mcp/www_authenticate"] vasitəsilə ChatGPT istifadəçiyə avtorizasiya UI-ı göstərsin və/və ya tokeni yenidən alsın.
Ümumiyyətlə, bizə bütün bunları bacaran standart, zamanla sınaqdan keçmiş bir protokol lazımdır. Spoiler: bu OAuth 2.1-dir (və onun böyük/kiçik “qardaşları”).
4. OAuth-un qısa təkamülü: dinozavrlardan PKCE-yə
İndi OAuth-un təkamülünü sakitcə izləyək — RFC-lərə dərin dalmadan, ancaq niyə bizi məhz müasir pattern-lər maraqlandırır, başa düşək.
OAuth 1.0 / 1.0a: kripto-fitness
Tarixən ilk OAuth 1.0 yarandı. O, veb-saytlara istifadəçinin parolunu ötürmədən digər servislərə öz resurslarına giriş verməyə imkan verirdi (bu artıq pis deyil). Amma:
- Sorğuların imzalanması mürəkkəb idi: demək olar ki, hər sorğu üçün HMAC-imzalama, base-strings, parametr normalizasiyası.
- Hər sorğunu imzalamaq, consumer secret saxlamaq, imzanı düzgün formalaşdırmağı bacarmaq lazım idi.
Müasir developerlərin çoxu bu rəqsləri əl ilə təkrarlamağa meyilli deyil.
1.0a spesifikasiyası bəzi zəiflikləri düzəltsə də, ümumi həcmli/çətin quruluş qalırdı.
OAuth 2.0: “bir protokol” deyil, freymvörk
OAuth 2.0 həyatı xeyli sadələşdirdi: bir sərt sxem əvəzinə flow-lar dəsti yarandı (authorization code, implicit, resource owner password, client credentials və s.). Bu çeviklik verdi, amma eyni zamanda çoxsaylı implementasiya “zoopark”ı yaratdı.
Üstünlüklər:
- SPA, mobil və server tətbiqlərini inteqrasiya etmək asanlaşdı.
- Rolların aydın bölgüsü yarandı: Resource Owner, Client, Resource Server, Authorization Server.
Çatışmazlıqlar:
- Real dünyada təhlükəli “qısayollar” çoxaldı. implicit flow-u (tokeni birbaşa brauzerə server tərəfində kod mübadiləsi olmadan verən) təhlükəsiz çıxmadı.
- password grant flow-u (müştəri sadəcə istifadəçi login/parolunu tokenlə dəyişir) OAuth fəlsəfəsinə ziddir — və anti-pattern oldu.
Spesifikasiya özü “seçim üçün” çox variant buraxdı, buna görə ayrıca RFC-lərdə və bloqlarda yaşayan çoxlu tövsiyələr və best practice-lər yarandı.
OAuth 2.1: yığıldıq, nəfəs aldıq, qayda yaratdıq
OAuth 2.1 — zamanla icmada formalaşmış best practice-ləri sənədləşdirmək cəhdidir:
- Demək olar ki, tam fokus Authorization Code Flow üzərindədir.
- PKCE (Proof Key for Code Exchange) public müştərilər üçün mütləqdir — yəni sirri saxlaya bilməyənlər (mobil tətbiqlər, SPA və… ChatGPT/MCP müştəriləri).
- Köhnəlmiş və təhlükəsiz olmayan flow-lar — implicit və password grant — spesifikasiyadan çıxarılıb.
- Access token-in qısa ömrü və uzunmüddətli sessiyalar üçün refresh token-lərdən istifadə barədə tövsiyələr.
Bu, sizin üçün niyə vacibdir? Çünki MCP və ChatGPT ətrafındakı ekosistem məhz bu best practice-lərə yönəlib: Apps SDK və MCP Authorization spesifikasiyası açıq-aydın Authorization Code + PKCE, qısaömürlü tokenlər və normal scope-lar tələb edir.
5. Niyə ChatGPT App dünyasında OAuth 2.1 + PKCE pattern-ləri ilə düşünürük
Artıq tarixi kontekst var; indi buna ChatGPT və MCP prizmasından baxaq.
Public client kimi ChatGPT
ChatGPT (və MCP Jam kimi müştərilər) sizin Auth Server-ə nisbətdə tipik public client-dir:
- Onun etibarlı şəkildə saxlanılan client_secret-i yoxdur və ola da bilməz.
- O, sizin idarəetmədiyiniz OpenAI infrastrukturunda işləyir.
Bu səbəbdən yeganə adekvat seçim — Authorization Code Flow + PKCE-dir; burada təhlükəsizlik müştəri sirrinə yox, code challenge və code verifier yoxlamasına əsaslanır.
Apps SDK-nın rəsmi sənədləşməsi bildirir ki, ChatGPT MCP müştərisi kimi Authorization Code + PKCE (S256) flow-u icra edir və Authorization Server-in metadatada PKCE dəstəyi elan edilməyibsə avtorizasiyanı başa çatdırmaqdan imtina edəcək: code_challenge_methods_supported: ["S256"].
MCP baxımından flow necə görünür
Çox kobud, amma faydalı ardıcıllıq (qorunan resurs üçün) belə təsəvvür oluna bilər:
sequenceDiagram
participant U as İstifadəçi
participant C as ChatGPT (MCP Client)
participant AS as Auth Server
participant RS as MCP Server (Resurs)
U->>C: "Sifarişlərimi göstər"
C->>RS: call_tool(list_orders) tokensiz
RS-->>C: Xəta + _meta["mcp/www_authenticate"]
C->>AS: Login/consent açır (Authorization Code + PKCE)
U->>AS: Daxil olur və razılıq verir (scopes)
AS-->>C: Authorization Code
C->>AS: Kodu Access Token-lə mübadilə edir (+PKCE yoxlaması)
AS-->>C: Access Token (Bearer)
C->>RS: call_tool(list_orders) Authorization: Bearer <token> ilə
RS->>RS: İmza, issuer, audience, scopes yoxlanışı
RS-->>C: İstifadəçinin sifariş siyahısı
C-->>U: Məlumatları göstərir
Server bununla yanaşı istifadə edir:
- Qorunan resursun metadatasını (/.well-known/oauth-protected-resource) — burada o, özünü resurs kimi elan edir və bu resursa hansı Authorization Server-in xidmət göstərdiyini göstərir.
- Başlıqla gələn tokeni Authorization: Bearer <token>, ya JWK ilə JWT kimi yoxlayır, ya da Authorization Server vasitəsilə introspeksiya edir.
- Token audience və ya scopes uyğun deyilsə — server sorğunu rədd edə və yenə WWW-Authenticate challenge-ni _meta["mcp/www_authenticate"] vasitəsilə qaytara bilər ki, ChatGPT lazımi parametrlərlə avtorizasiyanı təkrarlasın.
Sizin kodunuz baxımından isə hər şey human görünür: siz artıq yoxlanmış AuthContext alırsınız və onunla işləyirsiniz.
Mini-nümunə: MCP tool anonim və autentifikasiya olunmuş istifadəçini necə fərqləndirir
Hələ konkret OAuth SDK-sız, sadəcə konsept:
import type { McpToolHandler } from "./types";
export const listOrders: McpToolHandler = async (_args, context) => {
const auth = context.auth; // tutaq ki, bura token yoxlamasının nəticəsini qoyuruq
if (!auth) {
return {
content: [{ type: "text", text: "Sifarişləri görmək üçün daxil olmalısınız." }],
_meta: {
// ChatGPT üçün challenge: OAuth flow-unı başlat
"mcp/www_authenticate": [
'Bearer resource_metadata="https://mcp.giftgenius.app/.well-known/oauth-protected-resource", error="insufficient_scope", error_description="Login required to view orders"'
]
},
isError: true
};
}
const orders = await db.orders.findMany({ where: { userId: auth.userId } });
return {
content: [{ type: "text", text: `Tapılan sifarişlər: ${orders.length}` }],
structuredContent: orders
};
};
Məhz belə bir _meta["mcp/www_authenticate"] ipucu Apps SDK-nın rəsmi sənədləşməsində ChatGPT tərəfindən OAuth UI-ını işə salmaq üçün trigger kimi təsvir edilib.
6. Praktikada “qısaömürlü token, minimal scopes” nə deməkdir
Spesifikasiyalar və qaydalardan daha bir neçə vacib prinsip çıxır; bunları növbəti IdP sazlama mühazirəsindən əvvəl də yadınızda saxlayın.
Tokenin qısa ömrü
Access token uzun yaşamamalıdır. Niyə?
- Əgər o sızsa, hücumçu yenə də vaxt baxımından məhdud olacaq.
- İstifadəçinin hüquqlarını təhlükəsiz dəyişə bilərsiniz və qısa müddətdən sonra token “köhnələcək” və yenisi tələb olunacaq.
Adətən bu — dəqiqələr və ya onlarla dəqiqədir. Bunun əvəzində refresh token-lər və/və ya təkrar avtorizasiyalar əldə edirsiniz, amma ChatGPT kontekstində işin çoxunu müştəri tərəfi görür.
Səlahiyyətləri məhdudlaşdırma üsulu kimi scopes
Scopes — gifts.read, gifts.write, orders.read, orders.checkout kimi sətirlərdir. Onlar bu resurs çərçivəsində istifadəçinin nəyə icazəsi olduğunu göstərir.
ChatGPT App üçün bu xüsusilə vacibdir:
- İstifadəçi sadəcə wish-list-lərə baxanda yalnız gifts.read olan token verə bilərsiniz.
- ACP/Instant Checkout əməliyyatları üçün isə daha sərt hüquqlar istəmək məntiqlidir — məsələn, orders.checkout — və bunu istifadəçiyə açıq göstərmək.
MCP-də alətlərin (tools) təsvirində artıq konkret alətlər üçün lazım olan scopes-ları göstərmək üçün securitySchemes elan etmək imkanı var ki, ChatGPT hansı aləti çağırmaq üçün hansı hüquqların lazım olduğunu bilsin.
Audience: token məhz bu MCP resursu üçün olmalıdır
Daha bir vacib detal — aud (audience). MCP server tokenin həqiqətən bu resurs üçün verildiyini, qonşu servis üçün olmadığını yoxlamalıdır.
Apps SDK sənədləşməsində açıq-aydın deyilir ki, ChatGPT resource parametrini ötürəcək və gözlənilir ki, Authorization Server onu tokenə (adətən aud kimi) əks etdirəcək, MCP server isə bu sahəni yoxlayacaq.
Böyük ehtimalla, tətbiqinizin review prosesində sizə saxta auth_token verib təhlükəsizlik implementasiyanızda boşluqlar olub-olmadığını yoxlayacaqlar. Odur ki, hər şeyi dərhal düzgün edin.
7. Bütün bunlar bizim GiftGenius tətbiqinə necə oturur
Yenə tədris App-imizə fokuslanaq. Hazırda təxminən belədir:
- get_gift_ideas MCP aləti var — alıcı təsviri və büdcəyə görə hədiyyə ideyaları təklif edir. Bu, anonim işləyə bilər.
- save_gift_list MCP aləti var — siyahını DB-də saxlayır. Onun konkret istifadəçiyə bağlı olmasını istəyirik.
- list_saved_lists MCP aləti var — istifadəçinin saxladığı bütün siyahıları göstərir. Bu, qətiyyən autentifikasiya tələb edir.
Widget gözəl hədiyyə kartları göstərir, “saxla” və “alındı” düymələrini basmağa verir — bunların hamısı əslində MCP-nin qorunan alətlərinin ön üzüdür.
Tip səviyyəsində bu belə görünə bilər:
// Tool çağırış kontekstinin tipizasiyası (sadələşdirilmiş)
interface ToolContext {
auth: AuthContext | null;
}
// Qorunan alət nümunəsi
async function listSavedGiftLists(_input: {}, context: ToolContext) {
if (!context.auth) {
// Burada yuxarıdakı kimi mcp/www_authenticate trick-i olacaq
throw new Error("Authentication required");
}
return db.giftLists.findMany({
where: { ownerId: context.auth.userId }
});
}
Və belə funksiya yazan kimi aydın olur: “sadəcə .env-də API açarı” heç nəyə kömək etmir. Tam funksional AuthContext lazımdır — hansı ki, yoxlanmış OAuth tokeni əsasında qurulur.
Tətbiqin hansı hissələri anonim işləyə, hansıları işləyə bilməz
OAuth sazlamadan əvvəl yaxşı məşq — funksionallıqdan keçib onu səmimi şəkildə iki kateqoriyaya bölməkdir.
Məsələn, GiftGenius-də:
Anonim:
- Təsvirə əsasən hədiyyə ideyalarının generasiyası.
- Nümunələrin göstərilməsi və saxta məlumatlarla demo rejim.
Yalnız autentifikasiya olunmuşlar üçün:
- Şəxsi wish-list-lərə baxış və redaktə.
- Sifariş tarixçəsi.
- Hər cür ödəniş əməliyyatları, Instant Checkout, ACP-ə bağlama.
Növbəti mühazirələrdə Auth Server-i (məsələn, Keycloak və ya Hydra+Kratos cütlüyü) və MCP serveri elə sazlayacağıq ki, bu əməliyyatların tokenləri lazımi scopes-lara malik olsun və MCP alətləri düzgün şəkildə rədd etməyi və ChatGPT-dən yenidən avtorizasiya istəməyi bacarsın.
8. ChatGPT App-də autentifikasiya anlayışında tipik səhvlər
Xəta №1: “Axı ChatGPT artıq istifadəçini bilir, mənə niyə öz loginim lazımdır?”
Çoxları düşünür: “ChatGPT-də istifadəçi hesabı var, niyə bunu sadəcə userId kimi istifadə etməyim?” Amma ChatGPT sizə istifadəçinin real şəxsiyyətini açıqlamır və öz hesablarına çıxış vermir. MCP metadatasında ən yaxşı halda anonim _meta["openai/subject"] görürsünüz — hansı ki, rate-limit-lər və sessiya identifikasiyası üçün nəzərdə tutulub, amma onu avtorizasiya və ya real hesablarla bağlamaq üçün istifadə etmək olmaz deyə açıq qeyd olunur.
Xəta №2: “Hamı üçün bir API açarı normaldır, axı bu sadəcə ‘inteqrasiya’dır”
“MCP serverinə backend API açarını tikdik və sevinirik” yanaşması yalnız bütün ChatGPT istifadəçilərinin sizin servisdə eyni hesabı paylaşdığı ssenarilər üçün işləyir. Şəxsi məlumatlar, commerce, ACL peyda olan kimi siz istifadəçiləri fərqləndirmək və onların hüquqlarını idarə etmək imkanının olmamasına dirənirsiniz. API açarı — bu, servisin şəxsiyyətidir, istifadəçinin yox.
Xəta №3: “Tezliklə password grant yazarıq, ən asanı budur”
İstifadəçinin login/parolunu backend-ə ötürüb tokenlə dəyişmək (Resource Owner Password Credentials Grant) — OAuth 2.0-ın erkən dövrlərindən köhnəlmiş və təhlükəsiz olmayan pattern-dir. Müasir tövsiyələrdə və OAuth 2.1 kontekstində bu anti-pattern sayılır. ChatGPT kimi public müştərilər ümumiyyətlə istifadəçi parollarını görməməlidirlər — bunun üçün Authorization Code + PKCE var.
Xəta №4: “PKCE əlavə mürəkkəblikdir, gəlin onsuz edək”
PKCE (xüsusən S256) — public müştərilər üçün Authorization Code Flow-un mütləq qoruma mexanizmidir. PKCE olmadan oğurlanmış authorization code yenidən istifadə oluna bilər. MCP Authorization spesifikasiyasında və Apps SDK-da açıq yazılıb ki, ChatGPT Authorization Server metadatasında PKCE dəstəyinin elanını tələb edir və məhz bu mexanizmdən istifadə edir. Onu söndürsəniz, flow sadəcə işləməyəcək.
Xəta №5: “Gəlin ehtiyat üçün bütün mümkün scopes-ları bir dəfəyə istəyə bilərik”
Bəzən “hər şeyi açan” token yaratmaq istəyirsiniz. Amma bu, minimum səlahiyyət prinsipi (PoLP) ilə ziddiyyət təşkil edir və həm OpenAI, həm də əksər IdP-lərin siyasətləri ilə uyğun gəlmir. ChatGPT App-inizə hansı scopes-ların həqiqətən lazım olduğunu dəqiq düşünmək daha yaxşıdır: bəziləri oxu, bəziləri yazma, ayrılıqda commerce üçün. Bu, yalnız təhlükəsizliyi artırmır, həm də consent UX-ə təsir edir: istifadəçi anlaşılır və məhdudlaşdırılmış hüquqlar dəstini görür, qorxuducu, naməlum 20 sətirlik siyahını yox.
Xəta №6: “MCP server login/parolları özü saxlayacaq və login UI-ı çəkəcək”
MCP server — Resource Server-dir, Auth Server deyil. O, tokenləri yoxlamağı, öz .well-known metadatasını elan etməyi və WWW-Authenticate challenge-lərini qaytarmağı bacarmalıdır, amma login və parol saxlamaqla məşğul olmamalıdır. Login/consent üçün ixtisaslaşmış Authorization Server-dən (Keycloak, Hydra, Auth0 və s.) istifadə etmək daha yaxşıdır — bunu növbəti mühazirələrdə görəcəyik.
GO TO FULL VERSION