JWT Decoder JavaScript — atob(), TextDecoder ve jose

·JavaScript Performance Engineer·İnceleyenSophie Laurent·Yayınlandı

Ücretsiz JWT Kod Çözücü aracını doğrudan tarayıcınızda kullanın — kurulum gerektirmez.

JWT Kod Çözücü Online Dene →

Geliştirdiğim her kimlik doğrulama akışı eninde sonunda aynı noktaya ulaşır: bir çerezde, başlıkta veya OAuth geri çağırma URL'sinde duran bir JWT vardır ve içinde ne olduğunu okumanız gerekir. JavaScript ile JWT çözümleyici herhangi bir npm paketi gerektirmez. Token'ın başlığı ve yükü, yalnızca Base64url kodlu JSON'dan ibarettir; hem tarayıcı hem de Node.js, bunları çözümlemek için gereken her şeyle birlikte gelir. Bu kılavuz, JWT'ler için tam JavaScript metin çözümleyiciardışık düzenini kapsar: token'ı bölmek, base64url kodlamasını standart Base64'e normalleştirmek, atob() ve TextDecoder ile düzgün UTF-8 işleme, Node.js Buffer.from(), jose ile imza doğrulama ve her gün geliştiricilerin tökezlediği yaygın hatalar. Hızlı tek seferlik bir inceleme için bunun yerine çevrimiçi JWT Çözümleyici aracını deneyin. Tüm örnekler ES2020+ ve Node.js 18+ hedeflemektedir.

  • JWT'yi "." karakterine göre bölün — 0. indeks başlık, 1. indeks yük, 2. indeks imzadır.
  • atob() Base64'ü çözer ancak UTF-8 değil Latin-1 döndürür. ASCII dışı claimler için TextDecoder veya Buffer.from() kullanın.
  • Buffer.from(segment, "base64url") Node.js'te base64url'yi yerel olarak destekler — manuel karakter değişimine gerek yoktur.
  • Çözümleme, DOĞRULAMA değildir. Sunucu tarafında imzayı kontrol etmeden çözümlenmiş JWT claimlerine güvenmeyin.
  • jose kütüphanesi her ikisini de yapar: HS256/RS256/ES256 imzalarını doğrular ve tek çağrıda çözümlenmiş yükü döndürür.

JWT Çözümleme Nedir?

Bir JSON Web Token, nokta ile ayrılmış üç Base64url kodlu segmentten oluşur. İlk segment başlık, ikincisi yük (asıl önem verdiğiniz claimler), üçüncüsü ise kriptografik imzadır. Başlık, token'ın kendisini tanımlayan küçük bir JSON nesnesidir. En önemli alanı alg — imzalama algoritmasıdır (ör. HS256, RS256, ES256). typ alanı neredeyse her zaman "JWT"şeklindedir; isteğe bağlı kid alanı ise token'ı imzalamak için hangi anahtarın kullanıldığını belirtir — bir kimlik sağlayıcısının anahtarları döndürdüğü ve birden fazla genel anahtar içeren bir JWKS uç noktası yayımladığı durumlarda bu alan kritik öneme sahiptir.

Yük, claimleri taşır. RFC 7519, yedi kayıtlı claim adı tanımlar: sub (konu — genellikle kullanıcı kimliği), iss (yayıncı — kimlik doğrulama sunucusu URL'si), aud (hedef kitle — token'ın yönelik olduğu API), iat (düzenlenme zaman damgası), exp (son kullanma zaman damgası), nbf (geçerlilik başlangıç zaman damgası) ve jti (JWT kimliği — yeniden oynatma saldırılarını önlemek için kullanılır). Tüm zaman damgaları milisaniye değil Unix epoch saniyesidir. İmza segmenti ham ikili veridir — anahtarlı HMAC özeti veya asimetrik dijital imzadır. Diğer segmentler gibi Base64url kodludur; ancak baytları JSON değildir ve insanın okuyabileceği bir yapıya sahip değildir.

Pratikte JavaScript'te JWT'leri üç yaygın nedenle çözümlersiniz. Birincisi, hata ayıklama: bir OAuth akışından veya test ortamından bir token aldınız ve claimlerin kimlik doğrulama sunucusunun vermiş olması gereken şeylerle örtüşüp örtüşmediğini doğrulamak istiyorsunuz. İkincisi, kullanıcı claimlerini istemci tarafında görüntüleme amaçlı okumak — ekstra bir API çağrısı olmadan token yükünden oturum açmış kullanıcının adını, avatar URL'sini veya rol rozetini göstermek. Üçüncüsü, yenileme girişiminden önce son kullanma tarihini kontrol etmek: eğer exp önümüzdeki 60 saniye içindeyse, bir 401 yanıtını beklemek yerine bir sonraki API çağrısından önce sessiz bir yenileme işlemi tetikleyin.

Çözümleme, token'ın geçerli veya değiştirilmemiş olup olmadığını kontrol etmez. Bu, HMAC sırrı ya da RSA/ECDSA genel anahtarı gerektiren doğrulama adı verilen ayrı bir işlemdir. Herkes bir JWT'yi çözümleyebilir. Yalnızca doğru anahtara sahip olan kişi doğrulayabilir. Bu ayrım, çözümlenmiş claimlerin görüntülendiği ancak yetkilendirme kararları için doğrulanmış bir arka uç kontrolü olmaksızın hiçbir zaman güvenilmemesi gereken istemci tarafı kimlik doğrulama akışları oluştururken pek çok geliştiricinin tökezlediği bir konudur.

Before · json
After · json
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOTIxZiIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTcxMTYxMDAwMH0.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
// Başlık
{ "alg": "HS256" }

// Yük
{
  "sub": "usr_921f",
  "role": "admin",
  "iat": 1711610000
}

atob() + TextDecoder — Tarayıcı Yerleşik JWT Çözümlemesi

Bir JWT'yi çözümlemek için tarayıcı yerleşik ardışık düzenin dört adımı vardır. Birincisi, token dizesini "." karakterine göre bölüp üç segmenti elde etmek. İkincisi, base64url segmentini - yerine + ve _ yerine / koyarak normalleştirmek, ardından uzunluk 4'ün katı olana dek = karakterleriyle doldurmak. Üçüncüsü, Base64'ü ikili dizeye dönüştürmek için atob() çağırmak. Dördüncüsü, TextDecoder kullanarak ikili dizeyi düzgün UTF-8'e dönüştürmek. Son adım önemlidir çünkü atob() Latin-1 döndürür. Çok baytlı karakterler — emoji, CJK metni, Latin-1 aralığının ötesindeki aksanlı karakterler — JavaScript metin çözümleyici adımı olmadan bozuk çıkar.

