AccessToken returns a valid access token, refreshing if needed. If HEY_TOKEN env var is set, it's used directly.
(ctx context.Context)
| 45 | // AccessToken returns a valid access token, refreshing if needed. |
| 46 | // If HEY_TOKEN env var is set, it's used directly. |
| 47 | func (m *Manager) AccessToken(ctx context.Context) (string, error) { |
| 48 | if token := os.Getenv("HEY_TOKEN"); token != "" { |
| 49 | return token, nil |
| 50 | } |
| 51 | |
| 52 | m.mu.Lock() |
| 53 | defer m.mu.Unlock() |
| 54 | |
| 55 | creds, err := m.store.Load(m.baseURL) |
| 56 | if err != nil { |
| 57 | return "", fmt.Errorf("not authenticated: %w", err) |
| 58 | } |
| 59 | |
| 60 | // Check if token is expired (with 5-minute buffer) |
| 61 | if creds.ExpiresAt > 0 && time.Now().Unix() >= creds.ExpiresAt-300 { |
| 62 | if err = m.refreshLocked(ctx, creds); err != nil { |
| 63 | return "", err |
| 64 | } |
| 65 | creds, err = m.store.Load(m.baseURL) |
| 66 | if err != nil { |
| 67 | return "", fmt.Errorf("failed to load refreshed credentials: %w", err) |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | if creds.AccessToken != "" { |
| 72 | return creds.AccessToken, nil |
| 73 | } |
| 74 | |
| 75 | // Fall back to session cookie for cookie-based auth. |
| 76 | if creds.SessionCookie != "" { |
| 77 | return creds.SessionCookie, nil |
| 78 | } |
| 79 | |
| 80 | return "", fmt.Errorf("no access token or session cookie available") |
| 81 | } |
| 82 | |
| 83 | // AuthenticateRequest sets the appropriate auth header on an HTTP request. |
| 84 | // Uses Bearer token if available, otherwise falls back to session cookie. |