···11+import {jwtDecode} from 'jwt-decode'
22+33+import {logger} from '#/logger'
44+55+/**
66+ * Simple check if a JWT token has expired. Does *not* validate the token or check for revocation status,
77+ * just checks the expiration time.
88+ *
99+ * @param token The JWT token to check.
1010+ * @returns `true` if the token has expired, `false` otherwise.
1111+ */
1212+export function isJwtExpired(token: string) {
1313+ try {
1414+ const payload = jwtDecode(token)
1515+1616+ if (!payload.exp) return true
1717+ const now = Math.floor(Date.now() / 1000)
1818+ return now >= payload.exp
1919+ } catch {
2020+ logger.error(`session: could not decode jwt`)
2121+ return true // invalid token or parse error
2222+ }
2323+}
+3-2
src/screens/Login/ChooseAccountForm.tsx
···88import {type SessionAccount, useSession, useSessionApi} from '#/state/session'
99import {useLoggedOutViewControls} from '#/state/shell/logged-out'
1010import * as Toast from '#/view/com/util/Toast'
1111-import {atoms as a} from '#/alf'
1111+import {atoms as a, web} from '#/alf'
1212import {AccountList} from '#/components/AccountList'
1313import {Button, ButtonText} from '#/components/Button'
1414import * as TextField from '#/components/forms/TextField'
···7474 return (
7575 <FormContainer
7676 testID="chooseAccountForm"
7777- titleText={<Trans>Select account</Trans>}>
7777+ titleText={<Trans>Select account</Trans>}
7878+ style={web([a.py_2xl])}>
7879 <View>
7980 <TextField.LabelText>
8081 <Trans>Sign in as...</Trans>
+5-12
src/state/session/util.ts
···11import {jwtDecode} from 'jwt-decode'
2233+import {isJwtExpired} from '#/lib/jwt'
34import {hasProp} from '#/lib/type-guards'
44-import {logger} from '#/logger'
55import * as persisted from '#/state/persisted'
66import {type SessionAccount} from './types'
77···2222}
23232424export function isSessionExpired(account: SessionAccount) {
2525- try {
2626- if (account.accessJwt) {
2727- const decoded = jwtDecode(account.accessJwt)
2828- if (decoded.exp) {
2929- const didExpire = Date.now() >= decoded.exp * 1000
3030- return didExpire
3131- }
3232- }
3333- } catch (e) {
3434- logger.error(`session: could not decode jwt`)
2525+ if (account.accessJwt) {
2626+ return isJwtExpired(account.accessJwt)
2727+ } else {
2828+ return true
3529 }
3636- return true
3730}