Skip to content

Commit

Permalink
fix(authentication-client): Remove access token for fatal 400 errors (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
daffl authored Nov 25, 2022
1 parent cc4e767 commit cfc6c7a
Showing 1 changed file with 51 additions and 1 deletion.
52 changes: 51 additions & 1 deletion packages/authentication-client/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ export class AuthenticationClient {
})
}

/**
* Parse the access token or authentication error from the window location hash. Will remove it from the hash
* if found.
*
* @param location The window location
* @returns The access token if available, will throw an error if found, otherwise null
*/
getFromLocation(location: Location) {
const [accessToken, tokenRegex] = getMatch(location, this.options.locationKey)

Expand All @@ -102,10 +109,21 @@ export class AuthenticationClient {
return Promise.resolve(null)
}

/**
* Set the access token in storage.
*
* @param accessToken The access token to set
* @returns
*/
setAccessToken(accessToken: string) {
return this.storage.setItem(this.options.storageKey, accessToken)
}

/**
* Returns the access token from storage or the window location hash.
*
* @returns The access token from storage or location hash
*/
getAccessToken(): Promise<string | null> {
return this.storage.getItem(this.options.storageKey).then((accessToken: string) => {
if (!accessToken && typeof window !== 'undefined' && window.location) {
Expand All @@ -116,10 +134,19 @@ export class AuthenticationClient {
})
}

/**
* Remove the access token from storage
* @returns The removed access token
*/
removeAccessToken() {
return this.storage.removeItem(this.options.storageKey)
}

/**
* Reset the internal authentication state. Usually not necessary to call directly.
*
* @returns null
*/
reset() {
this.app.set('authentication', null)
this.authenticated = false
Expand All @@ -128,7 +155,9 @@ export class AuthenticationClient {
}

handleError(error: FeathersError, type: 'authenticate' | 'logout') {
if (error.code === 401 || error.code === 403) {
// For NotAuthenticated, PaymentError, Forbidden, NotFound, MethodNotAllowed, NotAcceptable
// errors, remove the access token
if (error.code > 400 && error.code < 408) {
const promise = this.removeAccessToken().then(() => this.reset())

return type === 'logout' ? promise : promise.then(() => Promise.reject(error))
Expand All @@ -137,6 +166,14 @@ export class AuthenticationClient {
return this.reset().then(() => Promise.reject(error))
}

/**
* Try to reauthenticate using the token from storage. Will do nothing if already authenticated unless
* `force` is true.
*
* @param force force reauthentication with the server
* @param strategy The name of the strategy to use. Defaults to `options.jwtStrategy`
* @returns The reauthentication result
*/
reAuthenticate(force = false, strategy?: string): Promise<AuthenticationResult> {
// Either returns the authentication state or
// tries to re-authenticate with the stored JWT and strategy
Expand All @@ -159,6 +196,13 @@ export class AuthenticationClient {
return authPromise
}

/**
* Authenticate using a specific strategy and data.
*
* @param authentication The authentication data
* @param params Additional parameters
* @returns The authentication result
*/
authenticate(authentication?: AuthenticationRequest, params?: Params): Promise<AuthenticationResult> {
if (!authentication) {
return this.reAuthenticate()
Expand All @@ -182,6 +226,12 @@ export class AuthenticationClient {
return promise
}

/**
* Log out the current user and remove their token. Will do nothing
* if not authenticated.
*
* @returns The log out result.
*/
logout(): Promise<AuthenticationResult | null> {
return Promise.resolve(this.app.get('authentication'))
.then(() =>
Expand Down

0 comments on commit cfc6c7a

Please sign in to comment.