Keycloak İle React Uygulamalarında Kimlik Doğrulama


Keycloak Nedir?

Keycloak, modern uygulamalar ve hizmetler için tek oturum açma (SSO) özelliği sunan, kimlik ve erişim yönetimi (IAM) sağlayan açık kaynaklı bir yazılım ürünüdür. Java tabanlı olarak geliştirilen Keycloak, uygulamalarınızın güvenliğini kolaylaştıran ve merkezi kimlik doğrulama sağlayan bir çözümdür.

Keycloak’ın Temel İşlevleri

  • Tek Oturum Açma (SSO): Kullanıcıların bir kez kimlik doğrulaması yaparak birden fazla uygulamaya erişebilmesini sağlar.
  • Kimlik Doğrulama ve Yetkilendirme: Kullanıcıların kimliklerini doğrular ve uygulamalara erişim haklarını yönetir.
  • Merkezi Kullanıcı Yönetimi: Kullanıcı hesaplarını, verilerini ve oturumları tek bir merkezden yönetme imkanı sunar.
  • Standart Protokol Desteği: OpenID Connect, OAuth 2.0 ve SAML 2.0 gibi standart kimlik protokollerini destekler.

Keycloak’ı Kimler Geliştirmiştir?

Keycloak, başlangıçta WildFly (eski adıyla JBoss) topluluğu tarafından geliştirilmiş ve Red Hat tarafından desteklenen bir projedir. İlk üretim sürümü 10 Eylül 2014’te yayınlanmıştır.

2016 yılında Red Hat, RH SSO (Red Hat Single Sign-On) ürününü PicketLink çerçevesi yerine Keycloak temel alacak şekilde yeniden tasarlamıştır. Nisan 2023’te ise Keycloak projesi CNCF (Cloud Native Computing Foundation)‘a bağışlanmış ve vakfın kuluçka projelerinden biri haline gelmiştir.

Keycloak’ın geliştirilmesinde Red Hat’in önemli katkıları olmuştur. Red Hat, GNOME ve diğer birçok açık kaynaklı projeye yaptığı katkılarla tanınan bir Amerikan yazılım şirketidir.

Keycloak Neden Geliştirilmiştir?

Keycloak’ın geliştirilme amacı, uygulama güvenliğini basitleştirmek ve geliştiricilerin kimlik yönetimi konusunda kendi çözümlerini oluşturmasına gerek kalmadan güvenli uygulamalar geliştirebilmesini sağlamaktır.

Başlıca Geliştirilme Nedenleri

  • Karmaşık Kimlik Yönetimi Sorunlarını Çözmek: Her uygulamanın kendi kimlik doğrulama mekanizmasını oluşturması yerine, merkezi bir çözüm sunarak karmaşıklığı azaltmak.
  • Maliyet ve Zaman Tasarrufu Sağlamak: Özel yazılım çözümleri oluşturmak maliyetli ve zaman alıcı olabilir. Keycloak açık kaynak olarak bu maliyetleri ortadan kaldırır.
  • Güvenliği Artırmak: Test edilmiş ve birçok kuruluş tarafından kullanılan bir çözüm sunarak güvenlik ihtiyaçlarını karşılamak.
  • Entegrasyon Kolaylığı: Mevcut sistemlerle (LDAP, Active Directory gibi) kolay entegrasyon sağlayarak esnek bir çözüm sunmak.
  • Modern Uygulama İhtiyaçlarını Karşılamak: Mikroservis mimarileri ve bulut tabanlı uygulamalar için uygun kimlik yönetimi sağlamak.

Keycloak, özellikle çok sayıda kullanıcı ve sisteme sahip organizasyonlar için kritik bir güvenlik çözümü olarak öne çıkmaktadır. SSO kullanımı sayesinde kullanıcı kimlik bilgileri merkezi ve güvenli bir noktada tutularak, veri paylaşımı sınırlandırılır ve siber saldırılara karşı daha dayanıklı bir yapı oluşturulur.

Keycloak Hakkında Bilgi Sahibi Olduğumuza Göre Artık React İle Nasıl Entegre Edeceğimize Geçebiliriz

1-) Öncelikle Keycloak’ı kurmamız gerekiyor. Keycloak’ı Docker ile kolayca kurabiliriz:

# Start PostgreSQL
docker run -d \
  --name keycloak-db \
  -e POSTGRES_DB=keycloak \
  -e POSTGRES_USER=keycloak \
  -e POSTGRES_PASSWORD=password \
  -v keycloak-db-data:/var/lib/postgresql/data \
  postgres:16

# Start Keycloak
docker run -d \
  --name keycloak \
  -p 8080:8080 \
  --link keycloak-db:postgres \
  -e KC_DB=postgres \
  -e KC_DB_URL=jdbc:postgresql://postgres:5432/keycloak \
  -e KC_DB_USERNAME=keycloak \
  -e KC_DB_PASSWORD=password \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:latest start-dev
  • Keycloak’ı PostgreSQL ile birlikte başlatıyoruz. Keycloak’ın yönetici kullanıcı adı ve şifresini admin olarak ayarlıyoruz.

Keycloak’ı PostgreSQL ile başlatıyoruz çünkü Keycloak tarafında yaptığımız tüm işlemler veritabanında saklanacak. Bu nedenle veritabanı bağlantı bilgilerini doğru bir şekilde ayarlamamız gerekiyor.

  • Keycloak :8080 portundan erişilebilir olacak. Yönetici paneline erişmek için http://localhost:8080 adresini kullanabilirsiniz.

  • Giriş yaptıktan sonra kendi admin kullanıcımızı oluşturacağız. Bu kullanıcı, Keycloak yönetim paneline erişim sağlayacak. Keycloak’ı başlatırken oluşturulan admin kullanıcısı geçici bir kullanıcıdır.

  • Kullanıcı oluşturmak için Keycloak yönetim paneline giriş yaptıktan sonra sol menüden “Users” sekmesine gidin ve “Add user” butonuna tıklayın.

  • İlgili alanları doldurduktan sonra “Save” butonuna tıklayın. “Email verified” alanını etkinleştirin. Kullanıcı oluşturulduktan sonra, kullanıcıyı düzenleyerek şifresini belirleyebilirsiniz.

  • “Users” sekmesinde oluşturduğunuz kullanıcıyı görebilirsiniz. Kullanıcının üzerine tıklayarak açılan ekranda “Credentials” sekmesine gidin ve şifresini belirleyin. Şifreyi belirledikten sonra “Set Password” butonuna tıklayın.

  • Artık admin kullanıcınız hazır. Keycloak yönetim paneline giriş yaparak kullanıcıları ve rolleri yönetebilirsiniz.

  • Gelin şimdi Keycloak’ta Realm oluşturalım ve kullanıcı ekleyelim

1-) Realm oluştur

Keycloak

2-) Kullanıcı oluştur

Keycloak

  • Admin kullanıcısı oluştururken email verified seçeneğini işaretlemeyi unutmayın. Bu, kullanıcıların email adreslerini doğrulamalarını sağlar.

3-) Şifre belirle

Keycloak

4-) Client oluştur

Keycloak

5-) Giriş ayarları

Keycloak

  • Burada ilgili alanları frontend uygulamanızın URL’sine göre ayarlayın. Örneğin, http://localhost:3000/* gibi.
Artık React tarafında Keycloak ile kimlik doğrulama yapmaya hazırız. Şimdi React uygulamamızı oluşturalım

1-) Öncelikle yeni bir React uygulaması oluşturalım:

npm create vite@latest keycloak-react-app --template react-ts

2-) Gerekli bağımlılıkları yükleyelim:

npm i @react-keycloak/web keycloak-js keycloak-js axios react-router-dom

3-) “.env” dosyasını oluşturalım ve Keycloak yapılandırmalarını ekleyelim:

VITE_KEYCLOAK_URL=http://localhost:8080
VITE_KEYCLOAK_REALM=myrealm
VITE_KEYCLOAK_CLIENT_ID=myclient

4-) Keycloak Yapılandırmasını yapalım:

  • “src” klasörünün içine “keycloak” adında bir klasör oluşturalım ve içine “keycloak.ts” adında bir dosya oluşturalım. Bu dosya Keycloak yapılandırmalarını içerecek.
import Keycloak from 'keycloak-js';

const keycloakConfig = {
  url: import.meta.env.VITE_KEYCLOAK_URL,
  realm: import.meta.env.VITE_KEYCLOAK_REALM,
  clientId: import.meta.env.VITE_KEYCLOAK_CLIENT_ID,
};

const keycloak = new Keycloak(keycloakConfig);

export default keycloak;
  • “keycloak” klasörünün içine “KeycloakProvider” adında bir dosya oluşturalım. Bu dosya Keycloak sağlayıcısını içerecek ve uygulamamızın ana bileşeni olacak.
import { ReactKeycloakProvider } from '@react-keycloak/web';
import keycloak from './keycloak';
import type { ReactNode } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import Loading from '../common/components/Loading';

type KeycloakProviderProps = {
  children: ReactNode;
};

const KeycloakProvider = ({ children }: KeycloakProviderProps) => {
  const navigate = useNavigate();
  const location = useLocation();
  return (
    <ReactKeycloakProvider
      LoadingComponent={<Loading />}
      authClient={keycloak}
      initOptions={{
        onLoad: 'check-sso',
        silentCheckSsoRedirectUri: `${window.location.origin}/silent-check-sso.html`,
        pkceMethod: 'S256'
      }}
      autoRefreshToken={true}
      onTokens={({ token, refreshToken, idToken }) => {
        if (token) {
          localStorage.setItem('access_token', token);
          localStorage.setItem('refresh_token', refreshToken || '');
          localStorage.setItem('id_token', idToken || '');
        }
      }}
      onEvent={(event) => {
        if (event === 'onAuthSuccess') {
          navigate(location.pathname, { replace: true });
        }
        if (event === 'onAuthRefreshError') {
          navigate('/login');
        }
      }}
    >
      {children}
    </ReactKeycloakProvider>
  );
};

export default KeycloakProvider;
  • Eğer event ‘onAuthSuccess’ ise (yani kullanıcı başarıyla giriş yaptıysa), navigate fonksiyonu ile mevcut sayfaya tekrar yönlendirme yapılır. Bu, URL’nin güncellenmesini veya uygulamanın doğru şekilde yeniden yüklenmesini sağlar:

    if (event === 'onAuthSuccess') {
      navigate(location.pathname, { replace: true });
    }
  • Eğer event ‘onAuthRefreshError’ ise (yani token yenileme işlemi başarısız olursa), kullanıcı ‘/login’ sayfasına yönlendirilir. Bu, oturumun süresi dolduğunda veya yenileme hatası olduğunda kullanıcıdan tekrar giriş yapmasını ister:

    if (event === 'onAuthRefreshError') {
      navigate('/login');
    }

5-) PrivateRoute bileşenini oluşturalım:

  • Bu bileşen, kullanıcıların belirli sayfalara erişimini kontrol edecek. Eğer kullanıcı oturum açmamışsa veya gerekli role sahip değilse, kullanıcıyı giriş sayfasına yönlendirecek.
import type { ReactNode } from 'react';
import { useKeycloak } from '@react-keycloak/web';
import { Navigate, useLocation } from 'react-router-dom';
import Layout from './common/components/Layout';

type PrivateRouteProps = {
  children: ReactNode;
  roles?: string[];
};

const PrivateRoute = ({ children, roles }: PrivateRouteProps) => {
  const { keycloak } = useKeycloak();
  const location = useLocation();

  if (!keycloak.authenticated) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }

  if (roles && !roles.some(role => keycloak.hasRealmRole(role))) {
    return <Navigate to="/unauthorized" replace />;
  }

  return <>
    <Layout>
      {children}
    </Layout>
  </>;
};

export default PrivateRoute;

6-) App.tsx dosyasını güncelleyelim:

import KeycloakProvider from './keycloak/KeycloakProvider';
import { Routes, Route } from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import LoginPage from './features/auth/Login';
import HomePage from './features/home/Home';
import UnauthorizedPage from './common/components/Unauthorized';
import DashboardPage from './features/dashboard/Dashboard';
import AdminPage from './features/admin/Admin';

function App() {
  return (
    <KeycloakProvider>
      <Routes>
        {/* Public routes */}
        <Route path="/" element={<HomePage />} />
        <Route path="/login" element={<LoginPage />} />
        <Route path="/unauthorized" element={<UnauthorizedPage />} />

        {/* Protected routes */}
        <Route
          path="/dashboard"
          element={
            <PrivateRoute>
              <DashboardPage />
            </PrivateRoute>
          }
        />

        {/* Role protected routes */}
        <Route
          path="/admin"
          element={
            <PrivateRoute roles={['admin']}>
              <AdminPage />
            </PrivateRoute>
          }
        />
      </Routes>
    </KeycloakProvider>
  );
}

export default App;

Sonuç olarak, Keycloak ile React uygulamalarında kimlik doğrulama ve yetkilendirme işlemlerini başarıyla gerçekleştirmiş olduk. Bu yapı, kullanıcıların güvenli bir şekilde oturum açmasını ve belirli sayfalara erişimini kontrol etmenizi sağlar.