header('Authorization', ''); $jwt = str_starts_with($authHeader, 'Bearer ') ? substr($authHeader, 7) : ''; if (empty($jwt)) { return $this->fail('No token provided.', 'missing_token', 401); } $payload = $this->ldapJwt->validate($jwt); if ($payload === null) { return $this->fail('Token invalid or expired.', 'invalid_token', 401); } $newToken = $this->ldapJwt->issue( $payload['username'], $payload['is_admin'], $payload['groups'] ?? [] ); $this->audit->logPublic('api.v1.auth.refresh', $payload['username'], $request, [ 'username' => $payload['username'], ]); return $this->ok([ 'access_token' => $newToken, 'token_type' => 'Bearer', 'expires_in' => config('api.ldap_jwt_ttl'), 'auth_type' => 'ldap_jwt', ]); } public function login(Request $request): JsonResponse { $credentials = $request->validate([ 'username' => ['required', 'string', 'max:100'], 'password' => ['required', 'string', 'max:255'], ]); $user = $this->ldapAuth->attempt($credentials['username'], $credentials['password']); if ($user === null) { $this->audit->logPublic('api.v1.auth.login.failed', $credentials['username'], $request, [ 'username' => $credentials['username'], ]); return $this->fail('Invalid LDAP credentials.', 'invalid_credentials', 401); } $profile = $this->ldapAuth->lookupUser($user['username']); $groups = $profile['groups'] ?? []; $token = $this->ldapJwt->issue($user['username'], $user['is_admin'], $groups); $this->audit->logPublic('api.v1.auth.login', $user['username'], $request, [ 'username' => $user['username'], 'is_admin' => $user['is_admin'], ]); return $this->ok([ 'access_token' => $token, 'token_type' => 'Bearer', 'expires_in' => config('api.ldap_jwt_ttl'), 'auth_type' => 'ldap_jwt', 'user' => [ 'username' => $user['username'], 'display_name' => $user['display_name'], 'is_admin' => $user['is_admin'], ], ]); } public function apiForgotPassword(Request $request): JsonResponse { $data = $request->validate([ 'username' => ['required', 'string', 'max:100', 'regex:/^[a-zA-Z0-9._-]+$/'], ]); try { $this->passwordReset->sendResetLink($data['username']); $this->audit->logPublic('api.v1.auth.password.forgot', $data['username'], $request, [ 'username' => $data['username'], 'source' => 'api', ]); } catch (\Throwable) { // Do not reveal whether user exists or email failed. } return $this->ok([ 'message' => 'Jika akun ditemukan dan memiliki email terdaftar, link reset password telah dikirim. Link berlaku selama 60 menit.', ]); } }