Skip to content

Feature request: Refresh token system for TESTING_SESSION #956

Description

@tickBit

What do you want to see in the API?

Add backward-compatible refresh token support for TESTING_SESSION authentication.

In this context:

GroupAdmin = teacher
tester = student
box = testing session

Refresh token support should work for both:

GroupAdmin / teacher tokens
tester / student tokens

The current API responses that already return an accessToken should keep working exactly as before, but should additionally return:

{
  "refreshToken": "...",
  "refreshTokenExpires": 1234567890
}

Relevant flows:

POST /box
POST /box/admin/signIn
POST /box/claim-account
POST /auth/signIn
POST /auth/refresh

POST /auth/refresh should also work in TESTING_SESSION mode. It should return a new access token and a new refresh token for the same testing session user. Currently that endpoint is not implemented yet. A separate issue exists for normal auth flow (both will use the same endpoint for refresh token).

Example response:

{
  "accessToken": "...",
  "tokenExpires": 1234567890,
  "refreshToken": "...",
  "refreshTokenExpires": 1234567890
}

How do you think this should work?

In TESTING_SESSION, tokens are not normal auth tokens. They must include testing-session-specific fields.

The current BoxAuthGuard expects the token payload to contain:

{
  profile_id,
  player_id,
  box_id,
  groupAdmin
}

For tester/student tokens, the current claim-account flow also includes:

{
  clan_id
}

Refresh token payload should preserve the same important identity/session information:

{
  profile_id,
  player_id,
  box_id,
  groupAdmin,
  clan_id?, // include this when the original user/token has it
  type: 'refresh',
  tokenVersion
}

groupAdmin: true means the token belongs to the teacher.

groupAdmin: false means the token belongs to a tester/student.

The refresh endpoint should not need to know whether the user is a teacher or a student based on the URL. It can inspect the refresh token payload and recreate the correct access token from that.

Suggested flow:

  1. User receives access token and refresh token from a testing-session auth flow.
  2. Access token expires.
  3. Frontend calls:
POST /auth/refresh

with:

{
  "refreshToken": "..."
}
  1. Backend verifies the refresh token.
  2. Backend checks that the profile, player, and box still exist.
  3. Backend checks that tokenVersion still matches the profile.
  4. Backend returns a new access token and a new refresh token.
  5. The new access token must work with BoxAuthGuard.

The refresh endpoint should return 401 Unauthorized if:

  • refresh token is missing
  • refresh token is expired
  • refresh token signature is invalid
  • token type is not "refresh"
  • profile does not exist
  • player does not exist
  • box does not exist
  • tokenVersion does not match
  • box_id is missing
  • groupAdmin is missing

For GroupAdmin/teacher tokens, also verify that the token still belongs to the admin of that box.

For tester/student tokens, verify that the profile/player still belongs to the same box_id.

Any additional info?

This issue is only for the Box / TESTING_SESSION side. The normal auth refresh token issue is handled separately.

Important files:

src/auth/box/BoxAuthService.ts
src/box/auth/BoxAuthHandler.ts
src/box/auth/boxAuth.guard.ts
src/box/auth/BoxUser.ts
src/box/accountClaimer/accountClaimer.service.ts
src/box/box.controller.ts
src/auth/auth.controller.ts
src/auth/authService.provider.ts
src/auth/dto/refreshToken.dto.ts

Token creation currently happens in multiple places:

GroupAdmin from POST /box:
src/box/box.controller.ts
src/box/auth/BoxAuthHandler.ts

GroupAdmin from POST /box/admin/signIn:
src/box/box.controller.ts
src/box/auth/BoxAuthHandler.ts

Tester/student from POST /box/claim-account:
src/box/accountClaimer/accountClaimer.service.ts

Testing-session sign-in from POST /auth/signIn:
src/auth/box/BoxAuthService.ts

Because token creation is spread out, it would be good to avoid duplicating refresh-token creation logic in every controller/service. Prefer adding a small helper method on the Box auth side, for example something conceptually like:

createTestingSessionTokens(payload)

It should return:

{
  accessToken,
  tokenExpires,
  refreshToken,
  refreshTokenExpires
}

Suggested env variable:

JWT_REFRESH_EXPIRES_IN: process.env.JWT_REFRESH_EXPIRES_IN ?? '30d'

Do not change the current access token lifetime in this issue unless necessary.

Tests should cover:

  • GroupAdmin receives refreshToken when creating a box
  • GroupAdmin receives refreshToken from POST /box/admin/signIn
  • Tester receives refreshToken from POST /box/claim-account
  • POST /auth/refresh returns new tokens for GroupAdmin
  • POST /auth/refresh returns new tokens for tester
  • Refreshed GroupAdmin access token works with BoxAuthGuard
  • Refreshed tester access token works with BoxAuthGuard
  • Access token cannot be used as a refresh token
  • Invalid refresh token returns 401
  • Expired refresh token returns 401
  • Refresh token with missing box_id returns 401
  • Refresh token with missing groupAdmin returns 401
  • Refresh token with stale tokenVersion returns 401

Backward compatibility requirement:

  • Existing frontend must continue working if it ignores refreshToken and refreshTokenExpires.
  • No existing response fields should be removed or renamed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

featureNew feature to add

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions