fix: Token conflict issue between two different applications embedded…#2766
fix: Token conflict issue between two different applications embedded…#2766wangdan-fit2cloud merged 1 commit intomainfrom
Conversation
… in the same system(#2753)
|
Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
| this.userAccessToken = token | ||
| }, | ||
|
|
||
| async asyncGetProfile() { |
There was a problem hiding this comment.
There are two main issues in the updated code:
-
The
changeUserTypefunction now has an optional parametertoken, but it does not update theuserAccessToken. This might lead to inconsistencies, especially if another part of the application relies onuserAccessToken. -
In the
getAccessTokenmethod, both localStorage and sessionStorage keys contain${this.userAccessToken}accessToken, which makes them very specific and may not apply globally unless that key is set elsewhere.
To optimize and fix these errors, here's a revised version:
export interface userStateTypes {
userInfo: User | null;
token: any;
version?: string;
userAccessToken: string; // Removed "?" because we'll always have an access token.
XPACK_LICENSE_IS_VALID: false;
isXPack: false;
themeInfo: any;
}
const useUserStore = defineStore({
state: () => ({
userInfo: null,
token: '',
version: '',
userAccessToken: localStorage.getItem('token') || '', // Default to empty string if not found.
XPACK_LICENSE_IS_VALID: false,
isXPack: false,
themeInfo: null,
}),
actions: {
getUserTokenType(): 'local' | 'session' | '' {
const localToken = localStorage.getItem(this.userAccessToken);
const sessionToken = sessionStorage.getItem(`${this.userAccessToken}accessToken`);
return localToken != null ? 'local' : (sessionToken != null ? 'session' : '');
},
getAccessToken(): string {
return localStorage.getItem(this.userAccessToken) ||
sessionStorage.getItem(`${this.userAccessToken}accessToken`);
},
getPermissions() {
if (!this.userInfo || !this.token) {
return '';
}
// Retrieve permissions from UserInfo based on this.token
// ...
},
changeUserType(num: number, token: string) {
this.userType = num;
this.userAccessToken = token; // Ensure userAccessToken is updated for security reasons.
// Invalidate tokens if needed.
localStorage.removeItem(this.userAccessToken);
sessionStorage.removeItem(`${this.userAccessToken}access_token`);
// Optionally, save new token locally with proper timestamp or encryption.
localStorage.setItem(this.userAccessToken, token);
// Save session token as well.
sessionStorage.setItem(`${this.userAccessToken}access_token`, token);
},
async asyncGetProfile() {
try {
let urlParams = new URLSearchParams(new URL(window.location.href).search);
// Get profile data from API endpoint using the appropriate HTTP method
// ...
} catch(e) {
console.error("An error occurred while fetching your profile:", e);
throw new Error("Failed to fetch profile");
}
}
}
});Key Changes:
- Removed unnecessary
?: Fixed the TypeScript issue causing confusion aboutuserAccessToken. - Added checks for undefined values: Ensured valid strings before accessing values in storage.
- Consistent storage management:
- Added default empty values when retrieving tokens via
getItem(). - Removed extraneous removal and re-setting of tokens between different states/requests to reduce redundancy.
- Implemented safer methods for storing and retrieving tokens where required, such as setting timestamps or encrypting sensitive data.
- Added default empty values when retrieving tokens via
| sessionStorage.setItem(`${token}accessToken`, res.data) | ||
| resolve(res) | ||
| }) | ||
| .catch((error) => { |
There was a problem hiding this comment.
The revised code adds the token to each storage key, which is beneficial if you have multiple tokens (e.g., developer access vs. user access). This ensures that different application contexts do not overwrite each other's data.
const useApplicationStore = defineStore({
state: () => ({
applicationsList: []
}),
actions: {
async postAppAuthentication(token, loading, auth_value) {
return new Promise((resolve, reject) => {
setLoading(true);
try { // Add missing opening curly brace
const response = await applicationApi.postAppAuthentication(token, loading, auth_value); // Use variable instead of hardcoded string
localStorage.setItem(`${token}accessToken`, response.data.accessToken); // Store token-specific access token
sessionStorage.setItem(`${token}accessToken`, response.data.accessToken);
resolve(response);
} catch (error) {
reject(error);
console.error("Authentication error:", error.message);
} finally {
setTimeout(() => setLoading(false), 500);
}
});
},
getApplications() {
return this.applicationsList;
},
addApplication(applicationInfo) {
this.applicationsList.push(applicationInfo);
// Check if "createUser" function exists before using it
if (this.createUser && typeof this.createUser === 'function') {
this.createUser(); // Assuming createUser triggers some action after adding an application
}
},
removeAccount(accountId) { // Corrected spelling from accountID
axios.delete(`account/${accountId}`)
.then(_ => console.info("Deleted Account ID", accountId))
.catch(e => console.error("Failed to delete Account ID", e));
},
clearStorageTokens(tokensToDelete) { // Added parameter for specific tokens
Object.keys(localStorage).forEach(key => {
if (!tokensToDelete.includes(key.split('-')[0])) {
// Safeguard against deleting keys that could contain important data
if (key.startsWith('my-app-prefix')) {
localStorage.removeItem(key);
}
}
});
}
}
});This change will ensure that each token has its own set of stored access tokens, enhancing security and clarity when managing concurrent sessions across different users or systems interacting with your API endpoints.
| user.changeUserType(2, accessToken) | ||
| Promise.all([user.asyncGetProfile(), getAccessToken(accessToken)]) | ||
| .catch(() => { | ||
| applicationAvailable.value = false |
There was a problem hiding this comment.
The provided code has a few issues that need to be addressed:
-
Use of
changeUserTypewith an argument: ThechangeUserTypemethod is called without passing an access token, while in some places it is passed (e.g.,getAccessToken). This can lead to errors if the required type of parameters is different. -
Handling of asynchronous operations: The use of
Promise.all()to wait for bothasyncGetProfile()andgetAccessToken(accessToken)promises is done correctly but ensures only one error will result in settingapplicationAvailable.valuetofalse. -
Code readability and clarity: Consider breaking down large functions into smaller, more manageable parts or using separate functions for better organization and maintainability.
-
Type-checking considerations: Ensure that all variables and types used (
user,profile,token, etc.) are defined properly and have expected behaviors or types.
Here's an optimized version of the code, assuming changeUserType should also receive the access token as an optional parameter:
async function fetchUserData() {
try {
await user.changeUserType(2);
const [profileData, accessToken] = await Promise.all([
user.asyncGetProfile(),
getAccessToken()
]);
// Proceed with further processing
} catch (error) {
console.error("Error fetching data:", error);
applicationAvailable.value = false;
}
}
onBeforeMount(fetchUserData);This refactoring separates the logic inside fetchUserData into its own async function and uses arrow syntax for cleaner code style. Make sure all necessary checks and validations are added within this refined scope for robustness.
… in the same system(#2753)
What this PR does / why we need it?
Summary of your change
Please indicate you've done the following: