[GH-ISSUE #37] [Bug]: TubeArchivist-JF-Plugin: Authorization Header Not Applied Correctly #29

Closed
opened 2026-03-23 20:35:09 +00:00 by mirror · 1 comment
Owner

Originally created by @mattkduran on GitHub (Mar 3, 2025).
Original GitHub issue: https://github.com/tubearchivist/tubearchivist-jf-plugin/issues/37

I've read the documentation

Operating System

Linux

Your Bug Report

Describe the bug

The plugin is not properly setting the Authorization header when communicating with TubeArchivist, resulting in 403 Forbidden errors when trying to access API endpoints like /api/video/{video_id}/progress/.
Steps to Reproduce

Install the TubeArchivist-JF-Plugin in Jellyfin
Configure the plugin with:

TubeArchivist URL: http://192.168.0.8:8582/
Valid API token (which works with curl commands)

Try to sync watch status or video progress between Jellyfin and TubeArchivist

Expected Behavior

The plugin should successfully authenticate with the TubeArchivist API and sync watch status and progress.

Actual Behavior

The plugin reports "Forbidden" (403) errors in the logs when trying to access TubeArchivist API endpoints:

[2025-03-02 20:57:45.262 -08:00] [INF] [38] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Ping..."
[2025-03-02 20:57:45.262 -08:00] [INF] [38] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Ping..."
[2025-03-02 20:57:45.269 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/ping/: Forbidden"

TubeArchivist logs confirm the 403 errors:

[pid: 341|app: 0|req: 22925/22925] 192.168.0.8 () {32 vars in 461 bytes} [Sun Mar 2 21:04:47 2025] GET /api/video/a3zXdmWpYPI/progress/ => generated 59 bytes in 2 msecs (HTTP/1.1 403) 8 headers in 276 bytes (1 switches on core 0)
[pid: 341|app: 0|req: 22926/22926] 192.168.0.8 () {32 vars in 461 bytes} [Sun Mar 2 21:04:47 2025] GET /api/video/lVq4UEMOH-8/progress/ => generated 59 bytes in 3 msecs (HTTP/1.1 403) 8 headers in 276 bytes (1 switches on core 0)
[pid: 341|app: 0|req: 22927/22927] 192.168.0.8 () {32 vars in 461 bytes} [Sun Mar 2 21:04:47 2025] GET /api/video/m3ysIQZ7iKY/progress/ => generated 59 bytes in 3 msecs (HTTP/1.1 403) 8 headers in 276 bytes (1 switches on core 0)

However, using the exact same URL and token with curl works correctly:

curl -v http://192.168.0.8:8582/api/ping/ -H "Authorization: Token xxxx"
{"response":"pong","user":1,"version":"v0.4.13"}

Steps To Reproduce

  1. Install tubearchivist-jf-plugin using the manifest.json url provided in the github repository
  2. Enter URL and Auth token into fields, click Save Settings
  3. Confirm that the auth token is valid by running curl example above
  4. Go to Scheduled Tasks and choose either JFToTubeArchivistProgressSyncTask or TATToJellyfinProgressSyncTask
  5. Check Jellyfin logs, you should see 403 errors present
  6. Restart Jellyfin service, go back and run scheduled tasks, you should see the task successfully start without issue now

Root Cause

Looking at the plugin code, I found an initialization issue. In Plugin.cs, the authorization header is set during construction:

HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Token", Instance?.Configuration.TubeArchivistApiKey);

github.com/tubearchivist/tubearchivist-jf-plugin@ab96b227a1/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs (L60)

But Instance is null at this point because it hasn't been assigned yet (Instance = this happens earlier in the constructor). This means the authorization header is created with an empty token value.

Proposed Fix

Move the header initialization after the Instance is set, and create a method to update the header whenever the API key changes:

// In Plugin.cs constructor
Instance = this; // Set Instance first
// ... other initialization
UpdateAuthorizationHeader(); // Call this after Instance is set

// Add this new method
public void UpdateAuthorizationHeader()
{
    if (!string.IsNullOrEmpty(Configuration.TubeArchivistApiKey))
    {
        HttpClient.DefaultRequestHeaders.Authorization = 
            new System.Net.Http.Headers.AuthenticationHeaderValue("Token", Configuration.TubeArchivistApiKey);
        Logger.LogInformation("Updated Authorization header with API key");
    }
    else
    {
        Logger.LogWarning("No TubeArchivist API key configured");
    }
}

Then modify PluginConfiguration.cs to call this method when the API key is updated:

// In TubeArchivistApiKey setter
set
{
    _tubeArchivistApiKey = value;
    Plugin.Instance?.LogTAApiConnectionStatus();
    Plugin.Instance?.UpdateAuthorizationHeader(); // Add this line
}

Workaround

Restart the entire Jellyfin server after changing the API key in the plugin settings. This forces the HttpClient to be recreated with the proper token.

Environment

Jellyfin version: 10.10.6
TubeArchivist version: v0.4.13
TubeArchivist-JF-Plugin version: 1.3.4.0
Docker? Yes
OS/Environment: Ubuntu 20.04

Relevant Jellyfin log output

[2025-03-02 18:43:56.588 -08:00] [INF] [26] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Ping..."
[2025-03-02 18:43:56.591 -08:00] [INF] [26] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Ping..."
[2025-03-02 18:43:56.628 -08:00] [INF] [17] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/ping/: Forbidden"
[2025-03-02 18:43:56.632 -08:00] [FTL] [14] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "TubeArchivist API was unreachable!"
[2025-03-02 18:43:56.634 -08:00] [INF] [17] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/ping/: Forbidden"

####
[2025-03-02 18:46:15.222 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/video/rCJ0mR2WgtA/: Forbidden"
[2025-03-02 18:46:15.223 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Getting metadata for video:  (rCJ0mR2WgtA)"
[2025-03-02 18:46:15.224 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Received metadata: 
null"
[2025-03-02 18:46:15.278 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/channel/UC6LBo0GXFaUtf-mWccqfw-w/: Forbidden"
[2025-03-02 18:46:15.278 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Getting metadata for channel:  (UC6LBo0GXFaUtf-mWccqfw-w)"
[2025-03-02 18:46:15.279 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Received metadata: 
null"

###
[2025-03-02 19:06:06.873 -08:00] [INF] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: Starting Jellyfin->TubeArchivist playback progresses synchronization.
[2025-03-02 19:06:06.882 -08:00] [INF] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: Analyzing collection e59b3714-8e0f-f06f-0d35-b0c3c714e75c with name "Youtube"
[2025-03-02 19:06:07.029 -08:00] [INF] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: Found a total of 239 videos
[2025-03-02 19:06:07.062 -08:00] [FTL] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "POST /video/z1ykCc588Zw/progress returned Forbidden for video The Elon Musk Cheating Scandal with progress System.Progress`1[System.Double] seconds"
[2025-03-02 19:06:07.074 -08:00] [FTL] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "POST /watched returned Forbidden for video The Elon Musk Cheating Scandal (z1ykCc588Zw) with wacthed status False"
[2025-03-02 19:06:07.079 -08:00] [FTL] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "POST /video/jC9P4m8_NM0/progress returned Forbidden for video Sega Mega Drive 2 Restoration - I got scammed with progress System.Progress`1[System.Double] seconds"
[2025-03-02 19:06:07.083 -08:00] [FTL] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "POST /watched returned Forbidden for video Sega Mega Drive 2 Restoration - I got scammed (jC9P4m8_NM0) with wacthed status False"

Anything else?

No response

Originally created by @mattkduran on GitHub (Mar 3, 2025). Original GitHub issue: https://github.com/tubearchivist/tubearchivist-jf-plugin/issues/37 ### I've read the documentation - [x] I'm running the latest version of tubearchivist-jf-plugin. - [x] I have read the [how to open an issue](https://github.com/tubearchivist/tubearchivist/blob/master/CONTRIBUTING.md#how-to-open-an-issue) guide, particularly the [bug report](https://github.com/tubearchivist/tubearchivist/blob/master/CONTRIBUTING.md#bug-report) section. ### Operating System Linux ### Your Bug Report ## Describe the bug The plugin is not properly setting the Authorization header when communicating with TubeArchivist, resulting in 403 Forbidden errors when trying to access API endpoints like /api/video/{video_id}/progress/. Steps to Reproduce Install the TubeArchivist-JF-Plugin in Jellyfin Configure the plugin with: TubeArchivist URL: http://192.168.0.8:8582/ Valid API token (which works with curl commands) Try to sync watch status or video progress between Jellyfin and TubeArchivist ## Expected Behavior The plugin should successfully authenticate with the TubeArchivist API and sync watch status and progress. ## Actual Behavior The plugin reports "Forbidden" (403) errors in the logs when trying to access TubeArchivist API endpoints: ``` [2025-03-02 20:57:45.262 -08:00] [INF] [38] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Ping..." [2025-03-02 20:57:45.262 -08:00] [INF] [38] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Ping..." [2025-03-02 20:57:45.269 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/ping/: Forbidden" ``` TubeArchivist logs confirm the 403 errors: ``` [pid: 341|app: 0|req: 22925/22925] 192.168.0.8 () {32 vars in 461 bytes} [Sun Mar 2 21:04:47 2025] GET /api/video/a3zXdmWpYPI/progress/ => generated 59 bytes in 2 msecs (HTTP/1.1 403) 8 headers in 276 bytes (1 switches on core 0) [pid: 341|app: 0|req: 22926/22926] 192.168.0.8 () {32 vars in 461 bytes} [Sun Mar 2 21:04:47 2025] GET /api/video/lVq4UEMOH-8/progress/ => generated 59 bytes in 3 msecs (HTTP/1.1 403) 8 headers in 276 bytes (1 switches on core 0) [pid: 341|app: 0|req: 22927/22927] 192.168.0.8 () {32 vars in 461 bytes} [Sun Mar 2 21:04:47 2025] GET /api/video/m3ysIQZ7iKY/progress/ => generated 59 bytes in 3 msecs (HTTP/1.1 403) 8 headers in 276 bytes (1 switches on core 0) ``` However, using the exact same URL and token with curl works correctly: ``` curl -v http://192.168.0.8:8582/api/ping/ -H "Authorization: Token xxxx" {"response":"pong","user":1,"version":"v0.4.13"} ``` ## Steps To Reproduce 1. Install tubearchivist-jf-plugin using the manifest.json url provided in the github repository 2. Enter URL and Auth token into fields, click Save Settings 3. Confirm that the auth token is valid by running curl example above 4. Go to Scheduled Tasks and choose either JFToTubeArchivistProgressSyncTask or TATToJellyfinProgressSyncTask 5. Check Jellyfin logs, you should see 403 errors present 6. Restart Jellyfin service, go back and run scheduled tasks, you should see the task successfully start without issue now ## Root Cause Looking at the plugin code, I found an initialization issue. In Plugin.cs, the authorization header is set during construction: ``` HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Token", Instance?.Configuration.TubeArchivistApiKey); ``` https://github.com/tubearchivist/tubearchivist-jf-plugin/blob/ab96b227a146d66e93c54490376bd824faefea7d/Jellyfin.Plugin.TubeArchivistMetadata/Plugin.cs#L60 But Instance is null at this point because it hasn't been assigned yet (Instance = this happens earlier in the constructor). This means the authorization header is created with an empty token value. ## Proposed Fix Move the header initialization after the Instance is set, and create a method to update the header whenever the API key changes: ``` // In Plugin.cs constructor Instance = this; // Set Instance first // ... other initialization UpdateAuthorizationHeader(); // Call this after Instance is set // Add this new method public void UpdateAuthorizationHeader() { if (!string.IsNullOrEmpty(Configuration.TubeArchivistApiKey)) { HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Token", Configuration.TubeArchivistApiKey); Logger.LogInformation("Updated Authorization header with API key"); } else { Logger.LogWarning("No TubeArchivist API key configured"); } } ``` Then modify PluginConfiguration.cs to call this method when the API key is updated: ``` // In TubeArchivistApiKey setter set { _tubeArchivistApiKey = value; Plugin.Instance?.LogTAApiConnectionStatus(); Plugin.Instance?.UpdateAuthorizationHeader(); // Add this line } ``` ## Workaround Restart the entire Jellyfin server after changing the API key in the plugin settings. This forces the HttpClient to be recreated with the proper token. Environment Jellyfin version: 10.10.6 TubeArchivist version: v0.4.13 TubeArchivist-JF-Plugin version: 1.3.4.0 Docker? Yes OS/Environment: Ubuntu 20.04 ### Relevant Jellyfin log output ```shell [2025-03-02 18:43:56.588 -08:00] [INF] [26] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Ping..." [2025-03-02 18:43:56.591 -08:00] [INF] [26] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Ping..." [2025-03-02 18:43:56.628 -08:00] [INF] [17] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/ping/: Forbidden" [2025-03-02 18:43:56.632 -08:00] [FTL] [14] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "TubeArchivist API was unreachable!" [2025-03-02 18:43:56.634 -08:00] [INF] [17] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/ping/: Forbidden" #### [2025-03-02 18:46:15.222 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/video/rCJ0mR2WgtA/: Forbidden" [2025-03-02 18:46:15.223 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Getting metadata for video: (rCJ0mR2WgtA)" [2025-03-02 18:46:15.224 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Received metadata: null" [2025-03-02 18:46:15.278 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "http://192.168.0.8:8582/api/channel/UC6LBo0GXFaUtf-mWccqfw-w/: Forbidden" [2025-03-02 18:46:15.278 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Getting metadata for channel: (UC6LBo0GXFaUtf-mWccqfw-w)" [2025-03-02 18:46:15.279 -08:00] [INF] [28] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "Received metadata: null" ### [2025-03-02 19:06:06.873 -08:00] [INF] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: Starting Jellyfin->TubeArchivist playback progresses synchronization. [2025-03-02 19:06:06.882 -08:00] [INF] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: Analyzing collection e59b3714-8e0f-f06f-0d35-b0c3c714e75c with name "Youtube" [2025-03-02 19:06:07.029 -08:00] [INF] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: Found a total of 239 videos [2025-03-02 19:06:07.062 -08:00] [FTL] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "POST /video/z1ykCc588Zw/progress returned Forbidden for video The Elon Musk Cheating Scandal with progress System.Progress`1[System.Double] seconds" [2025-03-02 19:06:07.074 -08:00] [FTL] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "POST /watched returned Forbidden for video The Elon Musk Cheating Scandal (z1ykCc588Zw) with wacthed status False" [2025-03-02 19:06:07.079 -08:00] [FTL] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "POST /video/jC9P4m8_NM0/progress returned Forbidden for video Sega Mega Drive 2 Restoration - I got scammed with progress System.Progress`1[System.Double] seconds" [2025-03-02 19:06:07.083 -08:00] [FTL] [34] Jellyfin.Plugin.TubeArchivistMetadata.Plugin: "POST /watched returned Forbidden for video Sega Mega Drive 2 Restoration - I got scammed (jC9P4m8_NM0) with wacthed status False" ``` ### Anything else? _No response_
Author
Owner

@DarkFighterLuke commented on GitHub (Mar 3, 2025):

Hi, you've done a great report of what happens and you actually fixed a very common bug. Feel free to submit a PR!

<!-- gh-comment-id:2694416552 --> @DarkFighterLuke commented on GitHub (Mar 3, 2025): Hi, you've done a great report of what happens and you actually fixed a very common bug. Feel free to submit a PR!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
tubearchivist/archived-tubearchivist-jf-plugin#29
No description provided.