D
Engineering

JWT Lifecycle

Penerbitan, refresh, dan penggunaan JWT lintas service. Token dazoapp dipakai backend Go, engine WhatsApp, dan engine bot — bukan auth internal.

JWT yang diterbitkan dazoapp adalah kontrak lintas-service. Frontend memakainya untuk mengakses backend Go dan seluruh microservice lain. Ini bukan auth internal.

Ringkasan alur

text
ISSUE:
  Login (password / Google SSO / QuickLogin admin)
    → auth('api')->attempt() / login() / JWTAuth::fromUser()
    → Tymon generate JWT dengan claim standar (sub, iat, exp, nbf, iss, jti, prv)
    → claim custom = KOSONG (tidak ada store_id/role di token)
    → response: { access_token, expires_in: 3600, user }

REFRESH:
  POST /api/refresh (Authorization: Bearer <old token>)
    → auth('api')->refresh(true, true)
    → old token di-blacklist (tidak bisa dipakai lagi)
    → new token di-issue (TTL sama: 60 menit)
    → response: { access_token, expires_in }

CROSS-SERVICE:
  Frontend → backend Go (url_api) pakai axios polos
    → Authorization: Bearer <token>  (TAPI axios polos tidak auto-attach)
    → backend Go verifikasi pakai secret bersama JWT_SECRET

1. Token issuance

Titik penerbitan

TitikLokasiMetode
Login utamaapp/Services/AuthService.php:143auth('api')->attempt($credentials)
Refresh tokenapp/Services/AuthService.php:181auth('api')->refresh(true, true)
Quick login adminapp/Http/Controllers/QuickLoginController.php:53JWTAuth::fromUser($user)
Save store (onboarding)app/Http/Controllers/WelcomeController.php:607auth('api')->login($user)
Google SSOapp/Http/Controllers/Auth/GoogleAuthController.php:165auth('api')->login($user)

Claim/payload

Claim standar (config/jwt.php:149-156):

  • sub — user ID (MongoDB UUID string) dari User::getJWTIdentifier() (User.php:60-63)
  • iat, exp, nbf, iss, jti — standar Tymon
  • prv — otomatis aktif (config/jwt.php:193 lock_subject = true) untuk mencegah cross-model impersonation

TTL

TokenTTLSumber
Access token60 menitconfig/jwt.php:104env('JWT_TTL', 60)
Refresh window10.000 menit (~6,9 hari)config/jwt.php:124env('JWT_REFRESH_TTL', 10000)

expires_in di response = auth('api')->factory()->getTTL() * 60 (detik) — AuthService.php:160.

Secret

config/jwt.php:28'secret' => env('JWT_SECRET'). Algoritma HS256 (config/jwt.php:136).

2. Refresh flow

Endpoint

POST /api/refresh (routes/api.php:85) → AuthController@refresh (AuthController.php:35-38) → AuthService::refresh() (AuthService.php:178-196).

Verifikasi & rotation

  • Tymon verifikasi signature + exp dari token lama
  • Token lama harus masih dalam window refresh_ttl (10.000 menit) sejak iat asli
  • auth('api')->refresh(true, true) (AuthService.php:181):
    • Argumen 1 forceBlacklist=true — token lama di-blacklist, tidak bisa dipakai lagi
    • Argumen 2 blacklistEmulate=true — emulate blacklist behavior
  • Blacklist aktif (config/jwt.php:222 JWT_BLACKLIST_ENABLED=true), storage default cache Illuminate (config/jwt.php:299)

Token expired saat request

Tymon lempar TokenExpiredException. Di AuthService.php:191-195 catch jadi AuthenticationException (401). Frontend axiosInstance.js:46:

  1. POST /api/refresh pakai access token lama di header Authorization
  2. Simpan access token baru ke localStorage
  3. Replay request
  4. Kalau refresh gagal, localStorage.clear() + router.post('/logout') (axiosInstance.js:74-76)

3. Cross-service usage

Service yang memakai JWT dazoapp

ServiceURL configCara pakai
Backend Go (url_api)resources/js/global.js:66-86Frontend call langsung pakai axios polos (lihat SchedularCreate.vue:1342, PenjadwalanBroadcastTab.vue:806)
Engine WhatsApp (url_engine)global.jsTidak ada auth token — endpoint bersifat terbuka, hanya instance ID. Dipanggil dari backend Laravel via cURL (DeviceService.php:33)
Engine Bot (url_ai_agent)global.jsDipanggil dari sisi Go, bukan langsung dari dazoapp

Cara frontend kirim token

Authorization: Bearer {token} header. resources/js/services/axiosInstance.js:12-22 — interceptor request ambil localStorage.getItem('access_token'), set header Authorization.

Token exchange vs langsung

Frontend memanggil backend Go (url_api) langsung pakai JWT dazoapp lewat axios. Tidak ada token exchange.

URL service di frontend

Envurl_engineurl_apiurl_ai_agent
localhttp://localhost:5002/http://127.0.0.1:8081/v1/http://127.0.0.1:1212/
developmenthttps://engine.dazo.dev/https://api.dazo.dev/v1/https://engine-bot.dazo.dev/
productionhttps://engine.dazo.id/https://api.dazo.id/v1/https://engine-bot.dazo.id/

4. Guard & middleware

Guard

Guard api dengan driver jwtconfig/auth.php:43-46. Provider users = Eloquent App\Models\User (config/auth.php:67-70).

User model implement Tymon\JWTAuth\Contracts\JWTSubject (User.php:11,15).

Middleware

  • auth:api HANYA dipakai di 1 route group: routes/api.php:86-89 (/testjwt, /logout)
  • Mayoritas route API pakai auth:sanctum (sanctum stateful via session cookie, bukan JWT)
  • Tidak ada middleware alias jwt.auth / jwt.verify terdaftar di app/Http/Kernel.php:59-75. Tymon default dimasukkan via auth:api guard driver

Scope/role check

user_store pivot di-load saat auth

Eager loading: Auth::user()->loadMissing(['store', 'user_store.store']) — pola dominan (HandleInertiaRequests.php:52, BroadcastchatController.php:517, dst). Relasi User->user_store() = belongsTo(UserStore, 'id', 'user_id') (User.php:45-48). Bukan dari JWT, tapi query DB setelah auth resolve.

Inkonsistensi host engine WA

LokasiHost
resources/js/global.js (production)engine.dazo.id
app/Services/DeviceService.php:17engine-wa.dazo.id
app/Http/Controllers/BroadcastscedularController.php:37engine-wa.dazo.id
app/Http/Controllers/AgentAiController.php:38engine-wa.dazo.id
Controller lain (Downgrade, LoginlogController, OrderController)engine.dazo.id

Jangan pilih sendiri — butuh konfirmasi user. Lihat External Services.

Yang tidak boleh diubah sendiri

Referensi file

FilePeran
app/Services/AuthService.phpIssue + refresh token
app/Http/Controllers/Api/AuthController.phpEndpoint refresh
app/Http/Controllers/QuickLoginController.phpQuick login admin (login-as-user)
app/Models/User.phpJWTSubject implementation
config/jwt.phpTTL, secret, blacklist config
config/auth.phpGuard api driver jwt
resources/js/services/axiosInstance.jsAuto-refresh token frontend
resources/js/global.jsURL service (url_api, url_engine, url_ai_agent)