Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support API key authentication #23

Merged
merged 1 commit into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ json.loads(credentials)
client.authenticate({"Servers": [credentials]}, discover=False)
```

You can also authenticate using an API key, which is generated on the server.
This is different to a device AccessToken, and is set by not configuring a
device name, or a device id:

```
client.config.data["app.name"] = 'your_brilliant_app'
client.config.data["app.version"] = '0.0.1'
client.authenticate({"Servers": [{"AccessToken: <API key here>, "address": <Server Address>}]}, discover=False)
```

### API

The API is accessed via the `jellyfin` attribute of the client. Return values
Expand Down Expand Up @@ -83,6 +93,7 @@ The test suite is run via `tox`, and you can install it from PyPi.
- Remove usage of `six` module.
- Add group of `remote_` API calls to remote control another session
- Configurable item refreshes allowing custom refresh logic (can also iterate through a list of items)
- Add support for authenticating via an API key

## Contributing

Expand Down
3 changes: 2 additions & 1 deletion jellyfin_apiclient_python/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,8 @@ def login(self, server_url, username, password=""):

def validate_authentication_token(self, server):
headers = self.get_default_headers()
headers["Authorization"] += f", Token=\"{server['AccessToken']}\""
comma = "," if "app.device_name" in self.config.data else ""
headers["Authorization"] += f"{comma} Token=\"{server['AccessToken']}\""

response = self.send_request(server['address'], "system/info", headers=headers)
return response.json() if response.status_code == 200 else {}
Expand Down
6 changes: 4 additions & 2 deletions jellyfin_apiclient_python/connection_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ def get_available_servers(self, discover=True):
except KeyError:
continue

servers.sort(key=itemgetter('DateLastAccessed'), reverse=True)
if len(servers) > 1:
servers.sort(key=itemgetter('DateLastAccessed'), reverse=True)
credentials['Servers'] = servers
self.credentials.set(credentials)

Expand Down Expand Up @@ -338,7 +339,8 @@ def _after_connect_validated(self, server, credentials, system_info, verify_auth
if system_info:

self._update_server_info(server, system_info)
self.config.data['auth.user_id'] = server['UserId']
if "UserId" in server:
self.config.data['auth.user_id'] = server['UserId']
self.config.data['auth.token'] = server['AccessToken']

return self._after_connect_validated(server, credentials, system_info, False, options)
Expand Down
2 changes: 2 additions & 0 deletions jellyfin_apiclient_python/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ def add_update_server(self, servers, server):

if server.get('AccessToken'):
existing['AccessToken'] = server['AccessToken']

if server.get('UserId'):
existing['UserId'] = server['UserId']

if server.get('ExchangeToken'):
Expand Down
14 changes: 8 additions & 6 deletions jellyfin_apiclient_python/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,14 @@ def _process_params(self, params):
params[key] = self._replace_user_info(value)

def _get_authenication_header(self):
params = {
"Client": self.config.data['app.name'],
"Device": self.config.data['app.device_name'],
"DeviceId": self.config.data['app.device_id'],
"Version": self.config.data['app.version']
}
params = {}
if "app.device_name" in self.config.data:
params.update({
"Client": self.config.data['app.name'],
"Device": self.config.data['app.device_name'],
"DeviceId": self.config.data['app.device_id'],
"Version": self.config.data['app.version']
})
if "auth.token" in self.config.data:
params["Token"] = self.config.data['auth.token']
param_line = ", ".join(f'{k}="{v}"' for k, v in params.items())
Expand Down