Feat/refresh tokens#62
Merged
Merged
Conversation
- Add RefreshToken entity with hashed token storage, expiry, and revocation - Add RefreshTokenService: create, validate-and-rotate, revoke, revoke-all - POST /api/auth/refresh: validates refresh token, rotates it, returns new pair - POST /api/auth/logout: revokes the refresh token server-side - Login, AcceptInvite, CompleteProfile now issue real refresh tokens - Shorten access token lifetime from 24h to 60 min (refresh token: 30 days) - Frontend: 401 auto-refresh interceptor in apiClient with concurrent-request dedup - Frontend: useLogout calls server logout before clearing local state - EF Core migration: AddRefreshTokens Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds first-class refresh-token authentication to the VMan backend and frontend, while also updating the committed Kiota-generated Immich client to a newer OpenAPI spec snapshot.
Changes:
- Introduces persisted refresh tokens (DB model + EF migration) and backend refresh/logout endpoints plus refresh-token service.
- Updates frontend auth state + API client to automatically refresh access tokens on 401s and to revoke refresh tokens on logout.
- Regenerates/updates the Immich Kiota client (new endpoints/models + various ID types moving from
stringtoGuid).
Reviewed changes
Copilot reviewed 117 out of 118 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| VideoManager/VManBackendInfrastructureImmichGenerated/Workflows/Item/WorkflowsItemRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Users/Me/Preferences/PreferencesRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Users/Me/MeRequestBuilder.cs | Adds CalendarHeatmap sub-builder and deprecates PUT helpers. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Users/Me/CalendarHeatmap/CalendarHeatmapRequestBuilder.cs | Adds new request builder for /users/me/calendar-heatmap. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Tags/Item/TagsItemRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Stacks/Item/StacksItemRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Sessions/Item/SessionsItemRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/People/Item/PeopleItemRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/WorkflowType.cs | Removes an enum member no longer present in the spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/WorkflowTrigger.cs | Updates enum members to match updated workflow triggers. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/WorkflowResponseDto.cs | Changes workflow Id to Guid? and updates serialization/deserialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/UserPreferencesUpdateDto.cs | Adds RecentlyAdded preference update model field. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/UserPreferencesResponseDto.cs | Adds RecentlyAdded preference response model field. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/UsageByUserDto.cs | Changes UserId to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/UpdateAssetDto.cs | Updates rating documentation to reflect new semantics. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/TagResponseDto.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SystemConfigNightlyTasksDto.cs | Clarifies StartTime format in documentation. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SystemConfigNewVersionCheckDto.cs | Adds Channel (release channel) configuration support. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SystemConfigJobDto.cs | Adds IntegrityCheck job settings support. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SystemConfigIntegrityJob.cs | Adds integrity job configuration model. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SystemConfigIntegrityChecksumJob.cs | Adds integrity checksum job configuration model. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SystemConfigIntegrityChecks.cs | Adds integrity checks configuration model group. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SystemConfigFFmpegRealtimeDto.cs | Adds real-time FFmpeg/HLS transcoding config model. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SystemConfigFFmpegDto.cs | Adds Realtime FFmpeg configuration section. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SystemConfigDto.cs | Adds IntegrityChecks into system config DTO. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SyncRequestType.cs | Adds AssetOcrV1 request type enum value. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SyncEntityType.cs | Adds OCR entity and delete entity enum values. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/StackResponseDto.cs | Changes IDs to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SharedLinkResponseDto.cs | Changes IDs to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SharedLinkEditDto.cs | Removes ChangeExpiryTime per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SessionResponseDto.cs | Changes session Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/SessionCreateResponseDto.cs | Changes session Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/ServerVersionResponseDto.cs | Adds Prerelease version field. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/ServerVersionHistoryResponseDto.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/ServerFeaturesDto.cs | Adds RealtimeTranscoding feature flag. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/ServerConfigDto.cs | Adds MinFaces server config field. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/ReleaseChannel.cs | Adds new ReleaseChannel enum. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/RecentlyAddedUpdate.cs | Adds recently-added preferences update model. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/RecentlyAddedResponse.cs | Adds recently-added preferences response model. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/QueuesResponseLegacyDto.cs | Adds IntegrityCheck queue status. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/QueueName.cs | Adds IntegrityCheck queue name enum value. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/PluginResponseDto.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/PersonResponseDto.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/PeopleUpdateItem.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/PeopleUpdate.cs | Adds MinimumFaces to people configuration update model. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/PeopleResponse.cs | Adds MinimumFaces to people configuration response model. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/NotificationDto.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/MemoryResponseDto.cs | Changes Id/OwnerId to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/MapMarkerResponseDto.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/ManualJobName.cs | Adds integrity-related manual job names. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/LoginResponseDto.cs | Changes UserId to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/LibraryResponseDto.cs | Changes Id/OwnerId to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/JobName.cs | Adds HLS cleanup + integrity-related job names. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/IntegrityReportSummaryResponseDto.cs | Adds integrity summary response DTO. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/IntegrityReportResponseDto.cs | Adds paged integrity report response DTO. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/IntegrityReportResponseDto_items.cs | Adds integrity report item DTO. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/IntegrityReport.cs | Adds integrity report type enum. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/DuplicateResponseDto.cs | Changes DuplicateId to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/DownloadArchiveInfo.cs | Changes AssetIds to List<Guid?> and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/CreateProfileImageResponseDto.cs | Changes UserId to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/ContributorCountResponseDto.cs | Changes UserId to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/CalendarHeatmapType.cs | Adds calendar heatmap type enum. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/CalendarHeatmapResponseDto.cs | Adds calendar heatmap response DTO. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/CalendarHeatmapResponseDto_series.cs | Adds calendar heatmap series DTO. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/BulkIdResponseDto.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/AssetStackResponseDto.cs | Changes stack IDs to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/AssetResponseDto.cs | Changes key IDs to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/AssetMetadataBulkResponseDto.cs | Changes AssetId to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/AssetMediaResponseDto.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/AssetIdsResponseDto.cs | Changes AssetId to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/AssetBulkUploadCheckResult.cs | Changes AssetId to Guid? and clarifies Id meaning. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/AssetBulkUploadCheckItem.cs | Clarifies Id documentation to indicate client-side identifier. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/AssetBulkUpdateDto.cs | Fixes time-offset doc + updates rating documentation. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/ApiKeyResponseDto.cs | Changes Id to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Models/AlbumResponseDto.cs | Changes album IDs to Guid? and updates parsing/serialization. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Memories/Item/MemoriesItemRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Libraries/Item/LibrariesItemRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/kiota-lock.json | Updates Kiota lock hash/version to reflect regenerated client. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Assets/Item/Video/VideoRequestBuilder.cs | Adds Stream sub-builder for video streaming endpoints. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Assets/Item/Video/StreamNamespace/StreamRequestBuilder.cs | Adds streaming request builder root under /assets/{id}/video/stream. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Assets/Item/Video/StreamNamespace/MainM3u8/MainM3u8RequestBuilder.cs | Adds request builder for HLS main playlist. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Assets/Item/Video/StreamNamespace/Item/WithSessionItemRequestBuilder.cs | Adds request builder for streaming session resources (delete + variants). |
| VideoManager/VManBackendInfrastructureImmichGenerated/Assets/Item/Video/StreamNamespace/Item/Item/WithVariantIndexItemRequestBuilder.cs | Adds request builder for variant-level resources. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Assets/Item/Video/StreamNamespace/Item/Item/PlaylistM3u8/PlaylistM3u8RequestBuilder.cs | Adds request builder for HLS media playlist per variant. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Assets/Item/Video/StreamNamespace/Item/Item/Item/WithFilenameItemRequestBuilder.cs | Adds request builder for streaming init/segment downloads. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Assets/Item/AssetsItemRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Assets/AssetsRequestBuilder.cs | Marks bulk PUT helper methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/ApiKeys/Item/ApiKeysItemRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Admin/Users/Item/UsersItemRequestBuilder.cs | Adds admin user CalendarHeatmap sub-builder and deprecates PUT helpers. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Admin/Users/Item/Preferences/PreferencesRequestBuilder.cs | Marks PUT request builder methods as obsolete per updated spec. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Admin/Users/Item/CalendarHeatmap/CalendarHeatmapRequestBuilder.cs | Adds admin calendar heatmap request builder for a user. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Admin/Integrity/Summary/SummaryRequestBuilder.cs | Adds request builder for integrity summary endpoint. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Admin/Integrity/Report/Item/ItemRequestBuilder.cs | Adds request builder for integrity report item operations. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Admin/Integrity/Report/Item/FileNamespace/FileRequestBuilder.cs | Adds request builder for downloading integrity report files. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Admin/Integrity/Report/Item/CsvEscaped/CsvRequestBuilder.cs | Adds request builder for exporting integrity report CSV. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Admin/Integrity/IntegrityRequestBuilder.cs | Adds top-level integrity request builder. |
| VideoManager/VManBackendInfrastructureImmichGenerated/Admin/AdminRequestBuilder.cs | Wires new Integrity subtree into admin request builder. |
| VideoManager/VManBackend/Program.cs | Registers refresh-token service in DI (but needs handler registration updates). |
| VideoManager/VManBackend/Migrations/ApplicationDbContextModelSnapshot.cs | Updates EF snapshot to include refresh tokens. |
| VideoManager/VManBackend/Migrations/20260706194641_AddRefreshTokens.cs | Adds migration to create RefreshTokens table and indexes. |
| VideoManager/VManBackend/Infrastructure/Authentication/RefreshTokenService.cs | Implements refresh token creation, rotation, and revocation. |
| VideoManager/VManBackend/Infrastructure/Authentication/JwtService.cs | Clarifies default access token expiration comment. |
| VideoManager/VManBackend/Features/Collections/ExportCollectionToShotcut.cs | Refactors to avoid concurrent DbContext access by batching DB reads. |
| VideoManager/VManBackend/Features/Authentication/RefreshTokens.cs | Adds mediator handler for rotating refresh tokens and issuing new access tokens. |
| VideoManager/VManBackend/Features/Authentication/Logout.cs | Adds mediator handler to revoke a refresh token on logout. |
| VideoManager/VManBackend/Features/Authentication/Login.cs | Issues a refresh token on login and stops reusing access token as refresh token. |
| VideoManager/VManBackend/Features/Authentication/CompleteProfile.cs | Issues a refresh token when profile completion returns new tokens. |
| VideoManager/VManBackend/Features/Authentication/AcceptInvite.cs | Issues a refresh token when accepting an invite (auto-login). |
| VideoManager/VManBackend/Endpoints/AuthEndpoints.cs | Adds /refresh and /logout endpoints. |
| VideoManager/VManBackend/Common/Models/RefreshToken.cs | Adds refresh token persistence model with active/expired/revoked helpers. |
| VideoManager/VManBackend/Common/Data/ApplicationDbContext.cs | Adds DbSet<RefreshToken> and entity configuration. |
| VideoManager/VManBackend/appsettings.json | Sets access token expiry default to 60 minutes and adds refresh token expiry days. |
| video-manager-frontend/src/lib/store/authStore.ts | Adds refresh token integration with API client and auth-clearing callback. |
| video-manager-frontend/src/lib/hooks/useAuth.ts | Updates logout flow to revoke refresh token server-side before clearing auth. |
| video-manager-frontend/src/lib/api/client.ts | Adds automatic refresh-on-401 logic, refresh concurrency guard, and logout call. |
Files not reviewed (1)
- VideoManager/VManBackend/Migrations/20260706194641_AddRefreshTokens.Designer.cs: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
74
to
77
| // Add Services | ||
| builder.Services.AddScoped<IJwtService, JwtService>(); | ||
| builder.Services.AddScoped<IRefreshTokenService, RefreshTokenService>(); | ||
| builder.Services.AddHttpContextAccessor(); // Required for getting current user in handlers |
Comment on lines
+39
to
+54
| public async Task<RefreshToken?> ValidateAndRotateAsync(string token, CancellationToken cancellationToken = default) | ||
| { | ||
| var hash = HashToken(token); | ||
| var stored = await db.RefreshTokens | ||
| .Include(t => t.User) | ||
| .FirstOrDefaultAsync(t => t.TokenHash == hash, cancellationToken); | ||
|
|
||
| if (stored == null || !stored.IsActive) | ||
| return null; | ||
|
|
||
| // Revoke the used token (rotation) | ||
| stored.RevokedAt = DateTime.UtcNow; | ||
| await db.SaveChangesAsync(cancellationToken); | ||
|
|
||
| return stored; | ||
| } |
Comment on lines
+56
to
+68
| // Batch fetch all item details in a single DB query to avoid concurrent DbContext access | ||
| var providerItemIds = orderedItems.Select(ci => ci.ProviderItemId).ToList(); | ||
| var providerNames = orderedItems.Select(ci => ci.ProviderName).Distinct().ToList(); | ||
|
|
||
| var dbItems = await db.Items | ||
| .Where(i => providerNames.Contains(i.ProviderName) && providerItemIds.Contains(i.ProviderItemId)) | ||
| .Select(i => new { i.ProviderName, i.ProviderItemId, i.Type, i.OriginalFileName }) | ||
| .ToListAsync(cancellationToken); | ||
|
|
||
| var matchedItems = orderedItems | ||
| .Select(ci => dbItems.FirstOrDefault(i => i.ProviderName == ci.ProviderName && i.ProviderItemId == ci.ProviderItemId)) | ||
| .Where(i => i != null) | ||
| .ToList(); |
- Add VManBackend.Tests project to solution and branch (was only in master) - Add ci.yml workflow to branch so PR CI runs correctly - Update LoginTests to pass StubRefreshTokenService to Login.Handler - Add StubRefreshTokenService test helper implementing IRefreshTokenService - Restore IsNullOrWhiteSpace blank-key validation in JwtService (was broken by accidental ?? replacement, needed by JwtServiceTests) - Assert response.RefreshToken is non-empty in the success test case All 24 tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Register the missing RefreshTokens and Logout mediator handlers in Program.cs (endpoints were dispatching to handlers that were never added to DI, which would fail at runtime). Also make refresh-token rotation atomic via a conditional ExecuteUpdateAsync so two concurrent refresh requests can't both rotate the same token.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.