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

API Key Authentication #99

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 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
3 changes: 2 additions & 1 deletion content/en/docs/Endpoints/getLyricsBySongId.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Clients should treat `xxx` as not having a specified language (equivalent to the

### Example

{{< alert color="primary" >}} `http://your-server/rest/getLyricsBySongId.view?&id=123&u=demo&p=demo&v=1.13.0&c=AwesomeClientName&f=json` {{< /alert >}}
{{< alert color="primary" >}} `http://your-server/rest/getLyricsBySongId.view?id=123&u=demo&p=demo&v=1.13.0&c=AwesomeClientName&f=json` {{< /alert >}}

### Result

Expand Down Expand Up @@ -110,6 +110,7 @@ A [`subsonic-response`](../../responses/subsonic-response) element with a nested
<line>Grating me</line>
<line>And twisting me around...</line>
</structuredLyrics>
</lyricsList>
</subsonic-response>
{{< /tab >}}
{{< tab header="Subsonic" >}}
Expand Down
2 changes: 2 additions & 0 deletions content/en/docs/Endpoints/getopensubsonicextensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ List the OpenSubsonic extensions supported by this server.

Takes no extra parameters.

**Note**: Unlike all other APIs `getOpenSubsonicExtensions` **must** be publicly accessible.

### Example

{{< alert color="primary" >}} `http://your-server/rest/getOpenSubsonicExtensions.view?u=demo&p=demo&v=1.13.0&c=AwesomeClientName&f=json` {{< /alert >}}
Expand Down
62 changes: 62 additions & 0 deletions content/en/docs/Endpoints/tokeninfo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: "tokenInfo"
linkTitle: "tokenInfo [OS]"
opensubsonic:
- Addition
- Extension
categories:
- System
description: >
Returns information about an API key
---

**OpenSubsonic version**: [1](../../opensubsonic-versions)

**OpenSubsonic extension name** `apiKeyAuthentication` (As returned by [`getOpenSubsonicExtensions`](../../endpoints/getopensubsonicextensions))

Returns data about an API key.

`http://your-server/rest/tokenInfo`

### Parameters

None

### Example

{{< alert color="primary" >}} `http://your-server/rest/tokenInfo.view?apiKey=1234&v=1.13.0&c=AwesomeClientName&f=json` {{< /alert >}}


### Result

A [`subsonic-response`](../../responses/subsonic-response) element with a nested [`tokenInfo`](../../responses/tokenInfo/) on success, or error 44 on invalid token.

{{< tabpane persistLang=false >}}
{{< tab header="**Example**:" disabled=true />}}
{{< tab header="OpenSubsonic JSON" lang="json">}}
{
"subsonic-response": {
"status": "ok",
"version": "1.16.1",
"type": "AwesomeServerName",
"serverVersion": "0.1.3 (tag)",
"openSubsonic": true,
"tokenInfo": {
"username": "token username"
}
}
}
{{< /tab >}}
{{< tab header="OpenSubsonic XML" lang="xml">}}
<subsonic-response status="ok" version="1.16.1" type="AwesomeServerName" serverVersion="0.1.3 (tag)" openSubsonic="true">
<tokenInfo username="token username"></tokenInfo>
</subsonic-response>
{{< /tab >}}
{{< tab header="Subsonic" >}}
Does not exist.
{{< /tab >}}
{{< /tabpane >}}

| Field | Type | Req. | OpenS. | Details |
| ----------- | ---------------------------------------- | ------- | ------- | ------------------------- |
| `tokenInfo` | [`tokenInfo`](../../responses/tokeninfo) | **Yes** | **Yes** | Information about the token |
47 changes: 47 additions & 0 deletions content/en/docs/Extensions/apiKeyAuth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: "API Key Authentication"
linkTitle: "API Key Authentication"
OpenSubsonic:
- Extension
description: >
Add support for synchronized lyrics, multiple languages, and retrieval by song ID
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad copy/paste?

---

**OpenSubsonic version**: [1](../../opensubsonic-versions)

**OpenSubsonic extension name** `apiKeyAuthentication` (As returned by [`getOpenSubsonicExtensions`](../../endpoints/getopensubsonicextensions))

## Version 1

This extension requires changes to the semantics of authentication.
Broadly, there are two general changes:

1. **Required**: A new authentication mechanism: `apiKey` for query.
2. Recommended: Deprecation of token/salt-based authentication.

### API keys

An API key is any authentication token generated by an OpenSubsonic server that can be used to authenticate.
How this API key is generated by the server is implementation-specific: the server may provide a page where the user can configure one or more API keys, the server may automatically generate a API key, or any other variety of means.
The format of the API key is not specified, but it **must** be of reasonable length to fit into a query parameter (less than 2048 characters URL-encoded).

Servers which implement this extension **must** provide some mechanism for viewing active API key(s) and allow for revoking API keys.
Note that these API keys **do not** expire; as long as they are not revoked by the user, they are assumed to be valid.

#### Using a API key

An API key is used as a query parameter `apiKey=<api key>`.
When an API key is provided, the client **must not** provide a `u` parameter; passing in `u` **must** be treated as an error `43`.

It is **recommended** that servers which provide API-key authentication deprecate salt/token-based authentication.

If multiple conflicting authentication parameters are passed in, the server **must** return an error `43`, `Multiple conflicting authentication mechanisms provided`

If a server deprecates salt-based authentication, it **must** return an error `41` (`Token authentication not supported for LDAP users.`).
Similarly, if a server deprecates password-based authentication, it **must** return an error `42` (`Password authentication not supported. Use API keys`).

In both cases, it is recommended that the server provide a meaningful url (configuration url, documentation, etc) in the `helpUrl` to help clients instruct their users how to obtain an API key.

## New error codes

This extension introduces three new errors `42`, `43` and `44`, and adds a new field `helpUrl`. See [error](../../responses/error)
43 changes: 25 additions & 18 deletions content/en/docs/Responses/error.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
title: "error"
linkTitle: "error"
linkTitle: "error [OS]"
opensubsonic:
- Change
description: >
Error.
---
Expand All @@ -9,8 +11,9 @@ description: >
{{< tab header="**Example**:" disabled=true />}}
{{< tab header="OpenSubsonic" lang="json">}}
{
"code": 40,
"message": "Wrong username or password"
"code": 42,
"message": "Authentication mechanism not supported. Use API keys",
"helpUrl": "https://example.org/users/apiKey"
}
{{< /tab >}}
{{< tab header="Subsonic" lang="json" >}}
Expand All @@ -21,21 +24,25 @@ description: >
{{< /tab >}}
{{< /tabpane >}}

| Field | Type | Req. | OpenS. | Details |
| --- | --- | --- | --- | --- |
| `code` | `int` | **Yes** | | The error code |
| `message` | `string` | No | | The optional error message |
| Field | Type | Req. | OpenS. | Details |
| --------- | -------- | ------- | ------ | --------------------------------------------------------------------------------------------- |
| `code` | `int` | **Yes** | | The error code |
| `message` | `string` | No | | The optional error message |
| `helpUrl` | `string` | No | Yes | A URL (documentation, configuration, etc) which may provide additional context for the error) |

