Laravel AT Protocol Client (alpha & unstable)

Parse JWT expiry for legacy tokens instead of defaulting to 300s

Changed files
+25 -1
src
+25 -1
src/Data/AccessToken.php
··· 2 2 3 3 namespace SocialDept\AtpClient\Data; 4 4 5 + use Carbon\Carbon; 5 6 use SocialDept\AtpClient\Enums\AuthType; 6 7 7 8 class AccessToken ··· 40 41 } 41 42 42 43 // Legacy createSession format (app passwords have full access) 44 + // Parse expiry from JWT since createSession doesn't return expiresIn 45 + $expiresAt = self::parseJwtExpiry($data['accessJwt']) ?? now()->addHour(); 46 + 43 47 return new self( 44 48 accessJwt: $data['accessJwt'], 45 49 refreshJwt: $data['refreshJwt'], 46 50 did: $data['did'], 47 - expiresAt: now()->addSeconds($data['expiresIn'] ?? 300), 51 + expiresAt: $expiresAt, 48 52 handle: $data['handle'] ?? $handle, 49 53 issuer: $issuer, 50 54 scope: ['atproto', 'transition:generic', 'transition:email'], 51 55 authType: AuthType::Legacy, 52 56 ); 57 + } 58 + 59 + /** 60 + * Parse the expiry timestamp from a JWT's payload. 61 + */ 62 + protected static function parseJwtExpiry(string $jwt): ?\DateTimeInterface 63 + { 64 + $parts = explode('.', $jwt); 65 + 66 + if (count($parts) !== 3) { 67 + return null; 68 + } 69 + 70 + $payload = json_decode(base64_decode(strtr($parts[1], '-_', '+/')), true); 71 + 72 + if (! isset($payload['exp'])) { 73 + return null; 74 + } 75 + 76 + return Carbon::createFromTimestamp($payload['exp']); 53 77 } 54 78 }