Skip to content

Commit

Permalink
Revoke token on logout (#541)
Browse files Browse the repository at this point in the history
  • Loading branch information
lanedirt committed Jan 28, 2025
1 parent 640b2e1 commit b38708b
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 17 deletions.
4 changes: 2 additions & 2 deletions browser-extensions/chrome/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import './styles/app.css';
import EncryptionUtility from './utils/EncryptionUtility';
import { VaultResponse } from './types/webapi/VaultResponse';
import { useWebApi } from './context/WebApiContext';
import SrpUtility from './utils/SrpUtility';

/**
* Main application component
Expand Down Expand Up @@ -76,11 +75,12 @@ const App: React.FC = () => {
*/
const handleLogout = async (): Promise<void> => {
setIsLoading(true);
setIsUserMenuOpen(false);
try {
await webApi.logout();
await authContext.logout();
} finally {
setIsLoading(false);
setIsUserMenuOpen(false);
}
};

Expand Down
11 changes: 8 additions & 3 deletions browser-extensions/chrome/src/contentScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,20 @@ function createPopup(input: HTMLInputElement, credentials: Credential[]) : void
padding: 8px 0;
`;

// Change to mousedown event instead of click
const handleClickOutside = (event: MouseEvent) => {
/**
* Close autofill popup when clicking outside.
*/
const handleClickOutside = (event: MouseEvent) : void => {
if (!popup.contains(event.target as Node)) {
removeExistingPopup();
document.removeEventListener('mousedown', handleClickOutside);
}
};

// Use setTimeout to prevent immediate trigger of the mousedown event
/**
* Add event listener to document to close popup when clicking outside
* after a short delay to prevent immediate trigger of the mousedown event.
*/
setTimeout(() => {
document.addEventListener('mousedown', handleClickOutside);
}, 100);
Expand Down
1 change: 1 addition & 0 deletions browser-extensions/chrome/src/pages/Unlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const Unlock: React.FC = () => {
const handleLogout = async () : Promise<void> => {
showLoading();
try {
await webApi.logout();
await authContext.logout();
} finally {
hideLoading();
Expand Down
44 changes: 32 additions & 12 deletions browser-extensions/chrome/src/utils/WebApiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ export class WebApiService {
}

/**
* Fetch data from the API
* Fetch data from the API.
*/
public async fetch<T>(
endpoint: string,
options: RequestInit = {}
options: RequestInit = {},
parseJson: boolean = true
): Promise<T> {
const url = this.baseUrl + endpoint;
const headers = new Headers(options.headers || {});
Expand Down Expand Up @@ -78,7 +79,7 @@ export class WebApiService {
throw new Error('Request failed after token refresh');
}

return retryResponse.json();
return parseJson ? retryResponse.json() : retryResponse.text() as T;
} else {
this.handleLogout();
throw new Error('Session expired');
Expand All @@ -89,15 +90,15 @@ export class WebApiService {
throw new Error(`HTTP error! status: ${response.status}`);
}

return response.json();
return parseJson ? response.json() : response.text() as T;
} catch (error) {
console.error('API request failed:', error);
throw error;
}
}

/**
* Refresh the access token
* Refresh the access token.
*/
private async refreshAccessToken(): Promise<string | null> {
const refreshToken = this.getRefreshToken();
Expand Down Expand Up @@ -132,27 +133,31 @@ export class WebApiService {
}

/**
* Get a resource
* Issue GET request to the API.
*/
public async get<T>(endpoint: string): Promise<T> {
return this.fetch<T>(endpoint, { method: 'GET' });
}

/**
* Create a resource
* Issue POST request to the API.
*/
public async post<TRequest, TResponse>(endpoint: string, data: TRequest): Promise<TResponse> {
public async post<TRequest, TResponse>(
endpoint: string,
data: TRequest,
parseJson: boolean = true
): Promise<TResponse> {
return this.fetch<TResponse>(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
}, parseJson);
}

/**
* Update a resource
* Issue PUT request to the API.
*/
public async put<TRequest, TResponse>(endpoint: string, data: TRequest): Promise<TResponse> {
return this.fetch<TResponse>(endpoint, {
Expand All @@ -165,9 +170,24 @@ export class WebApiService {
}

/**
* Delete a resource
* Issue DELETE request to the API.
*/
public async delete<T>(endpoint: string): Promise<T> {
return this.fetch<T>(endpoint, { method: 'DELETE' });
}
}

/**
* Logout and revoke tokens via WebApi.
*/
public async logout(): Promise<void> {
const refreshToken = this.getRefreshToken();
if (!refreshToken) {
return;
}

await this.post('Auth/revoke', {
token: this.getAccessToken(),
refreshToken: refreshToken,
}, false);
}
}

0 comments on commit b38708b

Please sign in to comment.