The following error codes are defined:

| Code | Description |
| --- | --- |
| 0 | A generic error. |
| 10 | Required parameter is missing. |
| 20 | Incompatible Subsonic REST protocol version. Client must upgrade. |
| 30 | Incompatible Subsonic REST protocol version. Server must upgrade. |
| 40 | Wrong username or password. |
| 41 | Token authentication not supported for LDAP users. |
| 50 | User is not authorized for the given operation. |
| 60 | The trial period for the Subsonic server is over. Please upgrade to Subsonic Premium. Visit subsonic.org for details. |
| 70 | The requested data was not found. |
| Code | Description |
| ---- | --------------------------------------------------------------------------------------------------------------------- |
| 0 | A generic error. |
| 10 | Required parameter is missing. |
| 20 | Incompatible Subsonic REST protocol version. Client must upgrade. |
| 30 | Incompatible Subsonic REST protocol version. Server must upgrade. |
| 40 | Wrong username or password. |
| 41 | Token authentication not supported for LDAP users. |
| 42 | Password authentication not supported. Use API keys |
| 43 | Multiple conflicting authentication mechanisms provided |
| 44 | Invalid API key or username |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the new apiKey version no more pass an username so it can't be a wrong user name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why I left username is if it's not required (and clients just specify api key), then there's no easy way to get the username. I would potentially be amenable to adding a new endpoint to turn a token into a username

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ho you left username mandatory I missed that. Well then it makes sense but won't it be a problem if we extend to v2 with apiKey that can be limited to a media and don't want to leak the username in the urls ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a new endpoint to exchange token for username (and other things (?) for v2) then

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, could return the scope too ;)

I think better to reuse the apiKey for media than adding again something else that would not bring anything more.

| 50 | User is not authorized for the given operation. |
| 60 | The trial period for the Subsonic server is over. Please upgrade to Subsonic Premium. Visit subsonic.org for details. |
| 70 | The requested data was not found. |
29 changes: 29 additions & 0 deletions content/en/docs/Responses/tokeninfo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: "tokenInfo"
linkTitle: "tokenInfo [OS]"
opensubsonic:
- Addition
description: >
Information about an API key
---

{{< tabpane persistLang=false >}}
{{< tab header="**Example**:" disabled=true />}}
{{< tab header="OpenSubsonic JSON" lang="json">}}
{
"tokenInfo": {
"username": "token username"
}
}
{{< /tab >}}
{{< tab header="OpenSubsonic XML" lang="xml">}}
<tokenInfo username="token username"></tokenInfo>
{{< /tab >}}
{{< tab header="Subsonic" >}}
Does not exist.
{{< /tab >}}
{{< /tabpane >}}

| Field | Type | Req. | OpenS. | Details |
| ---------- | ------ | ------- | ------- | ------------------------------ |
| `username` | string | **Yes** | **Yes** | Username associated with token |
Loading