Tek sayfalık bir React uygulamasına giriş ekleyin
Bu hızlı başlangıç, Vite ile oluşturulmuş bir React tek sayfalık uygulamasına @keenauth/js tarayıcı SDK'sını kullanarak KeenAuth girişi ekler. Uygulama, kullanıcıları yönlendirme ile giriş yaptırır, DPoP ile bağlanmış bir erişim belirteciyle korunan bir API'yi çağırır ve kullanıcıları çıkış yaptırır. Ayrıca bunu çevrimdışı test edersiniz. SDK, JavaScript tarayıcı SDK'sı sayfasında açıklanmıştır.
Tek sayfalık bir uygulamada belirteçler tarayıcıda bulunur. SDK bunları yalnızca bellekte tutar ve DPoP ile dışa aktarılamayan bir anahtara bağlar; böylece çalınan bir belirteç bu anahtar olmadan kullanılamaz. Uygulamanızın bir sunucusu varsa, Next.js hızlı başlangıcı bunun yerine tüm belirteçleri sunucuda tutar (arka uç-ön uç, backend for frontend); bu daha güçlü bir seçenektir.
Uygulamanın şu yolları vardır:
| Yol | Ne yapar |
|---|---|
/ |
Bir giriş düğmesi veya kullanıcı, API'nizi çağıran bir düğme ve bir çıkış düğmesi |
/callback |
Yönlendirme URI'si. SDK girişi burada tamamlar ve uygulama kullanıcının başladığı sayfaya geri döner |
Başlamadan önce
- Bir KeenAuth ortamı. Ortamınızın issuer değeri şuna benzer:
https://your-environment.eu.keenauth.app. - Ortamda bir tek sayfalık uygulama (Uygulama oluşturun);
app_typedeğerispavetoken_endpoint_auth_methoddeğerinoneolmalıdır (genel istemcinin sırrı yoktur).developmentortamında şunları kaydedin:- yönlendirme URI'si
http://localhost/callback(loopback yönlendirme URI'si port belirtilmeden kaydedilir ve herhangi bir portla eşleşir); - çıkış sonrası yönlendirme URI'si
http://localhost/; - izin verilen web kökeni
http://localhost:5173, böylece tarayıcı belirteç uç noktasını çağırabilir.
- yönlendirme URI'si
- Ortamda kayıtlı bir API (API oluşturun) ve
messages:readkapsamı. Örneğinhttps://api.example.comolanidentifierdeğeri, erişim belirteçlerinin hedef kitlesidir (audience). Express hızlı başlangıcı bu belirteçleri kabul eden bir API oluşturur. - Node.js 22.18 veya üzeri.
1. Kurun
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install @keenauth/js
SDK henüz yayımlanmadı. Yayımlanana kadar örnek, package.json dosyasındaki bağlantıyla SDK kaynağına işaret eder. Örnek vite@8.3.4, @vitejs/plugin-react@6.1.2, react@19.3.1 ve react-dom@19.3.1 sürümlerini sabitler.
2. Yapılandırın
Uygulama yapılandırmasını yalnızca ortam değişkenlerinden okur. Bunları Vite'ın yüklediği .env.local dosyasına koyun ve bu dosyayı asla commit etmeyin. Vite her VITE_ değişkenini tarayıcının indirdiği JavaScript'e derler; bu yüzden oraya hiçbir gizli bilgi koymayın. Bu uygulamanın gizli bilgisi yoktur.
| Değişken | Zorunlu | Anlamı |
|---|---|---|
VITE_KEENAUTH_ISSUER |
evet | Ortamınızın issuer değeri |
VITE_KEENAUTH_CLIENT_ID |
evet | Tek sayfalık uygulamanın client_id değeri |
VITE_KEENAUTH_API_AUDIENCE |
evet | KeenAuth'taki API'nizin identifier değeri |
VITE_API_URL |
hayır | API'nizin temel URL'si. Boş bırakılırsa uygulamanın kendi kökeni kullanılır |
API_PROXY_TARGET |
hayır | Yalnızca geliştirme: geliştirme sunucusunun /api isteklerini yönlendirdiği adres; varsayılan http://localhost:8080 |
loadConfig bu değerleri okur ve denetler. Bir değer eksikse, uygulamayı adını belirterek bir hatayla durdurur:
export function loadConfig(env: Readonly<Record<string, unknown>>): AppConfig {
const need = (name: string): string => {
const v = env[name];
if (typeof v !== "string" || v.trim() === "") throw new Error(`${name} is required (see .env.example)`);
return v.trim();
};
3. SDK istemcisini oluşturun
export function createAuth(config: AppConfig, origin: string, inject: Injectables = {}): KeenAuth {
return new KeenAuth({
issuer: config.issuer,
clientId: config.clientId,
redirectUri: `${origin}${CALLBACK_PATH}`,
postLogoutRedirectUri: `${origin}/`,
// The access token is for this API: its aud is the API identifier (RFC 8707).
resource: config.apiAudience,
// messages:read is a scope of that API; the example API requires it on /api/messages.
scope: "openid profile email offline_access messages:read",
...inject,
});
}
resource, API'nizin identifier değeridir (RFC 8707). SDK bunu yetkilendirme isteğinde, kod değişiminde ve her yenilemede gönderir; erişim belirtecinin hedef kitlesi (aud) API'nizdir. Bu olmazsa erişim belirteci API'niz için düzenlenmemiş olur ve API bunu reddeder. SDK istemci oluşturulurken her seçeneği denetler; geçersiz bir issuer veya resource, config_invalid koduyla bir KeenAuthError fırlatır.
Sayfa için tek bir istemci oluşturun ve bunu bir sağlayıcıya verin:
const config = loadConfig(import.meta.env);
const auth = createAuth(config, window.location.origin);
createRoot(document.getElementById("root")!).render(
<StrictMode>
<AuthProvider auth={auth}>
<App apiUrl={config.apiUrl} />
</AuthProvider>
</StrictMode>,
);
4. Girişi başlatın ve geri çağrıyı işleyin
Giriş düğmesi yönlendirmeli girişi başlatır: PKCE (S256), state ve nonce ile yetkilendirme kodu akışı. appState, dönülecek yoldur.
<button onClick={() => auth.signInRedirect({ appState: window.location.pathname })}>Sign in</button>
KeenAuth sizi /callback adresine geri yönlendirdiğinde sağlayıcı girişi tamamlar. SDK state, iss ve ID belirtecini denetler ve kodu bir DPoP kanıtıyla değiştirir. Bir yetkilendirme yanıtı yalnızca bir kez kullanılabilir ve React'in StrictMode'u geliştirmede efektleri iki kez çalıştırdığı için completeSignIn ilk sonucu hatırlar:
export function completeSignIn(auth: KeenAuth, href: string): Promise<string | null> {
const url = new URL(href);
if (url.pathname !== CALLBACK_PATH || !(url.searchParams.has("code") || url.searchParams.has("error"))) {
return Promise.resolve(null);
}
let done = completions.get(auth);
if (!done) {
done = auth.handleRedirectCallback(href).then((r) => safeReturnPath(r.appState));
completions.set(auth, done);
}
return done;
}
Sağlayıcı ardından adres çubuğundan code ve state parametrelerini kaldırır. Yalnızca uygulamanızın içindeki bir yol dönüş yolu olarak kullanılır; böylece hazırlanmış bir appState kullanıcıyı başka bir siteye yönlendiremez:
export function safeReturnPath(path: string | undefined): string {
return path !== undefined && /^\/(?![/\\])/.test(path) ? path : "/";
}
Üretimde de /callback için index.html sunun (Vite geliştirme sunucusu bunu zaten yapar).
5. API'nizi çağırın
authorizedFetch, belirtece bağlı yeni bir kanıtla Authorization: DPoP <token> başlığını gönderir ve belirteç süresi dolmak üzereyken onu yeniler:
export async function fetchMessages(auth: KeenAuth, apiUrl: string): Promise<unknown> {
const res = await auth.authorizedFetch(`${apiUrl}/api/messages`, { headers: { Accept: "application/json" } });
if (!res.ok) throw new Error(`The API answered ${res.status}`);
return res.json();
}
Geliştirmede Vite geliştirme sunucusu /api isteklerini API'nize iletir; böylece tarayıcı API'yi uygulamanın kendi kökeninden çağırır ve API'nin CORS ayarına ihtiyaç duymaz:
proxy: { "/api": env.API_PROXY_TARGET || "http://localhost:8080" },
API, DPoP kanıtını tarayıcının çağırdığı URL'ye göre denetler. Express hızlı başlangıcının API'sini bu proxy arkasında çalıştırdığınızda, PUBLIC_BASE_URL değerini http://localhost:5173 olarak ayarlayın. Üretimde API'yi aynı kökenden sunun ya da uygulamanızın kökeni için API'de CORS'u etkinleştirin ve VITE_API_URL değerini ayarlayın.
6. Çıkış yapın
<button onClick={() => auth.signOut()}>Sign out</button>
signOut belirteçleri siler, yenileme belirtecini iptal eder ve tarayıcıyı ortamınızın çıkış uç noktasına gönderir; bu uç nokta tarayıcıyı / adresine geri döndürür.
7. Uygulamayı çalıştırın
Express hızlı başlangıcındaki API'yi PUBLIC_BASE_URL=http://localhost:5173 ve KEENAUTH_AUDIENCE değeri API'nizin identifier değeri olacak şekilde başlatın, ardından uygulamayı çalıştırın:
cp .env.example .env.local # then fill it in
npm run dev
http://localhost:5173 adresini açın, Sign in seçeneğini seçin, KeenAuth'ta giriş yapın ve Call the API seçeneğini seçin.
SDK belirteçleri yalnızca bellekte tutar. Sayfa yeniden yüklendikten sonra kullanıcı uygulamada çıkış yapmış olur ve yeniden giriş yapar; KeenAuth oturumu genellikle bunu bir istem olmadan, yalnızca bir yönlendirmeye dönüştürür.
8. Ağ olmadan test edin
Testler ağ bağlantısı ve bir KeenAuth hesabı gerektirmez. Sahte bir fetch, yetkilendirme sunucusunu ve API'yi taklit eder; ID belirteci test için üretilmiş bir anahtarla imzalanır. Node, TypeScript testlerini doğrudan çalıştırır.
assert.deepEqual(await fetchMessages(s.auth, ""), { messages: ["hello"] });
const call = s.seen.find((c) => c.url === `${ORIGIN}/api/messages`)!;
assert.equal(call.headers.get("Authorization"), "DPoP access-token-1");
npm test
npm run typecheck
npm run deps # pinned versions, lockfile sources and licences
npm run build
Testler şunları denetler: yapılandırmanın doğrulandığını, SDK'nın geçersiz bir issuer veya resource değerini reddettiğini, girişin PKCE S256 ve API'nizi resource olarak gönderdiğini, geri çağrının bir kez tamamlandığını ve resource değerini kodla birlikte gönderdiğini, sahte bir state değerinin herhangi bir belirteç isteğinden önce reddedildiğini, girişten sonra yalnızca uygulama içindeki bir yolun kullanıldığını, hiçbir belirtecin depolamaya yazılmadığını ve API çağrısının DPoP ile bağlanmış belirteci ve bu belirtecin kanıtını taşıdığını.
Gerçek bir tarayıcıyla tam giriş için bir KeenAuth ortamı gerekir. Bu, çevrimdışı testlerin parçası değildir.
Sonraki adımlar
- JavaScript tarayıcı SDK'sı: her seçenek, belirteçlerin nerede tutulduğu ve mevcut sınırlar.
- React SDK'sı: gömülü giriş, hesap oluşturma ve hesap bileşenleri.
- Express API'sini koruyun: bu uygulamanın çağırdığı API.