JavaScript — minimal JWT çözümleme
const token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOTIxZiIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTcxMTYxMDAwMH0.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";

function decodeJwtPayload(jwt) {
  const base64Url = jwt.split(".")[1];
  const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
  const padded = base64.padEnd(base64.length + (4 - (base64.length % 4)) % 4, "=");
  const binary = atob(padded);
  const bytes = Uint8Array.from(binary, ch => ch.charCodeAt(0));
  const json = new TextDecoder("utf-8").decode(bytes);
  return JSON.parse(json);
}

console.log(decodeJwtPayload(token));
// { sub: "usr_921f", role: "admin", iat: 1711610000 }

Doldurma adımı gözden kaçırılması kolaydır. JWT'ler, Base64url segmentlerinden sondaki = karakterlerini çıkarır; çünkü JWT spesifikasyonu (RFC 7515) base64url'yi dolgu olmadan tanımlar. Ancak bazı tarayıcı motorlarındaki atob(), giriş uzunluğu 4'e bölünmüyorsa bir InvalidCharacterError fırlatır. padEnd() ile koruyucu biçimde doldurmak, tüm ortamlarda bu sınır durumunu ortadan kaldırır. Hem başlığı hem de yükü ayrı nesnelere çözümleyen yeniden kullanılabilir bir sürüm:

JavaScript — başlık ve yük çözümleme
function decodeBase64Url(segment) {
  const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
  const padded = base64.padEnd(base64.length + (4 - (base64.length % 4)) % 4, "=");
  const binary = atob(padded);
  const bytes = Uint8Array.from(binary, ch => ch.charCodeAt(0));
  return new TextDecoder("utf-8").decode(bytes);
}

function decodeJwt(token) {
  const [headerB64, payloadB64] = token.split(".");
  return {
    header: JSON.parse(decodeBase64Url(headerB64)),
    payload: JSON.parse(decodeBase64Url(payloadB64)),
  };
}

const { header, payload } = decodeJwt(token);
console.log("Algorithm:", header.alg);   // "HS256"
console.log("Subject:", payload.sub);     // "usr_921f"
console.log("Role:", payload.role);       // "admin"

Bu iki fonksiyona sahip olduğunuzda, mantığı dosyalar arasında kopyalamak yerine paylaşılan bir yardımcı modüle yerleştirmek mantıklıdır. src/lib/jwt.ts veya utils/jwt-decode.ts dosyası, tiplendirilerek dönüş şeklini kod tabanı genelinde açık hale getirir. TypeScript'te dönüşü { header: JwtHeader; payload: JwtPayload } olarak tiplendirebilirsiniz; burada JwtHeader alg, typ ve isteğe bağlı kid içerir, JwtPayload ise RFC 7519 kayıtlı claimlerini özel claimler için indeks imzasıyla genişletir. Çözümleme mantığını merkezileştirmek, daha sonra hata işleme (hatalı biçimlendirilmiş segmentleri yakalamak) veya telemetri (çözümleme hatalarını günlüğe kaydetmek) eklemek istediğinizde yalnızca tek bir yeri güncellemeniz gerektiği anlamına gelir.

Not:Bu ardışık düzeni ASCII dışı claimler için güvenli kılan TextDecoder adımıdır. Bu adım olmadan, atob() çok baytlı UTF-8 dizilerinin karakterlere bölündüğü Latin-1 bir dize döndürür. Emoji veya CJK metni yerine anlamsız karakterler görürsünüz. atob() sonrasında her zaman new TextDecoder("utf-8") üzerinden geçirin.

Çok Baytlı Karakterlerle UTF-8 JWT Claimlerini Çözümleme

JWT yükleri, base64url olarak kodlanmış UTF-8 JSON'dır. Yüklerin büyük çoğunluğu yalnızca ASCII kullanıcı kimlikleri ve zaman damgaları içerdiğinden geliştiriciler atob()'nin UTF-8 yerine Latin-1 döndürdüğünü hiç fark etmez. Sorun, bir claim emoji, Japonca karakter, Kiril veya U+00FF'in üzerindeki herhangi bir kod noktası içerdiği anda ortaya çıkar. JavaScript UTF-8 çözümleme deseni, ikili dizeyi önce bir bayt dizisine dönüştürmeyi, ardından TextDecoder üzerinden geçirmeyi gerektirir.

JavaScript — JWT yükünde emoji içeren UTF-8 tam döngüsü
// Emoji ve CJK karakterler içeren bir JWT yükünü simüle etme
const payloadObj = {
  sub: "usr_e821",
  display_name: "田中太郎",
  team: "Platform 🚀",
  region: "ap-northeast-1"
};

// Kodlama: nesne → JSON → UTF-8 baytları → base64url
const jsonStr = JSON.stringify(payloadObj);
const utf8Bytes = new TextEncoder().encode(jsonStr);
const base64 = btoa(String.fromCharCode(...utf8Bytes))
  .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");

// Çözümleme: base64url → base64 → ikili dize → baytlar → UTF-8 dize
const base64Std = base64.replace(/-/g, "+").replace(/_/g, "/");
const binary = atob(base64Std);
const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
const decoded = new TextDecoder("utf-8").decode(bytes);
const result = JSON.parse(decoded);

console.log(result.display_name); // "田中太郎" — doğru
console.log(result.team);         // "Platform 🚀" — doğru

Eski kod tabanlarında decodeURIComponent ile yüzde kodlama hilesini birleştiren eski bir yedek desen görebilirsiniz. Bu JavaScript decodeURIComponent yaklaşımı, her baytı bir yüzde-onaltılık çifte yeniden kodladığı ve ardından decodeURIComponent'in çok baytlı UTF-8 dizilerini yeniden birleştirdiği için çalışır:

