* Read + delete the stored state. Returns `null` if absent (expired, * forged, or already consumed) — and equally if the stored value is * not a JSON object: corrupted state must fail the flow, not pass as * a valid state with no extras. Read-and-delete makes replay * impossible.
(state: string)
| 74 | * impossible. |
| 75 | */ |
| 76 | async consume(state: string): Promise<IStoredState | null> { |
| 77 | const key = `${OAUTH_STATE_PREFIX}${state}`; |
| 78 | const raw = await this.getClient().getdel(key); |
| 79 | |
| 80 | if (raw === null) { |
| 81 | return null; |
| 82 | } |
| 83 | |
| 84 | try { |
| 85 | const parsed: unknown = JSON.parse(raw); |
| 86 | |
| 87 | if (parsed === null || typeof parsed !== "object") { |
| 88 | return null; |
| 89 | } |
| 90 | |
| 91 | const result: IStoredState = {}; |
| 92 | |
| 93 | if ("codeVerifier" in parsed && typeof parsed.codeVerifier === "string") { |
| 94 | result.codeVerifier = parsed.codeVerifier; |
| 95 | } |
| 96 | |
| 97 | if ("linkUserId" in parsed && typeof parsed.linkUserId === "string") { |
| 98 | result.linkUserId = parsed.linkUserId; |
| 99 | } |
| 100 | |
| 101 | return result; |
| 102 | } catch { |
| 103 | return null; |
| 104 | } |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | export const oauthStateStore = new OAuthStateStore(); |
no test coverage detected