diff --git a/SSO-Auth/Api/SSOViewsController.cs b/SSO-Auth/Api/SSOViewsController.cs
index 70770b5..2d66a9a 100644
--- a/SSO-Auth/Api/SSOViewsController.cs
+++ b/SSO-Auth/Api/SSOViewsController.cs
@@ -112,9 +112,9 @@ public class SSOViewsController : ControllerBase
}
///
- /// Returns the shared js module that initializes the ApiClient.
+ /// Get the shared js module that initializes the ApiClient.
///
- /// The html view for the linking interface.
+ /// Returns the shared js module that initializes the ApiClient.
// [Authorize(Policy = "DefaultAuthorization")]
[HttpGet("ApiClient.js")]
public ActionResult GetApiClientView()
diff --git a/SSO-Auth/Config/linking.html b/SSO-Auth/Config/linking.html
index 46beed7..1f53e7d 100644
--- a/SSO-Auth/Config/linking.html
+++ b/SSO-Auth/Config/linking.html
@@ -1,7 +1,15 @@
- SSO
+
+ SSO Linking
+
+
diff --git a/SSO-Auth/SSOPlugin.cs b/SSO-Auth/SSOPlugin.cs
index fd612a5..5eb981e 100644
--- a/SSO-Auth/SSOPlugin.cs
+++ b/SSO-Auth/SSOPlugin.cs
@@ -98,6 +98,11 @@ public class SSOPlugin : BasePlugin, IPlugin, IHasWebPages
Name = Name + "-linking.js",
EmbeddedResourcePath = $"{GetType().Namespace}.Config.linking.js"
},
+ new PluginPageInfo
+ {
+ Name = Name + "-ApiClient.js",
+ EmbeddedResourcePath = $"{GetType().Namespace}.Views.apiClient.js"
+ },
};
}
}
diff --git a/SSO-Auth/Views/apiClient.js b/SSO-Auth/Views/apiClient.js
new file mode 100644
index 0000000..307ff42
--- /dev/null
+++ b/SSO-Auth/Views/apiClient.js
@@ -0,0 +1,142 @@
+import jellyfinApiclient from "https://esm.run/jellyfin-apiclient";
+window.jellyfinApiclient = jellyfinApiclient;
+console.log(jellyfinApiclient);
+
+// https://github.com/jellyfin/jellyfin-web/blob/9067b0e397cc8b38635d661ce86ddd83194f3202/src/scripts/clientUtils.js#L19-L76
+export async function serverAddress() {
+ const apiClient = window.ApiClient;
+
+ if (apiClient) {
+ return Promise.resolve(apiClient.serverAddress());
+ }
+
+ const urls = [];
+
+ if (urls.length === 0) {
+ // Otherwise use computed base URL
+ let url;
+ const index = window.location.href.toLowerCase().lastIndexOf("/web");
+ if (index != -1) {
+ url = window.location.href.substring(0, index);
+ } else {
+ // fallback to location without path
+ url = window.location.origin;
+ }
+
+ // Don't use bundled app URL (file:) as server URL
+ if (url.startsWith("file:")) {
+ return Promise.resolve();
+ }
+
+ urls.push(url);
+ }
+
+ console.debug("URL candidates:", urls);
+
+ const promises = urls.map((url) => {
+ return fetch(`${url}/System/Info/Public`)
+ .then((resp) => {
+ return {
+ url: url,
+ response: resp,
+ };
+ })
+ .catch(() => {
+ return Promise.resolve();
+ });
+ });
+
+ return Promise.all(promises)
+ .then((responses) => {
+ responses = responses.filter((obj) => obj && obj.response.ok);
+ return Promise.all(
+ responses.map((obj) => {
+ return {
+ url: obj.url,
+ config: obj.response.json(),
+ };
+ })
+ );
+ })
+ .then((configs) => {
+ const selection =
+ configs.find((obj) => !obj.config.StartupWizardCompleted) || configs[0];
+ return Promise.resolve(selection?.url);
+ })
+ .catch((error) => {
+ console.log(error);
+ return Promise.resolve();
+ });
+}
+
+// TODO: Refactor duplicated code
+// ! Duplicated at
+// https://github.com/9p4/jellyfin-plugin-sso/blob/38558d762a13422862240af4060bdd1bb1618d57/SSO-Auth/WebResponse.cs#L363-L401
+function getDeviceName() {
+ return "DUMMY";
+}
+
+function getDeviceId() {
+ return localStorage.getItem("_deviceId2");
+}
+
+const sleep = (milliseconds) => {
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
+};
+
+async function awaitLocalStorage() {
+ while (
+ localStorage.getItem("_deviceId2") == null ||
+ localStorage.getItem("jellyfin_credentials") == null ||
+ JSON.parse(localStorage.getItem("jellyfin_credentials"))["Servers"][0][
+ "Id"
+ ] == null
+ ) {
+ // If localStorage isn't initialized yet, try again.
+ await sleep(100);
+ }
+}
+
+await awaitLocalStorage();
+
+// Fetch credentials
+
+var credentials = new jellyfinApiclient.Credentials();
+
+var server = await serverAddress();
+console.log({ server: server });
+var deviceId = getDeviceId();
+var appName = "SSO-Auth";
+var appVersion = "0.0.0.9000";
+var capabilities = {};
+
+const current_server = credentials
+ .credentials()
+ .Servers.find((e) => e.LocalAddress == server || e.ManualAddress == server);
+
+var localApiClient = new jellyfinApiclient.ApiClient(
+ server,
+ appName,
+ appVersion,
+ getDeviceName(),
+ deviceId
+);
+localApiClient.setAuthenticationInfo(
+ current_server.AccessToken,
+ current_server.UserId
+);
+
+var connections = new jellyfinApiclient.ConnectionManager(
+ credentials,
+ appName,
+ appVersion,
+ getDeviceName(),
+ deviceId,
+ capabilities
+);
+
+connections.addApiClient(localApiClient);
+
+window.ApiClient = localApiClient;
+
+export default localApiClient;