JavaScript — UTF-8 için decodeURIComponent yedek deseni
function decodeBase64UrlLegacy(segment) {
  const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
  const binary = atob(base64);
  // Her karakteri %XX onaltılığına çevir, ardından decodeURIComponent UTF-8'i yeniden birleştirir
  const utf8 = decodeURIComponent(
    binary.split("").map(c =>
      "%" + c.charCodeAt(0).toString(16).padStart(2, "0")
    ).join("")
  );
  return utf8;
}

// TextDecoder olmadan ASCII dışı claimler için çalışır
const payload = decodeBase64UrlLegacy(token.split(".")[1]);
console.log(JSON.parse(payload));
Uyarı:Eski JWT yardımcı kod parçacıklarında decodeURIComponent(escape(atob(segment))) desenine rastlayabilirsiniz. escape() fonksiyonu kullanımdan kaldırılmıştır ve standart dışıdır. Yukarıda gösterilen TextDecoder yaklaşımıyla değiştirin. JavaScript unescape çözümleyici deseni de aynı sorunu taşır: unescape() kullanımdan kaldırılmıştır. Her iki fonksiyon da gelecekteki JavaScript motorlarından kaldırılabilir.

JWT Çözümleme Ardışık Düzeni — Adım Başvurusu

Tarayıcı yerleşik JWT çözümleme ardışık düzenindeki her adım, kullanılan JavaScript API'si ve ürettiği çıktı ile birlikte:

Parametre / Adım
Tür
Açıklama
token.split(".")
string[]
JWT'yi [başlık, yük, imza] segmentlerine böler
base64url → base64
string replace
- yerine +, _ yerine / koy; uzunluğu 4'ün katı olacak şekilde = ile doldur
atob(base64)
string
Standart bir Base64 dizesini ikili dizeye (Latin-1) dönüştürür
TextDecoder("utf-8")
TextDecoder
Ham baytlardan oluşan Uint8Array'i düzgün bir UTF-8 dizesine çevirir
JSON.parse()
object
Elde edilen JSON dizesini bir JavaScript nesnesine ayrıştırır

Node.js eşdeğeri, 2 ile 4 arasındaki adımları tek bir çağrıda birleştirir: Buffer.from(segment, "base64url").toString("utf-8"). "base64url" kodlama seçeneği, alfabe dönüşümünü ve dolguyu dahili olarak yönetir.

Buffer.from() — JWT'ler için Node.js Dize Çözümleyici

Node.js'te çok daha basit bir yol vardır. Buffer sınıfı doğrudan "base64url" kodlamasını kabul ettiğinden manuel karakter değişimi ve dolgu adımlarını atlarsınız. Bu, sunucu tarafı kod için JavaScript dize çözümleyici yoludur. Tek bir satır, JWT segmentini UTF-8 dizesine dönüştürür ve ekstra adımlar olmadan çok baytlı karakterleri doğru şekilde işler.

Node.js 18+ — Buffer ile JWT çözümleme
const token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOTIxZiIsIm9yZyI6ImFjbWUtY29ycCIsInJvbGUiOiJiaWxsaW5nIiwiaWF0IjoxNzExNjEwMDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";

function decodeJwt(jwt) {
  const segments = jwt.split(".");
  return {
    header: JSON.parse(Buffer.from(segments[0], "base64url").toString("utf-8")),
    payload: JSON.parse(Buffer.from(segments[1], "base64url").toString("utf-8")),
  };
}

const { header, payload } = decodeJwt(token);
console.log(header);
// { alg: "HS256" }
console.log(payload);
// { sub: "usr_921f", org: "acme-corp", role: "billing", iat: 1711610000 }

Her Node.js projesinde tercih ettiğim yaklaşım budur. Daha kısa, daha hızlı ve UTF-8'i zaten doğru şekilde işler. TextDecoder gerekmez, karakter değişimi yok, dolgu matematiği yok. Buffer sınıfı, base64url alfabesini yerel olarak işleyen bir JavaScript dize çözümleyicidir; bu da karakter değişimiyle ilgili hataların tamamını ortadan kaldırır. Kodunuzun hem tarayıcıda hem de Node.js'te çalışması gerekiyorsa, çalışma zamanını algılayan isomorfik bir sarmalayıcı fonksiyon için en alttaki SSS bölümüne bakın.

Yaygın JWT claimlerini nasıl çıkaracağınızı ve zaman damgalarını okunabilir tarihlere nasıl dönüştüreceğinizi gösteren, ara katman ve API rota işleyicilerinde en sık kullanacağınız desen olan daha eksiksiz bir örnek:

Node.js — pratik JWT claim çıkarımı
function inspectToken(token) {
  const segments = token.split(".");
  if (segments.length !== 3) {
    throw new Error("Not a valid JWT — expected 3 dot-separated segments");
  }

  const header = JSON.parse(Buffer.from(segments[0], "base64url").toString("utf-8"));
  const payload = JSON.parse(Buffer.from(segments[1], "base64url").toString("utf-8"));

  const inspection = {
    algorithm: header.alg,
    tokenType: header.typ || "JWT",
    subject: payload.sub,
    issuer: payload.iss || "(ayarlanmamış)",
    audience: payload.aud || "(ayarlanmamış)",
    issuedAt: payload.iat ? new Date(payload.iat * 1000).toISOString() : "(ayarlanmamış)",
    expiresAt: payload.exp ? new Date(payload.exp * 1000).toISOString() : "(hiçbir zaman)",
    isExpired: payload.exp ? payload.exp < Math.floor(Date.now() / 1000) : false,
    customClaims: Object.keys(payload).filter(
      k => !["sub", "iss", "aud", "iat", "exp", "nbf", "jti"].includes(k)
    ),
  };

  return inspection;
}

console.log(inspectToken(process.env.ACCESS_TOKEN));
// {
//   algorithm: "RS256",
//   tokenType: "JWT",
//   subject: "usr_921f",
//   issuer: "https://auth.internal",
//   audience: "billing-api",
//   issuedAt: "2026-03-10T14:00:00.000Z",
//   expiresAt: "2026-03-10T15:00:00.000Z",
//   isExpired: true,
//   customClaims: ["role", "scope", "org"]
// }

