---
title: Uygulamadan Yetkilendirme
description: Uygulamanızdan mağaza yetkilendirme sürecini başlatma
---

Bu senaryoda ele alacağımız ilk durum uygulamadan yetkilendirme başlatmaktır. Bu senaryoda, uygulama mağaza sahibinden mağaza adını almalı ve bunu `/api/oauth/authorize` API'sine göndermelidir.

## Ana Sayfa Güncelleme

İlk olarak ana sayfanızı (`app/page.tsx`) güncelleyerek yetkilendirme sayfasına yönlendirme yapalım.

```typescript title="File: app/page.tsx"
'use client';

import { useEffect } from 'react';
import { useRouter } from 'next/navigation';

export default function Home() {
  const router = useRouter();

  useEffect(() => {
    // Next.js 15 App Router ile güvenli yönlendirme
    router.push('/authorize-store');
  }, [router]);

  return (
    <main className="min-h-screen flex items-center justify-center">
      <div className="text-center">
        <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto mb-4"></div>
        <p className="text-gray-600">Yönlendiriliyor...</p>
      </div>
    </main>
  );
}
```

Bu kodu ekledikten sonra [http://localhost:3000](http://localhost:3000) adresini açtığınızda otomatik olarak authorize store sayfasına yönlendirilmelisiniz.

![ikas Auth Panel Localhost](/media/app-development-media/ikas-cli-media/adim-3-OAuth-Yetkilendirme-Sayfası.png)

## Mağaza Yetkilendirme Sayfası

Mağaza adı girişi için bir sayfa oluşturalım:

```typescript title="File: app/authorize-store/page.tsx"
'use client';

import { useState } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';

export default function AuthorizeStore() {
  const [storeName, setStoreName] = useState('');
  const [loading, setLoading] = useState(false);
  const router = useRouter();
  const searchParams = useSearchParams();
  const status = searchParams.get('status');

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!storeName.trim()) return;

    setLoading(true);
    // OAuth authorize API'sine yönlendir
    window.location.href = `/api/oauth/authorize?storeName=${encodeURIComponent(storeName.trim())}`;
  };

  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-50">
      <div className="max-w-md w-full space-y-8 p-8">
        <div className="text-center">
          <h1 className="text-3xl font-bold text-gray-900 mb-2">
            ikas Mağazanızı Bağlayın
          </h1>
          <p className="text-gray-600">
            Uygulamayı mağazanıza bağlamak için mağaza adınızı girin
          </p>
        </div>

        {status === 'fail' && (
          <div className="bg-red-50 border border-red-200 rounded-lg p-4">
            <p className="text-red-700 text-sm">
              Yetkilendirme başarısız oldu. Lütfen tekrar deneyin.
            </p>
          </div>
        )}

        <form onSubmit={handleSubmit} className="space-y-4">
          <div>
            <label htmlFor="storeName" className="block text-sm font-medium text-gray-700 mb-1">
              Mağaza Adı
            </label>
            <div className="relative">
              <input
                type="text"
                id="storeName"
                value={storeName}
                onChange={(e) => setStoreName(e.target.value)}
                placeholder="ornek-magaza"
                className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                disabled={loading}
                required
              />
              <div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
                <span className="text-gray-400 text-sm">.myikas.com</span>
              </div>
            </div>
            <p className="text-xs text-gray-500 mt-1">
              Mağazanızın subdomain adını girin (örn: magaza-adi.myikas.com için "magaza-adi")
            </p>
          </div>

          <button
            type="submit"
            disabled={!storeName.trim() || loading}
            className="w-full bg-blue-600 text-white py-2 px-4 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center"
          >
            {loading ? (
              <>
                <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
                Bağlanıyor...
              </>
            ) : (
              'Mağazayı Bağla'
            )}
          </button>
        </form>
      </div>
    </div>
  );
}
```

## Yetkilendirme Süreci

### 1. Yetkilendirme Başlatma

Kullanıcı mağaza adını girip enter tuşuna bastığında veya "Mağazayı Bağla" butonuna tıkladığında:

1. Form `/api/oauth/authorize` API'sine `storeName` query parametresi ile yönlendirir
2. Authorize API, `storeName`, `state`, `client_id`, `scope`, ve `redirect_uri` ile yeni bir URL oluşturur
3. Kullanıcı ikas dashboard'a yönlendirilir

<Callout type="info" title="Yetkilendirme Akışı">
Bu süreçte oluşturulan `state` değişkeni güvenlik için kullanılır ve callback'te doğrulanır. OAuth2 standardına göre CSRF saldırılarını önlemek için gereklidir.
</Callout>

### 2. Uygulama Erişimi Verme

Query parametreleri doğru ise kullanıcı "Uygulama Erişimi Ver" sayfasını görmelidir. Bu sayfada:

- Uygulamanızın talep ettiği yetkiler listelenir
- Kullanıcı "Uygulamayı Yükle" butonuna tıklayarak onay verir

### 3. Yetkilendirme Tamamlama

Kullanıcı uygulamanızı onayladıktan sonra:

1. ikas benzersiz bir `code` oluşturur
2. Kullanıcı `redirect_uri`'nize (`/api/oauth/callback`) yönlendirilir
3. Callback API `code`, `storeName`, `state` parametreleri ile çağrılır
4. Callback API state'i doğrular ve `code` ile `access_token` talep eder
5. Token Redis Storage'a kaydedilir
6. Süreç tamamlandığında kullanıcı ikas Dashboard'a yönlendirilir

### 4. App Loader Kapatma

ikas Dashboard'da uygulamanızın yüklendiğini göstermek için bir loader gösterilir. Bu loader'ı kapatmak için ikas AppBridge'i kullanmalıyız.

```typescript title="File: app/dashboard/page.tsx"
'use client';

import { useEffect } from 'react';

export default function Dashboard() {
  useEffect(() => {
    // ikas AppBridge'den loader'ı kapat
    if (typeof window !== 'undefined' && window.parent) {
      window.parent.postMessage({ type: 'CLOSE_LOADER' }, '*');
    }
  }, []);

  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold text-gray-900 mb-4">
        Dashboard
      </h1>
      <p className="text-gray-600">
        Mağazanız başarıyla bağlandı! Uygulamanızı kullanmaya başlayabilirsiniz.
      </p>
    </div>
  );
}
```

Yetkilendirme başarıyla tamamlandığında ikas admin panelinde aşağıdaki gibi bir başarı mesajı göreceksiniz:

![Başarılı Yetkilendirme](/media/app-development-media/ikas-cli-media/congrats-auth-to-store.png)

<Callout type="success" title="Başarılı Yetkilendirme">
Authorize store sayfasını ikas Dashboard içinde görüyorsanız, sayfanızı başarıyla bir mağazaya yetkilendirdiğiniz anlamına gelir.
</Callout>

## Hata Durumları

Yetkilendirme sürecinde karşılaşabileceğiniz yaygın hatalar:

### Geçersiz Mağaza Adı
```typescript
// Callback API'de hata durumu - Next.js 15 best practices
const failUrl = new URL('/authorize-store', request.url);
failUrl.searchParams.set('storeName', storeName);
failUrl.searchParams.set('status', 'fail');
return NextResponse.redirect(failUrl);
```

### State Doğrulama Hatası
- `state` parametresi Redis'te bulunamazsa
- `state` değerleri eşleşmezse
- State'in süresi dolmuşsa (60 saniye TTL)

### Client Credentials Hatası
- Yanlış `client_id` veya `client_secret`
- Geçersiz `redirect_uri`
- Geçersiz `scope` tanımlaması

<Callout type="warning" title="Debug İpuçları">
Yetkilendirme sürecinde sorun yaşıyorsanız:
1. Environment variable'larınızı kontrol edin
2. Callback URL'inizin doğru tanımlandığından emin olun
3. State değişkeninin doğru kaydedilip kaydedilmediğini kontrol edin
4. Browser developer tools'da network sekmesini inceleyin
</Callout>

Bu adımları tamamladığınızda uygulamanızdan başlatılan OAuth yetkilendirme akışı çalışır hale gelecektir.
