Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 18, 2025

Implements a new internal interface for Tidal user authentication and playlist management accessible at /tidal for logged-in users.

<issue_title>Add logged-in internal interface for Tidal authentication and playlist selection</issue_title>

<issue_description>Build a quick interface (minimal styling, functional focus) as a new page in the TuneBridge webserver. This page should require users to be logged in. Provide logged-in users with the option to authenticate with Tidal, utilizing the token necessary to access their library and playlists.

Features:

  • Add a dedicated page requiring login.
  • Allow user authentication to Tidal from the page, storing the resulting token needed for future access to user library/playlists.
  • Present the user's list of playlists by name.
  • Let the user select a playlist (by name); do not perform any further actions (no playlist interaction or import/export).

Notes:

  • Prioritize completeness of authentication flow and basic playlist listing - do not refine UI or add extra playlist handling.
  • This feature is for internal/testing usage and can be "quick and dirty" for speed.
  • Future work may expand on playlist interactions after initial token access is proven functional.</issue_description>

Implementation Details

Features Implemented:

  • ✅ Dedicated login-required page at /tidal
  • ✅ OAuth 2.0 authorization code flow for Tidal user authentication
  • ✅ Token storage with automatic refresh capability
  • ✅ Playlist listing by name from user's Tidal account
  • ✅ Playlist selection UI with visual feedback
  • ✅ Navigation link added to header for authenticated users
  • ✅ Disconnect/reconnect functionality

Technical Changes:

  • Extended ApplicationUser model with three new fields: TidalAccessToken, TidalRefreshToken, TidalTokenExpiry
  • Created database migration AddTidalTokensToUser for token storage
  • Implemented TidalUserAuthHandler for OAuth authorization code flow with automatic token refresh
  • Added TidalUserAuthHandler to public properties of TidalCredentials class to support user authentication
  • Created TidalController with routes:
    • GET /tidal - Main page (requires authentication)
    • GET /tidal/connect - Initiates OAuth flow
    • GET /tidal/callback - Handles OAuth callback
    • POST /tidal/disconnect - Removes stored tokens
    • GET /tidal/playlists - Fetches user's playlists
  • Created responsive view page with playlist loading and selection UI
  • Updated navigation header to include Tidal link for authenticated users

Security Considerations:

  • All endpoints protected with [Authorize] attribute requiring user authentication
  • OAuth state parameter generated for CSRF protection
  • Automatic token refresh with 5-minute expiration buffer
  • Tokens stored in database (plaintext for internal testing - encryption recommended for production use)

This implementation prioritizes functional completeness for internal testing as specified in the requirements.

Original prompt

This section details on the original issue you should resolve

<issue_title>Add logged-in internal interface for Tidal authentication and playlist selection</issue_title>
<issue_description>Build a quick interface (minimal styling, functional focus) as a new page in the TuneBridge webserver. This page should require users to be logged in. Provide logged-in users with the option to authenticate with Tidal, utilizing the token necessary to access their library and playlists.

Features:

  • Add a dedicated page requiring login.
  • Allow user authentication to Tidal from the page, storing the resulting token needed for future access to user library/playlists.
  • Present the user's list of playlists by name.
  • Let the user select a playlist (by name); do not perform any further actions (no playlist interaction or import/export).

Notes:

  • Prioritize completeness of authentication flow and basic playlist listing - do not refine UI or add extra playlist handling.
  • This feature is for internal/testing usage and can be "quick and dirty" for speed.
  • Future work may expand on playlist interactions after initial token access is proven functional.</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI self-assigned this Nov 18, 2025
@tsmarvin
Copy link
Owner

Try again @copilot

[Route( "tidal/callback" )]
public async Task<IActionResult> Callback( [FromQuery] string? code, [FromQuery] string? error ) {
if (!string.IsNullOrEmpty( error )) {
_logger.LogError( "Tidal OAuth error: {Error}", error );

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.

Copilot Autofix

AI 16 days ago

To fix the problem, we need to sanitize the user-supplied error string before it is logged. Since the log entry is written as plain text, we should remove (or replace) newlines and other characters likely to disrupt log formatting. The simplest, safest method is to use String.Replace(Environment.NewLine, "") and also .Replace("\n", "") and .Replace("\r", "") for extra coverage. For clarity, the sanitized value should be used in the log entry instead of the raw user input.

This means:

  • In Callback, before logging, define a sanitized version of error (removing newlines).
  • Use the sanitized version in the logger call on line 72.

No other parts of the file need to change.

Suggested changeset 1
src/Web/Controllers/TidalController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/Web/Controllers/TidalController.cs b/src/Web/Controllers/TidalController.cs
--- a/src/Web/Controllers/TidalController.cs
+++ b/src/Web/Controllers/TidalController.cs
@@ -69,7 +69,8 @@
     [Route( "tidal/callback" )]
     public async Task<IActionResult> Callback( [FromQuery] string? code, [FromQuery] string? error ) {
         if (!string.IsNullOrEmpty( error )) {
-            _logger.LogError( "Tidal OAuth error: {Error}", error );
+            string sanitizedError = error.Replace("\r", "").Replace("\n", "");
+            _logger.LogError( "Tidal OAuth error: {Error}", sanitizedError );
             return RedirectToAction( "Index" );
         }
 
EOF
@@ -69,7 +69,8 @@
[Route( "tidal/callback" )]
public async Task<IActionResult> Callback( [FromQuery] string? code, [FromQuery] string? error ) {
if (!string.IsNullOrEmpty( error )) {
_logger.LogError( "Tidal OAuth error: {Error}", error );
string sanitizedError = error.Replace("\r", "").Replace("\n", "");
_logger.LogError( "Tidal OAuth error: {Error}", sanitizedError );
return RedirectToAction( "Index" );
}

Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Contributor Author

Copilot AI commented Nov 18, 2025

Try again @copilot

I've implemented the Tidal authentication and playlist selection interface. The feature includes:

OAuth Authentication Flow: Users can connect their Tidal account via OAuth 2.0 authorization code flow
Token Management: Access and refresh tokens are stored in the user profile with automatic refresh
Playlist Listing: Users can load and view their Tidal playlists by name
Playlist Selection: Users can select a playlist (highlighted in the UI)
Navigation: Added "Tidal" link in the header for authenticated users

Access the feature at /tidal after logging in.

The implementation is functional-focused as requested. Database migration AddTidalTokensToUser was created to store the OAuth tokens.

Note: Tokens are stored in plaintext in the database for this internal testing feature. For production use, token encryption should be added.

Commits: 4107093, 97d91e2

Copilot AI changed the title [WIP] Add logged-in interface for Tidal authentication and playlist selection Add logged-in interface for Tidal authentication and playlist selection Nov 18, 2025
Copilot finished work on behalf of tsmarvin November 18, 2025 22:12
@tsmarvin
Copy link
Owner

Can you rebase this off develop @copilot

Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

Can you rebase this off develop @copilot

I'm unable to perform a git rebase in this environment because force push is not available to me. To rebase this branch off develop, you would need to run locally:

git fetch origin develop
git checkout copilot/add-tidal-authentication-interface
git rebase origin/develop
git push --force-with-lease origin copilot/add-tidal-authentication-interface

Alternatively, if there are merge conflicts or updates needed from develop, I can help resolve those once the rebase is done manually.

Copilot finished work on behalf of tsmarvin November 26, 2025 07:59
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.

Add logged-in internal interface for Tidal authentication and playlist selection

2 participants