Üretim Node.js servislerinde, Buffer.from() çözümleme deseni üç tekrarlayan yerde karşımıza çıkar. Birincisi istek günlüğü ara katmanı: gelen Authorization başlığını çözümleyerek kimlik doğrulama sunucusuna ekstra bir ağ gidiş dönüşü yapmadan her yapılandırılmış günlük girişine userId ve org bilgilerini eklersiniz. İkincisi hata ayıklama: test iddiaları yazmadan önce doğru kapsamların verilip verilmediğini onaylamak için geliştirme sırasında çözümlenmiş token claimlerini konsola yazdırırsınız. Üçüncüsü ise API ağ geçitlerinde proaktif token yenileme. Upstream'e bir token iletip downstream servisin token sona erdiğinde 401 döndürmesini beklemek yerine, ağ geçidi token'ı kenarda çözümler, exp claimini okur ve son kullanma süresi önümüzdeki 30 saniye içindeyse yenileme işlemi tetikler. Bu, yeniden üretilmesi güç ve hata ayıklaması sinir bozucu olan geçici kimlik doğrulama hatalarının bir sınıfını ortadan kaldırır.

Not:"base64url" kodlaması Node.js 15.7.0 sürümüyle eklendi. Node.js 14 veya öncesine takılı kaldıysanız, aynı şekilde çalışan ancak manuel karakter değişimi gerektiren Buffer.from(segment.replace(/-/g, "+").replace(/_/g, "/"), "base64") ifadesine geri dönün.

Dosya ve API Yanıtından JWT Çözümleme

Sürekli karşılaşılan iki senaryo vardır. Birincisi yerel dosyadan JWT okumak: geliştirme sırasında kaydedilen bir token, bir test fikstürü veya sonradan inceleme için bir olay sırasında boşaltılan bir dosya. İkincisi bir HTTP yanıtından JWT çıkarmak; genellikle OAuth token yanıt gövdesindeki access_token alanı veya bir Authorization başlığı. Her ikisi de hata işleme gerektirir; çünkü hatalı biçimlendirilmiş tokenlar, kesilmiş dosyalar ve ağ hataları günlük gerçekliklerdir. Geçen hafta geçerli olan bir token, kopyala-yapıştır sırasında sona eklenen boşluk veya satır sonu karakterleri içerebilir. Kimlik doğrulama sunucusu hata sayfası döndürdüyse yanıt gövdesi JSON yerine HTML olabilir.

Dosyadan JWT Okuma (Node.js)

Node.js — hata işlemeli dosyadan JWT çözümleme
import { readFileSync } from "node:fs";

function decodeJwtFromFile(filePath) {
  const raw = readFileSync(filePath, "utf-8").trim();
  const segments = raw.split(".");

  if (segments.length !== 3) {
    throw new Error(`Invalid JWT: expected 3 segments, got ${segments.length}`);
  }

  try {
    return {
      header: JSON.parse(Buffer.from(segments[0], "base64url").toString("utf-8")),
      payload: JSON.parse(Buffer.from(segments[1], "base64url").toString("utf-8")),
    };
  } catch (err) {
    throw new Error(`Failed to decode JWT from ${filePath}: ${err.message}`);
  }
}

try {
  const { header, payload } = decodeJwtFromFile("./test-fixtures/access-token.txt");
  console.log("Algorithm:", header.alg);
  console.log("Expires:", new Date(payload.exp * 1000).toISOString());
} catch (err) {
  console.error(err.message);
}

API Yanıtından JWT Çıkarma (fetch)

JavaScript — API yanıtından JWT çözümleme
async function fetchAndDecodeToken(loginUrl, credentials) {
  const response = await fetch(loginUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(credentials),
  });

  if (!response.ok) {
    throw new Error(`Login failed: ${response.status} ${response.statusText}`);
  }

  const { access_token } = await response.json();
  if (!access_token || access_token.split(".").length !== 3) {
    throw new Error("Response does not contain a valid JWT");
  }

  const payload = access_token.split(".")[1];
  const json = Buffer.from(payload, "base64url").toString("utf-8");
  return JSON.parse(json);
}

// Kullanım
try {
  const claims = await fetchAndDecodeToken(
    "https://auth.internal/oauth/token",
    { username: "deploy-bot", password: process.env.DEPLOY_TOKEN }
  );
  console.log("Token subject:", claims.sub);
  console.log("Token scopes:", claims.scope);
  console.log("Expires at:", new Date(claims.exp * 1000).toISOString());
} catch (err) {
  console.error("Token decode error:", err.message);
}

Komut Satırından JWT Çözümleme

Bazen bir script yazmadan terminalde bir token'a hızlıca göz atmak istersiniz. Node.js çoğu geliştirici makinesinde mevcuttur, bu yüzden tek satırlık bir komut işe yarar. jq güzel biçimlendirmeyi üstlenir.

bash — terminalden JWT yükü çözümleme
# Node.js tek satırıyla JWT yükünü çözümle
echo "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOTIxZiIsInJvbGUiOiJhZG1pbiJ9.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" \
  | cut -d. -f2 \
  | node -e "process.stdin.on('data', d => console.log(JSON.parse(Buffer.from(d.toString().trim(), 'base64url').toString('utf-8'))))"

# Güzel çıktı için jq'ya aktar
echo "$JWT_TOKEN" | cut -d. -f2 \
  | node -e "process.stdin.on('data', d => process.stdout.write(Buffer.from(d.toString().trim(), 'base64url').toString('utf-8')))" \
  | jq .

# Hem başlığı hem de yükü çözümle
echo "$JWT_TOKEN" | node -e "
  process.stdin.on('data', d => {
    const parts = d.toString().trim().split('.');
    console.log('Header:', JSON.parse(Buffer.from(parts[0], 'base64url').toString()));
    console.log('Payload:', JSON.parse(Buffer.from(parts[1], 'base64url').toString()));
  });
"

Node.js olmadan saf bash tercih ederseniz, segmenti tr ile base64url karakterlerini düzelttikten sonra base64 -d üzerinden aktarın:

bash — Node.js olmadan saf bash ile JWT çözümleme
# Saf bash: Node.js olmadan JWT yükünü çözümle
echo "$JWT_TOKEN" | cut -d. -f2 | tr '_-' '/+' | base64 -d 2>/dev/null | jq .

# macOS varyantı (base64 -D yerine -d)
echo "$JWT_TOKEN" | cut -d. -f2 | tr '_-' '/+' | base64 -D 2>/dev/null | jq .

