jonschoning / espial

Espial is an open-source, web-based bookmarking server.
GNU Affero General Public License v3.0
793 stars 27 forks source link

API key auth #35

Closed ozkutuk closed 2 years ago

ozkutuk commented 2 years ago

Motivation:

Occasionally I want to save an article from my feed reader to Espial to read it later. The feed reader I use (Miniflux) provides integrations with different such services, and I am trying to add an Espial integration as well. Unfortunately, Espial uses cookie-based authentication throughout the app and as such makes heavy use of sessions, making it hard to consume by third-party services. This PR adds an alternative API key auth mechanism, to be allowed for selectively for specific routes. For such routes, an authorization header of the form Authorization: ApiKey <API-KEY> could be used to gain access to the resource. API keys are managed through the usual migration utility with two new commands: createapikey and deleteapikey.

For example:

$ cabal run migration -- createapikey --conn espial.sqlite3 --userName myuser
"-XmazfDccY1l-tNCjq_0Iy6RnQaCWrvkvA253X1g2As="

$ http -v POST localhost:3000/api/add url=https://example.com title="Example" Authorization:"ApiKey -XmazfDccY1l-tNCjq_0Iy6RnQaCWrvkvA253X1g2As="

POST /api/add HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate, br
Authorization: ApiKey -XmazfDccY1l-tNCjq_0Iy6RnQaCWrvkvA253X1g2As=
Connection: keep-alive
Content-Length: 46
Content-Type: application/json
Host: localhost:3000
User-Agent: HTTPie/3.0.2

{
    "title": "Example",
    "url": "https://example.com"
}

HTTP/1.1 201 Created
Content-Length: 1
Content-Type: application/json; charset=utf-8
Date: Wed, 13 Apr 2022 19:39:54 GMT
Server: Warp/3.3.19
Set-Cookie: _SESSION=FgPaaVWGrNO/fWGDisxgRtYi7hwn10X2ZrxWqHaew0NLegHM3i5eJKLmXrpt4FAGxF0mc3fPzQle4Bvju1Hs1bJznd3Ywkj5Aa1g1uJmvEACTfcAxhvaaaUJiD40E1qCdBj6nXWL+4FDrdwJu0QJpYoNyl+EfffPtpwprTxirK+upfk2htQ=; Path=/; Expires=Wed, 20-Apr-2022 19:39:54 GMT; HttpOnly
Vary: Accept-Encoding
Vary: Accept, Accept-Language
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

6

Implementation details:

I think the implementation doesn't expose any vulnerabilities, though I am not too familiar with the Yesod way of doing things and security isn't my strongest suite, so I would appreciate feedback regarding these choices.

jonschoning commented 2 years ago

Look good! Will merge this in soon