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

It is correct when decode token ? #137

Closed
wants to merge 1 commit into from

Conversation

huynhlephcvinh
Copy link
Collaborator

@huynhlephcvinh huynhlephcvinh commented Feb 16, 2025

This is test code need review to it is correct

Summary by CodeRabbit

  • New Features

    • Enhanced authentication flow with improved token management for secure logins, refined access control, and streamlined session handling.
  • Style

    • Updated visual elements with adjusted icon dimensions, added borders, and improved text contrast for a more consistent and accessible interface.

Copy link

coderabbitai bot commented Feb 16, 2025

Walkthrough

The changes integrate JWT support across the project. In the frontend, a new dependency (@auth0/angular-jwt) is added and several methods in the ApplicationService now manage access tokens, decode user IDs, and determine user roles. The plan component’s HTML has been updated with modified image attributes and additional CSS classes. In the backend, the UserInfoService now includes extra claims (userId and role) in its JWT authentication token generation.

Changes

File(s) Change Summary
sep490-frontend/package.json
sep490-frontend/.../services/application.service.ts
Added @auth0/angular-jwt dependency and enhanced the ApplicationService with JWT handling methods for token retrieval, storage, expiration check, and extracting userId and userRole.
sep490-frontend/.../plan/plan.component.html Updated <img> attributes (increased dimensions, added "border" class) and added "text-black" CSS classes to <div> and <p-accordion-header> elements for consistent styling.
sep490-idp/.../UserInfoService.java Extended getCustomClaimsForJwtAuthenticationToken method to include additional JWT claims: userId and role.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant ApplicationService
    participant oidcSecurityService
    participant JwtHelperService
    participant LocalStorage

    Client->>ApplicationService: login(credentials)
    ApplicationService->>oidcSecurityService: getAccessToken()
    oidcSecurityService-->>ApplicationService: accessToken
    ApplicationService->>LocalStorage: store(accessToken)
    Client->>ApplicationService: getUserId() / getUserRole()
    ApplicationService->>JwtHelperService: decode(accessToken)
    JwtHelperService-->>ApplicationService: user data
    ApplicationService->>Client: return userId / role
Loading
sequenceDiagram
    autonumber
    participant AuthToken
    participant UserInfoService
    participant UserEntity

    AuthToken->>UserInfoService: getCustomClaimsForJwtAuthenticationToken(email)
    UserInfoService->>UserEntity: fetch user details
    UserEntity-->>UserInfoService: user data (id, role)
    UserInfoService->>AuthToken: return claims {userId, role}
Loading

Possibly Related PRs

Suggested Labels

improvement

Suggested Reviewers

  • GiaBaorr
  • nganntqe170236

Poem

I'm just a rabbit with joyful hops,
Celebrating tokens that dance and swap.
Code now sings a JWT tune,
In frontend and backend, it makes us swoon.
With style and claims so neat,
I munch on carrots—coding can't be beat!
🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