Terminal olmadan hızlı görsel inceleme için, token'ınızı ToolDeck JWT Çözümleyici aracına yapıştırın; renk kodlu claim etiketleri ve son kullanma durumu ile üç segmentin yan yana dökümünü alın.

jose — Tek Kütüphanede Doğrulama ve Çözümleme

Üretim kimlik doğrulama ara katmanı için yalnızca çözümleme değil, imza doğrulaması da gerekir. jose kütüphanesi en iyi seçenektir. Hem Node.js'te hem de tarayıcılarda (Web Crypto API aracılığıyla) çalışır; HS256, RS256, ES256, EdDSA ve JWE (şifreli tokenlar) destekler; yerel bağımlılığı sıfırdır. npm install jose ile kurun.

JavaScript — jose: HS256 token doğrulama
import * as jose from "jose";

const secret = new TextEncoder().encode("k8s-webhook-signing-secret-2026");
const token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOTIxZiIsInNjb3BlIjoiYmlsbGluZzpyZWFkIiwiaWF0IjoxNzExNjEwMDAwLCJleHAiOjE3MTE2MTM2MDB9.abc123";

try {
  const { payload, protectedHeader } = await jose.jwtVerify(token, secret);
  console.log("Algorithm:", protectedHeader.alg); // "HS256"
  console.log("Subject:", payload.sub);            // "usr_921f"
  console.log("Scope:", payload.scope);            // "billing:read"
} catch (err) {
  if (err.code === "ERR_JWT_EXPIRED") {
    console.error("Token expired at:", err.payload.exp);
  } else {
    console.error("Verification failed:", err.message);
  }
}
JavaScript — jose: JWKS uç noktasıyla RS256 doğrulama
import * as jose from "jose";

// Kimlik sağlayıcısından genel anahtar setini getir
const jwks = jose.createRemoteJWKSet(
  new URL("https://auth.internal/.well-known/jwks.json")
);

const token = req.headers.authorization?.split(" ")[1];
if (!token) {
  return res.status(401).json({ error: "Missing token" });
}

try {
  const { payload } = await jose.jwtVerify(token, jwks, {
    issuer: "https://auth.internal",
    audience: "billing-api",
  });
  // payload.sub, payload.scope vb. artık doğrulandı
  req.userId = payload.sub;
} catch (err) {
  return res.status(401).json({ error: "Invalid token" });
}

jose ile daha eski jsonwebtoken paketi arasında karar verirken temel fark çalışma zamanı kapsamıdır. jsonwebtoken yalnızca Node.js'te çalışır — yerleşik crypto modülüne dayanır ve tarayıcı için paketlenemez. jose tam isomorfiktir: tüm modern tarayıcılarda, Node.js 16+, Deno, Bun ve Cloudflare Workers'da mevcut olan Web Crypto API'sini kullanır. Kimlik doğrulama mantığınız bir Next.js ara katman dosyasında (Edge Runtime'da çalışan), Cloudflare Worker'da veya hem sunucu hem de istemci kodu tarafından içe aktarılan paylaşılan bir yardımcı programda bulunuyorsa, jose doğru seçimdir; çünkü yerel bağımlılığı sıfırdır ve derleme adımı olmadan kurulur. jsonwebtoken, daha geniş imzalama yardımcıları ekosistemine ihtiyaç duyduğunuz ve kodu bir edge ortamında çalıştırmayı planlamadığınız saf Node.js sunucu uygulamaları için makul bir seçenek olmaya devam eder. 2026'da yeşil alan bir projede, eski API'yi tercih etmek için özel bir nedeniniz yoksa varsayılan olarak jose kullanın.

Yalnızca doğrulama olmadan çözümlemeye ihtiyaç duyarsanız, jose yükü döndüren jose.decodeJwt(token) ve başlık için jose.decodeProtectedHeader(token) işlevlerini sunar. Bunlar, Base64url çözümlemeyi dahili olarak gerçekleştiren kolaylık işlevleridir. Ancak jose'ye başvurmanın tüm nedeni, çözümlemenin nadiren doğrulama olmadan yapılması gerektiğidir. İstemci tarafındaysanız ve yalnızca kullanıcıya token claimlerinden görünen adını veya avatar URL'sini göstermeniz gerekiyorsa, yalnızca çözümleme uygundur. Sunucu tarafında ise her zaman doğrulayın. İmzayı kontrol etmeden erişim kontrolü kararları için JWT claimlerini çözümleyen üretim sistemleri gördüm; bu, JWT formatını anlayan her saldırgana açık bir kapıdır.

JavaScript — yalnızca çözümleme senaryoları için jose.decodeJwt
import * as jose from "jose";

// Yalnızca çözümleme: sır gerekmez, doğrulama yok
const payload = jose.decodeJwt(token);
console.log(payload.sub);   // "usr_921f"
console.log(payload.scope); // "billing:read"

const header = jose.decodeProtectedHeader(token);
console.log(header.alg);    // "HS256"
console.log(header.typ);    // "JWT"

// Doğrulama olmadan son kullanmayı kontrol et (istemci tarafı görüntüleme)
if (payload.exp && payload.exp < Math.floor(Date.now() / 1000)) {
  console.log("Token süresi doldu — giriş sayfasına yönlendir");
}

Söz Dizimi Vurgulamalı Terminal Çıktısı

Bir Node.js CLI aracında veya bir olay sırasında JWT tokenlarının hata ayıklamasını yaparken, renk kodlu çıktı gerçek anlamda fark yaratır. chalk kütüphanesi JSON.stringify ile birlikte işi halleder. npm install chalk ile kurun.

Node.js — renklendirilmiş JWT çözümleme çıktısı
import chalk from "chalk";

function printJwt(token) {
  const segments = token.split(".");
  if (segments.length !== 3) {
    console.error(chalk.red("Invalid JWT: expected 3 segments"));
    return;
  }

  const header = JSON.parse(Buffer.from(segments[0], "base64url").toString("utf-8"));
  const payload = JSON.parse(Buffer.from(segments[1], "base64url").toString("utf-8"));

  console.log(chalk.bold.cyan("\n=== JWT Header ==="));
  console.log(chalk.gray(JSON.stringify(header, null, 2)));

  console.log(chalk.bold.green("\n=== JWT Payload ==="));
  console.log(chalk.gray(JSON.stringify(payload, null, 2)));

  // Son kullanma durumunu vurgula
  if (payload.exp) {
    const expiresAt = new Date(payload.exp * 1000);
    const isExpired = expiresAt < new Date();
    console.log(
      chalk.bold("\nExpires:"),
      isExpired
        ? chalk.red(`EXPIRED at ${expiresAt.toISOString()}`)
        : chalk.green(`Valid until ${expiresAt.toISOString()}`)
    );
  }

  console.log(chalk.dim("\nSignature: " + segments[2].substring(0, 20) + "..."));
}

