Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: base64-encode session value #816

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/GoTrueClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ export default class GoTrueClient {
try {
let currentSession: Session | null = null

const maybeSession = await getItemAsync(this.storage, this.storageKey)
const maybeSession = await getItemAsync(this.storage, this.storageKey, true)

this._debug('#getSession()', 'session from storage', maybeSession)

Expand Down Expand Up @@ -1665,7 +1665,7 @@ export default class GoTrueClient {
this._debug(debugName, 'begin')

try {
const currentSession = await getItemAsync(this.storage, this.storageKey)
const currentSession = await getItemAsync(this.storage, this.storageKey, true)
this._debug(debugName, 'session from storage', currentSession)

if (!this._isValidSession(currentSession)) {
Expand Down Expand Up @@ -1820,7 +1820,8 @@ export default class GoTrueClient {
private _persistSession(currentSession: Session) {
this._debug('#_persistSession()', currentSession)

return setItemAsync(this.storage, this.storageKey, currentSession)
// encode the session in base64 for storages such as cookie
return setItemAsync(this.storage, this.storageKey, currentSession, true)
}

private async _removeSession() {
Expand Down
20 changes: 16 additions & 4 deletions src/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,26 @@ export const looksLikeFetchResponse = (maybeResponse: unknown): maybeResponse is
export const setItemAsync = async (
storage: SupportedStorage,
key: string,
data: any
data: any,
base64 = false
): Promise<void> => {
await storage.setItem(key, JSON.stringify(data))
const value = JSON.stringify(data)
await storage.setItem(key, base64 ? encodeBase64URL(value) : value)
}

export const getItemAsync = async (storage: SupportedStorage, key: string): Promise<unknown> => {
export const getItemAsync = async (
storage: SupportedStorage,
key: string,
base64 = false
): Promise<unknown> => {
const value = await storage.getItem(key)

if (!value) {
return null
}

try {
return JSON.parse(value)
return JSON.parse(base64 ? decodeBase64URL(value) : value)
} catch {
return value
}
Expand All @@ -139,6 +145,12 @@ export const removeItemAsync = async (storage: SupportedStorage, key: string): P
await storage.removeItem(key)
}

const encoder = new TextEncoder()

export function encodeBase64URL(value: string): string {
return base64urlencode(Array.from(encoder.encode(value), (c) => String.fromCharCode(c)).join(''))
}

export function decodeBase64URL(value: string): string {
const key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
let base64 = ''
Expand Down
12 changes: 8 additions & 4 deletions test/GoTrueClient.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Buffer } from 'node:buffer'
import { AuthError } from '../src/lib/errors'
import {
authClient as auth,
Expand Down Expand Up @@ -183,12 +184,15 @@ describe('GoTrueClient', () => {
// @ts-expect-error 'Allow access to protected storageKey'
const storageKey = authWithSession.storageKey

const value = Buffer.from(
(await storage.getItem(storageKey)) || Buffer.from('null').toString('base64url'),
'base64url'
).toString('utf8')
await storage.setItem(
storageKey,
JSON.stringify({
...JSON.parse((await storage.getItem(storageKey)) || 'null'),
expires_at: expiredSeconds,
})
Buffer.from(JSON.stringify({ ...JSON.parse(value), expires_at: expiredSeconds })).toString(
'base64url'
)
)

// wait 1 seconds before calling getSession()
Expand Down