private getAccessToken(): void {
this.oidcSecurityService.getAccessToken().subscribe((token: string) => {
if (token) {
localStorage.setItem('access_token', token);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is correct way to store access_token.
By the way we already store it in session/cookies

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
sep490-frontend/src/app/modules/enterprise/components/plan/plan.component.html (1)

11-25: Enhance payment method images accessibility.

The payment method images need better accessibility attributes.

Add descriptive alt text and aria labels:

 <img
     ngSrc="assets/images/payment-method/momo.svg"
-    alt="Logo"
+    alt="MoMo Payment Method"
+    aria-label="Pay with MoMo"
     width="30"
     height="30"
     priority
 />
 <img
     ngSrc="assets/images/payment-method/vnpay.svg"
-    alt="Logo"
+    alt="VNPay Payment Method"
+    aria-label="Pay with VNPay"
     width="30"
     height="30"
     priority
     class="border"
 />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7097cfc and 32bcd65.

⛔ Files ignored due to path filters (1)
  • sep490-frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • sep490-frontend/package.json (1 hunks)
  • sep490-frontend/src/app/modules/core/services/application.service.ts (4 hunks)
  • sep490-frontend/src/app/modules/enterprise/components/plan/plan.component.html (4 hunks)
  • sep490-idp/src/main/java/green_buildings/idp/service/impl/UserInfoService.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Build Java Modules (sep490-enterprise)
  • GitHub Check: Build Java Modules (sep490-idp)
  • GitHub Check: Build Frontend
🔇 Additional comments (1)
sep490-frontend/package.json (1)

22-22:

❌ Incorrect review comment

Update @auth0/angular-jwt to the latest version.

Version 5.2.0 might have known vulnerabilities.


🌐 Web query:

What is the latest version of @auth0/angular-jwt?

💡 Result:

The latest version of @auth0/angular-jwt is v5.2.0, released on October 31, 2023[10][9]. This version dropped support for Angular versions below 12 and aligns with Google’s maintenance policies for Angular frameworks[3][10].

Key details:

  • Available via npm with installation command: npm install @auth0/angular-jwt[10]
  • Includes updates like Ivy partial compilation mode and Angular 12+ compatibility[3][6]
  • Earlier versions (e.g., v1.x) targeted AngularJS (1.x), while newer versions support Angular 2+[1][5][7].

For projects using Angular ≥12, v5.x remains the recommended stable release[10].

Citations:


Dependency is up-to-date: No update required for @auth0/angular-jwt
The current package.json entry already uses v5.2.0, which is confirmed as the latest stable release.

  • sep490-frontend/package.json at line 22 correctly specifies "@auth0/angular-jwt": "^5.2.0".
  • There is no need to update, as v5.2.0 is the current supported and recommended version for Angular ≥12.

Likely an incorrect or invalid review comment.

Comment on lines +59 to +60
claims.put("userId", user.getId());
claims.put("role", user.getEnterprise().getRole());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Validate and sanitize JWT claims.

The new claims (userId and role) are added without validation:

  1. userId is exposed directly which could be sensitive
  2. No validation on role values which could lead to security issues

Add validation and consider using a more secure approach:

-        claims.put("userId", user.getId());
-        claims.put("role", user.getEnterprise().getRole());
+        claims.put("sub", user.getId().toString()); // Use standard JWT claim
+        if (user.getEnterprise() != null && user.getEnterprise().getRole() != null) {
+            claims.put("role", user.getEnterprise().getRole().name());
+        } else {
+            claims.put("role", "GUEST");
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
claims.put("userId", user.getId());
claims.put("role", user.getEnterprise().getRole());
claims.put("sub", user.getId().toString()); // Use standard JWT claim
if (user.getEnterprise() != null && user.getEnterprise().getRole() != null) {
claims.put("role", user.getEnterprise().getRole().name());
} else {
claims.put("role", "GUEST");
}

Comment on lines +104 to +106
getStoredAccessToken(): string | null {
return localStorage.getItem('access_token') ?? '';
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use secure storage for access tokens.

Storing tokens in localStorage makes them vulnerable to XSS attacks.

Consider using more secure alternatives:

  1. HttpOnly cookies for token storage
  2. In-memory storage with refresh token pattern

Comment on lines +116 to +123
getUserRole(): UserRole {
const token = this.getStoredAccessToken();
if (!token) {
return UserRole.ENTERPRISE_OWNER;
}
const userObject = this.jwtHelperService.decodeToken(token);
return 'role' in userObject ? userObject.role : '';
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid default role assignment.

Defaulting to ENTERPRISE_OWNER when token is missing could lead to privilege escalation.

Modify to use a safer default:

 getUserRole(): UserRole {
   const token = this.getStoredAccessToken();
   if (!token) {
-    return UserRole.ENTERPRISE_OWNER;
+    return UserRole.GUEST;
   }
+  try {
     const userObject = this.jwtHelperService.decodeToken(token);
     return 'role' in userObject ? userObject.role : '';
+  } catch (error) {
+    console.error('Invalid token:', error);
+    return UserRole.GUEST;
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
getUserRole(): UserRole {
const token = this.getStoredAccessToken();
if (!token) {
return UserRole.ENTERPRISE_OWNER;
}
const userObject = this.jwtHelperService.decodeToken(token);
return 'role' in userObject ? userObject.role : '';
}
getUserRole(): UserRole {
const token = this.getStoredAccessToken();
if (!token) {
return UserRole.GUEST;
}
try {
const userObject = this.jwtHelperService.decodeToken(token);
return 'role' in userObject ? userObject.role : '';
} catch (error) {
console.error('Invalid token:', error);
return UserRole.GUEST;
}
}

Comment on lines +107 to +114
getUserId(): UUID | null {
const token = this.getStoredAccessToken();
if (!token) {
return null;
}
const userObject = this.jwtHelperService.decodeToken(token);
return 'userId' in userObject ? userObject.userId : '';
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add token validation before decoding.

The token is decoded without validating its integrity or expiration.

Add validation before using the token:

 getUserId(): UUID | null {
   const token = this.getStoredAccessToken();
-  if (!token) {
+  if (!token || this.isTokenExpired()) {
     return null;
   }
+  try {
     const userObject = this.jwtHelperService.decodeToken(token);
     return 'userId' in userObject ? userObject.userId : '';
+  } catch (error) {
+    console.error('Invalid token:', error);
+    return null;
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
getUserId(): UUID | null {
const token = this.getStoredAccessToken();
if (!token) {
return null;
}
const userObject = this.jwtHelperService.decodeToken(token);
return 'userId' in userObject ? userObject.userId : '';
}
getUserId(): UUID | null {
const token = this.getStoredAccessToken();
if (!token || this.isTokenExpired()) {
return null;
}
try {
const userObject = this.jwtHelperService.decodeToken(token);
return 'userId' in userObject ? userObject.userId : '';
} catch (error) {
console.error('Invalid token:', error);
return null;
}
}

Copy link
Collaborator

@nganntqe170236 nganntqe170236 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok good jobs man, let's @thongdanghoang will do the rest

@@ -56,6 +56,8 @@ public Map<String, Object> getCustomClaimsForJwtAuthenticationToken(String email
.map(UserEnterpriseEntity::getEnterprise)
.map(UUID::toString)
.orElse(null));
claims.put("userId", user.getId());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

userId need to config as sub in access token instead of put userId

@@ -56,6 +56,8 @@ public Map<String, Object> getCustomClaimsForJwtAuthenticationToken(String email
.map(UserEnterpriseEntity::getEnterprise)
.map(UUID::toString)
.orElse(null));
claims.put("userId", user.getId());
claims.put("role", user.getEnterprise().getRole());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

authorities already include user roles, why need we put separately?

@@ -126,7 +130,7 @@
<p-accordion [value]="0">
@for (tab of tabs; track tab.title) {
<p-accordion-panel [value]="tab.value">
<p-accordion-header class="bg-[#F4FCFD]">{{
<p-accordion-header class="bg-[#F4FCFD] text-black">{{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

although UX/UI isn't the most important to put more effort, but hard code color like #F4FCFD is very hard to maintain later, in addition, use text-black will display fail on dark mode, by the way, create task fix dark mode config with primeNG to fix later for this point

private getAccessToken(): void {
this.oidcSecurityService.getAccessToken().subscribe((token: string) => {
if (token) {
localStorage.setItem('access_token', token);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never manually put secret to localStorage, we need to handle access token in application lifecycle instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants