Laravel AT Protocol Client (alpha & unstable)
at main 78 lines 2.5 kB view raw
1<?php 2 3namespace SocialDept\AtpClient\Data; 4 5use Carbon\Carbon; 6use SocialDept\AtpClient\Enums\AuthType; 7 8class AccessToken 9{ 10 public function __construct( 11 public readonly string $accessJwt, 12 public readonly string $refreshJwt, 13 public readonly string $did, 14 public readonly \DateTimeInterface $expiresAt, 15 public readonly ?string $handle = null, 16 public readonly ?string $issuer = null, 17 public readonly array $scope = [], 18 public readonly AuthType $authType = AuthType::OAuth, 19 ) {} 20 21 /** 22 * Create from API response. 23 * 24 * Handles both legacy createSession format (accessJwt, refreshJwt, did) 25 * and OAuth token format (access_token, refresh_token, sub). 26 */ 27 public static function fromResponse(array $data, ?string $handle = null, ?string $issuer = null): self 28 { 29 // OAuth token endpoint format 30 if (isset($data['access_token'])) { 31 return new self( 32 accessJwt: $data['access_token'], 33 refreshJwt: $data['refresh_token'] ?? '', 34 did: $data['sub'] ?? '', 35 expiresAt: now()->addSeconds($data['expires_in'] ?? 300), 36 handle: $handle, 37 issuer: $issuer, 38 scope: isset($data['scope']) ? explode(' ', $data['scope']) : [], 39 authType: AuthType::OAuth, 40 ); 41 } 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 47 return new self( 48 accessJwt: $data['accessJwt'], 49 refreshJwt: $data['refreshJwt'], 50 did: $data['did'], 51 expiresAt: $expiresAt, 52 handle: $data['handle'] ?? $handle, 53 issuer: $issuer, 54 scope: ['atproto', 'transition:generic', 'transition:email'], 55 authType: AuthType::Legacy, 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']); 77 } 78}