printJwt(process.argv[2]);
// Çalıştır: node jwt-debug.mjs "eyJhbGci..."
Not:Renk çıktısı yalnızca terminal içindir. JWT claimlerini günlük dosyalarına, API yanıtlarına veya veritabanı alanlarına yazarken chalk kullanmayın. Terminal dışı bağlamlarda ANSI kaçış kodları anlamsız karakterler olarak görünür.

Büyük Günlük Dosyalarından JWT İşleme

Modern API altyapısı, NDJSON biçiminde yapılandırılmış erişim günlükleri yayar — her satırda istek yolu, yanıt durumu, gecikme ve çözümlenmiş ya da ham Authorization başlığını içeren bir JSON nesnesi bulunur. Yoğun bir serviste bu dosyalar hızla büyür: dakikada 10.000 istek işleyen bir ağ geçidi günde 14 milyondan fazla günlük kaydı üretir. Güvenlik ve uyumluluk kullanım durumları, bu dosyaları geriye dönük olarak taramayı düzenli olarak gerektirir — güvenliği ihlal edilmiş bir servis hesabı tarafından yapılan her isteği belirleme (olay sonrası analiz), belirli bir kullanıcının tokenlarının veri erişim penceresinden önce sona erip ermediğini doğrulama (uyumluluk denetimi) veya bir bakım penceresi sırasında hassas bir uç noktaya erişen tüm özneleri çıkarma. Tek bir günlük dosyası birkaç gigabaytı aşabildiğinden readFileSync ile belleğe yüklemek uygulanabilir değildir. Node.js readline akışları dosyayı sabit bellek yüküyle satır satır işler; bu da standart bir geliştirici dizüstü bilgisayarında rastgele büyük günlüklerin taranmasını pratik kılar.

Tek bir JWT nadiren birkaç kilobayttan büyük olduğundan, bireysel JWT'lerle "dosya bellek için çok büyük" sorunuyla karşılaşmazsınız. Karşılaşılan senaryo, büyük bir erişim günlüğünü veya denetim izini JWT tokenları için taramak, her birini çözümlemek ve belirli claimleri çıkarmaktır. Node.js akışları bunu tüm dosyayı yüklemeden gerçekleştirir.

Node.js — NDJSON günlüğünü akıt ve gömülü JWT'leri çözümle
import { createReadStream } from "node:fs";
import { createInterface } from "node:readline";

async function scanLogsForExpiredTokens(logPath) {
  const fileStream = createReadStream(logPath, { encoding: "utf-8" });
  const rl = createInterface({ input: fileStream, crlfDelay: Infinity });

  let lineCount = 0;
  let expiredCount = 0;
  const nowSeconds = Math.floor(Date.now() / 1000);

  for await (const line of rl) {
    lineCount++;
    try {
      const entry = JSON.parse(line);
      if (!entry.authorization_token) continue;

      const segments = entry.authorization_token.split(".");
      if (segments.length !== 3) continue;

      const payload = JSON.parse(
        Buffer.from(segments[1], "base64url").toString("utf-8")
      );

      if (payload.exp && payload.exp < nowSeconds) {
        expiredCount++;
        const expDate = new Date(payload.exp * 1000).toISOString();
        console.log("Line " + lineCount + ": expired token for " + payload.sub + ", exp=" + expDate);
      }
    } catch {
      // Hatalı biçimlendirilmiş satırları atla
    }
  }

  console.log(`\nScanned ${lineCount} lines, found ${expiredCount} expired tokens`);
}

scanLogsForExpiredTokens("./logs/api-access-2026-03.ndjson");
Node.js — günlük akışından benzersiz JWT öznelerini çıkar
import { createReadStream } from "node:fs";
import { createInterface } from "node:readline";

async function extractUniqueSubjects(logPath) {
  const rl = createInterface({
    input: createReadStream(logPath, { encoding: "utf-8" }),
    crlfDelay: Infinity,
  });

  const subjects = new Set();
  const jwtRegex = /eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;

  for await (const line of rl) {
    const matches = line.match(jwtRegex);
    if (!matches) continue;

    for (const token of matches) {
      try {
        const payload = JSON.parse(
          Buffer.from(token.split(".")[1], "base64url").toString("utf-8")
        );
        if (payload.sub) subjects.add(payload.sub);
      } catch {
        // Geçerli bir JWT değil
      }
    }
  }

  console.log(`Found ${subjects.size} unique subjects:`);
  for (const sub of subjects) console.log(`  ${sub}`);
}

extractUniqueSubjects("./logs/gateway-2026-03.log");
Not:Günlük dosyası 50 MB'ı aştığında akışa geçin. readFileSyncile 500 MB'lık bir NDJSON dosyasını yüklemek belleği doldurur ve GC duraklamalarını tetikler. readline yaklaşımı sabit bellek kullanımıyla satır satır işler.

Yaygın Hatalar

ASCII dışı claimler için TextDecoder olmadan atob() kullanmak

Sorun: atob() bir Latin-1 dizesi döndürür. Çok baytlı UTF-8 karakterler (emoji, CJK, aksanlı karakterler) karakterlere bölünür ve bozuk çıkar.

Çözüm: atob() çıktısını Uint8Array'e dönüştürün, ardından new TextDecoder('utf-8') üzerinden geçirin.

Before · JavaScript
After · JavaScript
// ASCII dışı yük claimlerinde bozulur
const payload = JSON.parse(atob(token.split(".")[1]));
// display_name "ç°ä¸­å¤ªé\x83\x8E" olarak görünür, "田中太郎" yerine
const binary = atob(token.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"));
const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
const payload = JSON.parse(new TextDecoder("utf-8").decode(bytes));
// display_name doğru şekilde "田中太郎" gösterir
base64url'den base64'e karakter değişimini unutmak

Sorun: atob() "InvalidCharacterError" fırlatır; çünkü base64url + ve / yerine - ve _ kullanır.

Çözüm: atob() çağrısından önce - yerine + ve _ yerine / koyun. Node.js Buffer.from() ile 'base64url' bunu otomatik olarak yapar.

Before · JavaScript
After · JavaScript
// Fırlatır: InvalidCharacterError: String contains an invalid character
const payload = atob(token.split(".")[1]);
const segment = token.split(".")[1];
const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
const payload = atob(base64); // artık çalışır
İmza doğrulaması yapmadan çözümlenmiş JWT claimlerine güvenmek

Sorun: Herkes herhangi bir yük içeren bir JWT oluşturabilir. Çözümleme yalnızca veriyi okur — tokenın kimlik doğrulama sunucunuz tarafından düzenlendiğini kanıtlamaz.

Çözüm: Sunucu tarafında her zaman jose.jwtVerify() veya jsonwebtoken.verify() kullanarak imzayı doğrulayın. Yalnızca çözümleme, kullanıcı claimlerinin istemci tarafında görüntülenmesi için kabul edilebilir.

Before · JavaScript
After · JavaScript
// TEHLİKELİ: çözümlendi ancak doğrulanmadı
const claims = JSON.parse(atob(token.split(".")[1]));
if (claims.role === "admin") {
  grantAdminAccess(); // saldırgan bunu taklit edebilir
}
import * as jose from "jose";
const { payload } = await jose.jwtVerify(token, secretKey);
if (payload.role === "admin") {
  grantAdminAccess(); // güvenli — imza doğrulandı
}
exp'yi 1000'e bölmeden Date.now() ile karşılaştırmak

Sorun: JWT exp, epoch'tan bu yana geçen saniyedir; ancak Date.now() milisaniye döndürür. Karşılaştırma, milisaniye zaman damgası 1000 kat daha büyük olduğundan her zaman tokenın geçerli olduğunu söyler.

Çözüm: exp ile karşılaştırmadan önce Date.now()'u 1000'e bölün ve sonucu aşağı yuvarlayın.

Before · JavaScript
After · JavaScript
// Hata: Date.now() milisaniye, exp saniyedir
if (payload.exp > Date.now()) {
  console.log("Token is valid"); // her zaman doğru — yanlış!
}
const nowSeconds = Math.floor(Date.now() / 1000);
if (payload.exp > nowSeconds) {
  console.log("Token is valid"); // doğru karşılaştırma
}

JWT Çözümleme Yöntemleri — Hızlı Karşılaştırma

Yöntem
Ortam
UTF-8 Güvenli
İmza Doğrulama
Özel Türler
Kurulum Gerekir
atob() + TextDecoder
Tarayıcı
Yok (salt okunur)
Hayır
Buffer.from()
Node.js
Yok (salt okunur)
Hayır
decodeURIComponent()
Tarayıcı (eski)
Yok (salt okunur)
Hayır
jose
Her ikisi
✓ (JWS/JWE)
npm install
jsonwebtoken
Node.js
npm install
jwt-decode
Her ikisi
Yok
npm install

Kullanıcıya yalnızca claimleri görüntülemek istediğinizde tarayıcı tarafı çözümleme için atob() + TextDecoder kullanın. Node.js scriptleri ve CLI araçlarında Buffer.from() tercih edin. İmzayı doğrulamanız gerektiğinde — ki bu her sunucu tarafı kimlik doğrulama ara katmanı demektir — jose'ye başvurun. jwt-decode paketi, tarayıcıda yalnızca çözümleme için tek fonksiyonluk API isteyen kullanıcılar için hafif bir alternatiftir. Kod yazmadan hızlı görsel inceleme için token'ınızı JWT Çözümleyici aracına yapıştırın.

Sık Sorulan Sorular

JavaScript'te bir JWT token'ı kütüphane kullanmadan nasıl çözerim?

Token'ı "." karakterine göre bölün, ikinci segmenti (yük) alın, base64url kodlamasını normalleştirmek için - yerine + ve _ yerine / koyun, = karakterleri ile doldurun, ardından atob() fonksiyonunu ve TextDecoder'ı çağırarak UTF-8 JSON dizesini elde edin. Sonucu JSON.parse() ile ayrıştırın; claims nesnesi hazır olur. Herhangi bir npm paketine gerek yoktur. Bu yaklaşım tüm modern tarayıcılarda ve Node.js 18+ sürümlerinde çalışır. Başlığı da okumak istiyorsanız aynı adımları ilk segmente uygulayın. Bu işlemin herhangi bir imza doğrulaması yapmadığını unutmayın — imzayı sunucu tarafında doğrulamadığınız sürece sonucu yalnızca görüntüleme amaçlı kullanın.

JavaScript
const token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOTIxZiIsInJvbGUiOiJhZG1pbiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
const payload = token.split(".")[1];
const base64 = payload.replace(/-/g, "+").replace(/_/g, "/");
const json = atob(base64);
const claims = JSON.parse(json);
console.log(claims);
// { sub: "usr_921f", role: "admin" }

JWT çözümlemede atob() ile Buffer.from() arasındaki fark nedir?

atob(), standart Base64'ü Latin-1 ikili dizesine dönüştüren bir tarayıcı API'sidir. base64url kodlamasını doğrudan anlayamaz; bu nedenle önce - ve _ karakterlerini değiştirmeniz gerekir. Buffer.from(segment, "base64url") ise base64url alfabesini yerel olarak destekleyen ve .toString("utf-8") ile çağırabileceğiniz bir Buffer döndüren bir Node.js API'sidir. Tarayıcıda atob(), Node.js'te Buffer.from() kullanın. Tarihsel olarak yaygın olan üçüncü bir seçenek — daha yavaş olmakla birlikte — decodeURIComponent yüzde kodlama hilesidir; ancak bazı eski kod parçacıklarında kullanımdan kaldırılmış escape() fonksiyonuna dayanır ve yeni kodda kullanılmamalıdır. Her iki ortamda da çalışan isomorfik kod için typeof Buffer !== "undefined" kontrolü yapıp buna göre dallanabilirsiniz.

JavaScript
// Tarayıcı
const json = atob(payload.replace(/-/g, "+").replace(/_/g, "/"));

// Node.js
const json2 = Buffer.from(payload, "base64url").toString("utf-8");

atob() ASCII dışı JWT claimlerinde neden bozuk sonuç verir?

atob() her karakterin tek bir bayta karşılık geldiği Latin-1 bir dize döndürür. Çok baytlı UTF-8 dizileri (emoji, CJK karakterler, Latin-1 aralığının ötesindeki aksanlı harfler) birden fazla karaktere bölünerek anlamsız çıktı üretir. Çözüm, ikili dizeyi önce Uint8Array'e dönüştürmek, ardından bu diziyi new TextDecoder("utf-8").decode() fonksiyonuna geçirmektir. TextDecoder API'si çok baytlı dizileri doğru biçimde yeniden birleştirir. Bu sorun geliştirme sürecinde kolay fark edilmez çünkü JWT yükleri genellikle yalnızca ASCII kullanıcı kimlikleri, zaman damgaları ve rol adları içerir; hata, bir claim ASCII dışı bir görünen ad ya da yerelleştirilmiş bir dize içerdiğinde ortaya çıkar. Mevcut yükleriniz ASCII olsa bile yeni kodlarda her zaman TextDecoder yolunu kullanın; uygulama geliştikçe claimler değişebilir.

JavaScript
// Hatalı: atob Latin-1 döndürür, çok baytlı karakterler bozulur
const broken = atob(base64); // "ð\x9F\x8E\x89" emoji yerine

// Düzeltilmiş: bayt dizisine çevir, ardından TextDecoder kullan
const bytes = Uint8Array.from(atob(base64), c => c.charCodeAt(0));
const fixed = new TextDecoder("utf-8").decode(bytes);

JavaScript'te bir JWT imzasını doğrulayabilir miyim?

Çözümleme ve doğrulama farklı işlemlerdir. Çözümleme yalnızca yükü okur; yük şifreli değildir. Doğrulama ise imzayı bir sır (HMAC) veya genel anahtar (RSA/ECDSA) ile kontrol eder. jose kütüphanesi, tarayıcıda Web Crypto API aracılığıyla ve Node.js'te her ikisini de destekler. jsonwebtoken paketi yalnızca Node.js'te çalışır. Sunucu tarafında imzayı doğrulamadan çözümlenmiş claimlere güvenmeyin. İstemci tarafında bir JWT'yi kullanıcının görünen adını veya son kullanma zamanını okumak için çözümlemek kabul edilebilir; ancak bir kullanıcının belirli bir role ya da izne sahip olup olmadığını kontrol etmek gibi her erişim kontrolü kararı, doğrulamanın ardından sunucu tarafı kodunda gerçekleşmelidir. JWT formatını anlayan bir saldırgan, keyfi claimlerle token oluşturabilir ve istemci tarafındaki kontrolünüz geçilecektir.

JavaScript
import * as jose from "jose";

const secret = new TextEncoder().encode("your-256-bit-secret");
const { payload } = await jose.jwtVerify(token, secret);
console.log(payload.sub); // doğrulanmış claimler

JavaScript'te bir JWT'nin süresi dolmuş mu diye nasıl kontrol ederim?

Yükü çözümleyip saniye cinsinden Unix zaman damgası olan exp claimini okuyun. Bunu Math.floor(Date.now() / 1000) ile elde ettiğiniz geçerli zamana göre karşılaştırın. Geçerli zaman exp'den büyükse token süresi dolmuş demektir. Şunu unutmayın: exp değeri milisaniye değil, epoch'tan bu yana geçen saniyedir; bu nedenle Date.now()'u 1000'e bölmek zorunludur. Pratikte küçük bir saat kayması tamponu ekleyin — tokenın kesin olarak geçmişte olmak yerine önümüzdeki 30 saniye içinde dolup dolmadığını kontrol etmek, token'ı çözümlediğinizde hâlâ teknik olarak geçerli olduğu ancak bir sonraki downstream API çağrısını işlemeye gelindiğinde dolduğu sınır durumlarını önler. exp'nin hiç olmadığı durumu da ele alın; bu, token'ın hiç dolmadığı anlamına gelir.

JavaScript
function isTokenExpired(token) {
  const payload = JSON.parse(
    atob(token.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"))
  );
  const nowSeconds = Math.floor(Date.now() / 1000);
  return payload.exp < nowSeconds;
}

console.log(isTokenExpired(myToken)); // true or false

Hem Node.js hem de tarayıcıda çalışan isomorfik JWT çözümleme kodu nasıl yazarım?

globalThis.Buffer'ın varlığını kontrol edin. Varsa Node.js ortamındasınız demektir ve Buffer.from(segment, "base64url").toString("utf-8") kullanabilirsiniz. Yoksa tarayıcıdasınız ve atob() ile TextDecoder yaklaşımını kullanmalısınız. Bu kontrolü tek bir decodeBase64Url fonksiyonuna koyun ve her yerde bu fonksiyonu kullanın. Bu yaklaşım en çok, hem bir Next.js sunucu bileşeni hem de bir tarayıcı React bileşeni tarafından içe aktarılan monorepo paketlerindeki, tasarım sistemi bileşenlerindeki ve yardımcı paketlerdeki paylaşılan kod için önemlidir. Ortam tespitini tek bir yerde tutmak, çalışma zamanı değiştiğinde — örneğin Deno tam Buffer desteği eklediğinde veya yeni bir edge çalışma zamanı farklı bir kod yolu gerektirdiğinde — güncelleme yapmanız gereken tek bir yerin olduğu anlamına gelir.

JavaScript
function decodeBase64Url(segment) {
  if (typeof Buffer !== "undefined") {
    return Buffer.from(segment, "base64url").toString("utf-8");
  }
  const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
  const bytes = Uint8Array.from(atob(base64), c => c.charCodeAt(0));
  return new TextDecoder("utf-8").decode(bytes);
}

İlgili Araçlar

Şu dillerde de mevcut:Python
MW
Marcus WebbJavaScript Performance Engineer

Marcus specialises in JavaScript performance, build tooling, and the inner workings of the V8 engine. He has spent years profiling and optimising React applications, working on bundler configurations, and squeezing every millisecond out of critical rendering paths. He writes about Core Web Vitals, JavaScript memory management, and the tools developers reach for when performance really matters.

SL
Sophie LaurentTeknik İnceleyici

Sophie is a full-stack developer focused on TypeScript across the entire stack — from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.