Skip to content

Commit

Permalink
feat: add setSession support for a SSR context
Browse files Browse the repository at this point in the history
  • Loading branch information
hf committed Sep 21, 2022
1 parent 5609423 commit d8f83b1
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 8 deletions.
101 changes: 94 additions & 7 deletions src/GoTrueClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,25 +380,112 @@ export default class GoTrueClient {
}
}

/**
* Sets the session from the provided session information. The access_token
* is reused if it is not expired, otherwise a new access token is fetched by
* refreshing the session with the provided refresh_token.
*
* This method is useful when using in a server-side rendered context.
*
* @param params.refresh_token A valid refresh token (typically obtained from a cookie)
* @param params.access_token An access token (typically obtained from a cookie)
* @param params.provider_token A provider token (from social login, for example), optional
* @param params.expires_in A timeout in seconds when the access token will expire, if not provided taken from the `exp` claim in the access token
*/
async setSession(params: {
refresh_token: string
access_token: string
expires_in?: number
provider_token?: string
}): Promise<{ session: Session | null; error: ApiError | null }>

/**
* Sets the session data from refresh_token and returns current Session and Error
* @param refresh_token a JWT token
*/
async setSession(
refresh_token: string
): Promise<{ session: Session | null; error: ApiError | null }> {
try {
if (!refresh_token) {
throw new Error('No current session.')
}
): Promise<{ session: Session | null; error: ApiError | null }>

async setSession(arg0: any): Promise<{ session: Session | null; error: ApiError | null }> {
let session: Session

if (typeof arg0 === 'string') {
// using the refresh_token string API
const refresh_token = arg0

const { data, error } = await this.api.refreshAccessToken(refresh_token)
if (error) {
return { session: null, error: error }
}

this._saveSession(data!)
session = data!
} else if (
typeof arg0 === 'object' &&
arg0 &&
typeof arg0.refresh_token === 'string' &&
typeof arg0.access_token === 'string' &&
(typeof arg0.expires_in === 'number' || !arg0.expires_in) &&
(typeof arg0.provider_token === 'string' || !arg0.provider_token)
) {
// using the object parameter API
let { provider_token, refresh_token, access_token, expires_in } = arg0

const timeNow = Math.round(Date.now() / 1000)
let expires_at = 0

if (expires_in) {
expires_at = timeNow + expires_in
} else {
const tokenParts = access_token.split('.')
if (tokenParts.length !== 3) throw new Error('access_token is not a proper JWT')

const bodyJSON = atob(tokenParts[1].replaceAll(/[-]/g, '+').replaceAll(/[_]/g, '/'))

let parsed: any = undefined
try {
parsed = JSON.parse(bodyJSON)
} catch (e) {
throw new Error('access_token is not a proper JWT, invalid JSON in body')
}

if (typeof parsed === 'object' && parsed && typeof parsed.exp === 'number') {
expires_in = Math.max(0, parsed.exp - timeNow)
expires_at = parsed.exp
} else {
throw new Error('access_token is not a proper JWT, missing exp claim')
}
}

if (timeNow > expires_at) {
const { data, error } = await this.api.refreshAccessToken(refresh_token)
if (error) {
return { session: null, error: error }
}

session = data!
} else {
const { user, error } = await this.api.getUser(access_token)
if (error) throw error

session = {
provider_token,
access_token,
expires_in,
expires_at,
refresh_token,
token_type: 'Bearer',
user: user!,
}
}
} else {
throw new Error('Invalid argument, must be string or object')
}

try {
this._saveSession(session)
this._notifyAllSubscribers('SIGNED_IN')
return { session: data, error: null }
return { session, error: null }
} catch (e) {
return { error: e as ApiError, session: null }
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/version.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// generated by genversion
// Generated by genversion.
export const version = '0.0.0'

0 comments on commit d8f83b1

Please sign in to comment.