diff options
author | cglatot <[email protected]> | 2020-10-08 16:30:32 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-10-08 16:30:32 +0100 |
commit | e44b0d4e9174846af3fc36eb11277bf3f6c82e19 (patch) | |
tree | 6170e5facce3d74ef72574616e38491e63de8443 | |
parent | 521286237bed573e76f34f0c1d971387376d5fb1 (diff) | |
parent | 44898da825cf16985a88f3516df47453a6fdfed8 (diff) | |
download | pasta-1.5.0.tar.gz pasta-1.5.0.zip |
Merge pull request #27 from cglatot/proper-authentication-method1.5.0
Implement proper Plex login method
-rw-r--r-- | css/main.css | 8 | ||||
-rw-r--r-- | index.html | 24 | ||||
-rw-r--r-- | js/main.js | 202 |
3 files changed, 127 insertions, 107 deletions
diff --git a/css/main.css b/css/main.css index aeffe1c..582e92c 100644 --- a/css/main.css +++ b/css/main.css @@ -70,6 +70,14 @@ label, p { display: none; } +#new-pin-container { + display: none; +} + +#waitOnPinAuth { + display: none; +} + /*========================== MODALS ==========================*/ @@ -196,7 +196,7 @@ <div id="pinOrAuthBtns" class="btn-group btn-group-toggle" data-toggle="buttons"> <label class="btn btn-secondary active"> <input type="radio" name="pinOrAuth" value="showPinControls" id="showPinControls" autocomplete="off" - checked> PIN Authentication + checked> Plex Login </label> <label class="btn btn-secondary"> <input type="radio" name="pinOrAuth" value="showUrlControls" id="showUrlControls" autocomplete="off"> @@ -216,19 +216,16 @@ </button> </div> <!-- / WARNING BOX --> - <!-- PIN AUTHENTICATION --> - <div id="pin-auth-over-container" class="mt-4"> - <div id="new-pin-container"> - <p>Please go to <a href="https://www.plex.tv/pin" target="_blank">https://www.plex.tv/pin</a> and enter the following PIN:</p> - <div class="d-inline-flex flex-row align-items-center"> - <h1 id="pin-code-holder"></h1> - <div class="spinner-border spinner-border-sm text-warning ml-2" role="status" aria-hidden="true"></div> - </div> + <!-- PLEX AUTHENTICATION --> + <div id="pin-auth-over-container" class="row mt-4"> + <div id="new-pin-container" class="col pl-5 pr-5"> + <button id="loginWithPlexBtn" type="button" class="btn btn-secondary btn-lg btn-block" onclick="authenticateWithPlex()">Login with Plex</button> + <div id="waitOnPinAuth" class="spinner-border spinner-border-lg text-warning" role="status" aria-hidden="true"></div> </div> <div id="authed-pin-container"> - <p>You are authenticated via PIN. + <p>You are logged in as: <strong id="loggedInAs"></strong> <small id="forgetPinDetails"> - <a href="javascript:void(0)" onclick="forgetPinDetails()">Click here to logout.</a> + <a href="javascript:void(0)" class="ml-2" onclick="forgetPinDetails()">Click here to logout.</a> <i id="confirmForgetPin" class="fas fa-check" style="color: #28a745; font-size: 1.5em"></i> </small> </p> @@ -244,7 +241,7 @@ </div> </div> - <!-- / PIN AUTHENTICATION --> + <!-- / PLEX AUTHENTICATION --> <!-- URL / TOKEN AUTHENTICATION --> <div id="url-auth-over-container" class="mt-4"> <div class="form-group"> @@ -320,7 +317,6 @@ <div class="row mt-4"> <div class="col"> <h3>Plex Libraries</h3> - <small>Choose <strong>only</strong> episodic content (TV Shows, Anime, etc). This does not work for Movies.</small> <div class="table-responsive"> <table id="libraryTable" class="table table-hover mt-3"> <thead> @@ -489,7 +485,7 @@ <!-- MOVIE NAME --> <div id="movieNamePlaceholder" class="row mt-4"> <div class="col"> - <h2>Baby Driver</h2> + <h2></h2> </div> </div> <!-- / MOVIE NAME --> @@ -1,7 +1,7 @@ // Variables for the Authorised Devices card var clientIdentifier; // UID for the device being used var plexProduct = "PASTA"; // X-Plex-Product - Application name -var pastaVersion = "1.4.1"; // X-Plex-Version - Application version +var pastaVersion = "1.5.0"; // X-Plex-Version - Application version var pastaPlatform; // X-Plex-Platform - Web Browser var pastaPlatformVersion; // X-Plex-Platform-Version - Web Browser version var deviceInfo; // X-Plex-Device - Operation system? @@ -28,31 +28,25 @@ $(document).ready(() => { // Enable Tooltips $('.helpButtons, #titleLogo').tooltip(); - // Enable history tracking for tabs $('a[data-toggle="tab"]').historyTabs(); // Check if the page was loaded locally or over http and warn them about the value of https if ((location.protocol == "http:") || (location.protocol == "file:")) { - if (localStorage.showHttpAlert == 'false') { - - } + if (localStorage.showHttpAlert == 'false') {} else { $("#insecureWarning").show(); } } // Check if they have permanently dismissed the Login Info alert - if (localStorage.showLoginInfoAlert == 'false') { - console.log("infoalert is false"); - } + if (localStorage.showLoginInfoAlert == 'false') {} else { $("#loginInfoAlert").show(); } // Override the close mechanism to not show the loginInfoAlert $("#loginInfoAlertClose").on("click", () => { - console.log('Entered the click for close'); hideLoginInfoAlertForever(); }); @@ -60,7 +54,7 @@ $(document).ready(() => { try { let browserInfo = getBrowser(); // Set the clientID, this might get overridden if one is saved to localstorage - clientIdentifier = `PASTA-cglatot-${Date.now()}-${Math.round(Math.random() * 1000)}`; + clientIdentifier = localStorage.clientIdentifier || `PASTA-cglatot-${Date.now()}-${Math.round(Math.random() * 1000)}`; // Set the OS deviceInfo = browserInfo.os || ""; // Set the web browser and version @@ -72,7 +66,7 @@ $(document).ready(() => { console.log(e); // Fallback values // Set the clientID, this might get overridden if one is saved to localstorage - clientIdentifier = `PASTA-cglatot-${Date.now()}-${Math.round(Math.random() * 1000)}`; + clientIdentifier = localStorage.clientIdentifier || `PASTA-cglatot-${Date.now()}-${Math.round(Math.random() * 1000)}`; // Set the OS deviceInfo = ""; // Set the web browser and version @@ -86,7 +80,6 @@ $(document).ready(() => { $('#plexUrl').on("input", () => { validateEnableConnectBtn('plexUrl'); }); - // Validation listeners on the Plex Token Input $('#plexToken').on("input", () => { validateEnableConnectBtn('plexToken'); @@ -97,47 +90,117 @@ $(document).ready(() => { toggleAuthPages(this.value); }); + // Check whether they want to connect using a local IP or not if (localStorage.useLocalAddress == "true") { $('#connectViaLocalAddress').prop('checked', true); } else { $('#connectViaLocalAddress').prop('checked', false); } - if (!localStorage.isPinAuth) { - // Not using PIN auth, so must be using url / token - if (localStorage.plexUrl && localStorage.plexUrl !== "") { - plexUrl = localStorage.plexUrl; - $('#plexUrl').val(localStorage.plexUrl); - validateEnableConnectBtn('plexUrl'); - $('#forgetDivider, #forgetDetailsSection').show(); + // Check if there is a stored Auth Token + if (localStorage.pinAuthToken) { + checkIfAuthTokenIsValid(); + } else { + $('#new-pin-container').show(); + } +}); + +// Checks if the generated token is valid +function checkIfAuthTokenIsValid() { + $.ajax({ + "url": `https://plex.tv/api/v2/user`, + "headers": { + "accept": "application/json", + "X-Plex-Client-Identifier": clientIdentifier, + "X-Plex-Token": localStorage.pinAuthToken, + "X-Plex-Product": plexProduct, + "X-Plex-Version": pastaVersion, + "X-Plex-Platform": pastaPlatform, + "X-Plex-Platform-Version": pastaPlatformVersion, + "X-Plex-Device": deviceInfo, + "X-Plex-Device-Name": deviceName + }, + "method": "GET", + "success": (data) => { + console.log(data); + plexToken = localStorage.pinAuthToken; + $('#new-pin-container').hide(); + $('#authed-pin-container').show(); + $('#loggedInAs').text(data.username); + getServers(); + }, + "error": (data, statusText, xhr) => { + console.log("ERROR L121"); + console.log(data.status); + if (data.status == 401) { + // Auth Token has expired + localStorage.removeItem('isPinAuth'); + localStorage.removeItem('pinAuthToken'); + localStorage.removeItem('useLocalAddress'); + $('#new-pin-container').show(); + } } - if (localStorage.plexToken && localStorage.plexToken !== "") { - plexToken = localStorage.plexToken; - $('#plexToken').val(localStorage.plexToken); - validateEnableConnectBtn('plexToken'); - $('#forgetDivider, #forgetDetailsSection').show(); + }); +} + +function authenticateWithPlex() { + // Generate a PIN code to get the URL + $.ajax({ + "url": `https://plex.tv/api/v2/pins`, + "headers": { + "accept": "application/json", + "strong": "true", + "X-Plex-Client-Identifier": clientIdentifier, + "X-Plex-Product": plexProduct, + "X-Plex-Version": pastaVersion, + "X-Plex-Platform": pastaPlatform, + "X-Plex-Platform-Version": pastaPlatformVersion, + "X-Plex-Device": deviceInfo, + "X-Plex-Device-Name": deviceName + }, + "method": "POST", + "success": (data) => { + // For some reason auth doesn't work unless you choose Plex Web as the product id + let plexProductTemp = encodeURIComponent("Plex Web"); + let authAppUrl = `https://app.plex.tv/auth#?clientID=${clientIdentifier}&code=${data.code}&context%5Bdevice%5D%5Bproduct%5D=${plexProductTemp}`; + + $('#waitOnPinAuth').show(); + $('#loginWithPlexBtn').hide(); + window.open(authAppUrl, 'PlexSignIn', 'width=800,height=730'); + backOffTimer = Date.now(); + listenForValidPincode(data.id, clientIdentifier, data.code); + }, + "error": (data) => { + console.log("ERROR L121"); + console.log(data); } + }); +} - // Display a PIN code for that authentication as well +function listenForValidPincode(pinId, clientId, pinCode) { + let currentTime = Date.now(); + if ((currentTime - backOffTimer)/1000 < 10) { $.ajax({ - "url": `https://plex.tv/pins.xml`, + "url": `https://plex.tv/api/v2/pins/${pinId}`, "headers": { - "X-Plex-Client-Identifier": clientIdentifier, - "X-Plex-Product": plexProduct, - "X-Plex-Version": pastaVersion, - "X-Plex-Platform": pastaPlatform, - "X-Plex-Platform-Version": pastaPlatformVersion, - "X-Plex-Device": deviceInfo, - "X-Plex-Device-Name": deviceName + "accept": "application/json", + "code": pinCode, + "X-Plex-Client-Identifier": clientId, }, - "method": "POST", + "method": "GET", "success": (data) => { - let pinId = $(data).find('id')[0].innerHTML; - let pinCode = $(data).find('code')[0].innerHTML; - - $('#pin-code-holder').html(pinCode); - backOffTimer = Date.now(); - listenForValidPincode(pinId); + if (data.authToken != null) { + $('#waitOnPinAuth').hide(); + localStorage.clientIdentifier = clientIdentifier; + localStorage.isPinAuth = true; + localStorage.pinAuthToken = data.authToken; + plexToken = data.authToken; + checkIfAuthTokenIsValid(); + } else { + setTimeout(() => { + listenForValidPincode(pinId, clientId, pinCode); + }, 3000); // Check every 3 seconds + } }, "error": (data) => { console.log("ERROR L121"); @@ -145,15 +208,12 @@ $(document).ready(() => { } }); } else { - $('#new-pin-container').hide(); - $('#authed-pin-container').show(); - // We are using Pin Auth - clientIdentifier = localStorage.clientIdentifier; - plexToken = localStorage.pinAuthToken; - getServers(); + $('#new-pin-container').html(' <p><i class="far fa-times-circle mr-2" style="color: #e5a00d; font-size: 1.5em; vertical-align: middle;"></i>Login timed out. \ + Please <a href="javascript:void(0)" onclick="window.location.reload()">refresh the page</a> and ensure your popup blocker is disabled.</p>'); } -}); +} +// Toggle between the authentication methods function toggleAuthPages(value) { if (value == 'showPinControls') { $('#pin-auth-over-container').show(); @@ -164,7 +224,7 @@ function toggleAuthPages(value) { if (localStorage.isPinAuth) { $("#authWarningText").html(`<div class="alert alert-warning alert-dismissible fade show mt-3" role="alert"> - <strong>Warning:</strong> You are currently signed in via PIN. Please <a href="javascript:void(0)" onclick="forgetPinDetails()">sign out of PIN</a> before proceeding to connect using a URL / IP address. + <strong>Warning:</strong> You are currently signed in via Plex. Please <a href="javascript:void(0)" onclick="forgetPinDetails()">sign out of Plex</a> before proceeding to connect using a URL / IP address. <button type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">×</span> </button> @@ -173,56 +233,13 @@ function toggleAuthPages(value) { } } -function listenForValidPincode (pinId) { - let currentTime = Date.now(); - if ((currentTime - backOffTimer)/1000 < 180) { - $.ajax({ - "url": `https://plex.tv/pins/${pinId}`, - "headers": { - "X-Plex-Client-Identifier": clientIdentifier, - "X-Plex-Product": plexProduct, - "X-Plex-Version": pastaVersion, - "X-Plex-Platform": pastaPlatform, - "X-Plex-Platform-Version": pastaPlatformVersion, - "X-Plex-Device": deviceInfo, - "X-Plex-Device-Name": deviceName - }, - "method": "GET", - "success": (data) => { - if (data.pin.auth_token != null) { - plexToken = data.pin.auth_token; - // Save to local storage - localStorage.isPinAuth = true; - localStorage.pinAuthToken = plexToken; - localStorage.clientIdentifier = clientIdentifier; - $('#new-pin-container').hide(); - $('#authed-pin-container').show(); - getServers(); - } else { - setTimeout(() => { - listenForValidPincode(pinId); - }, 5000); - } - }, - "error": (data) => { - console.log("ERROR L186"); - console.log(data); - return; - } - }); - } else { - $('#new-pin-container').html(' <p><i class="far fa-times-circle mr-2" style="color: #e5a00d; font-size: 1.5em; vertical-align: middle;"></i>PIN entry timed out. \ - Please <a href="javascript:void(0)" onclick="window.location.reload()">refresh the page</a> to get a new PIN.</p>'); - } -} - // Called when the "connect using local IP" checkbox is toggled // Refreshes the page and updates the variable for whether it should use the local address or not function useLocalAddress (checkbox) { if (checkbox.checked) { localStorage.useLocalAddress = "true"; } else { - localStorage.useLocalAddress = "false"; + localStorage.removeItem('useLocalAddress'); } window.location.reload(); } @@ -358,7 +375,6 @@ function forgetDetails() { function forgetPinDetails() { localStorage.removeItem('isPinAuth'); localStorage.removeItem('pinAuthToken'); - localStorage.removeItem('clientIdentifier'); localStorage.removeItem('useLocalAddress'); window.location.reload(); } |