Track when an API key was last used, which IP address last used it, and
how many times it's been used overall.
This is so you can tell when an API key was last used, so you know if
the key is safe to delete, and so you can tell if an unrecognized IP has
used your key.
Add the ability to restrict API keys so that they can only be used with
certain IP addresses or certain API endpoints.
Restricting your key is useful to limit damage in case it gets leaked or
stolen. For example, if your key is on a remote server and it gets
hacked, or if you accidentally check-in your key to Github.
Restricting your key's API permissions is useful if a third-party app or
script wants your key, but you don't want to give full access to your
account.
If you're an app or userscript developer, and your app needs an API key
from the user, you should only request a key with the minimum
permissions needed by your app.
If you have a privileged account, and you have scripts running under
your account, you are highly encouraged to restrict your key to limit
damage in case your key gets leaked or stolen.
* Add an explanation of what an API key is and how to use it.
* Make it possible for the site owner to view all API keys.
* Remove the requirement to re-enter your password before you can view
your API key (to be reworked).
* Move the API key controller from maintenance/user/api_keys_controller.rb
to a top level controller.
Remove the ability to authenticate to the API with the `login` and
`password_hash` url parameters. This is a legacy authentication method
from Danbooru 1. How to actually generate the password_hash for this
method hasn't been fully documented for many years now. It required
taking the SHA1 hash of your password combined with an undocumented salt
value (i.e., password_hash = sha1("choujin-steiner--#{password}")).
This authentication method was also slow because it required checking
the password on every API call. Checking passwords is deliberately slow
because passwords are hashed with BCrypt. BCrypt takes about ~200ms per
request, so using this method effectively limited you to ~5 requests per
second in a single thread.
In xml responses, if the result is an empty array we want the response
to look like this:
<posts type="array"/>
not like this (the default):
<nil-classes type="array"/>
This refactors controllers so that this is done automatically instead of
having to manually call `@things.to_xml(root: "things")` everywhere. We
do this by overriding the behavior of `respond_with` in `ApplicationResponder`
to set the `root` option by default in xml responses.
Refactor to use `render_error_page` to handle User::PrivilegeError
exceptions. This way these exceptions are logged to New Relic.
Changes:
* Anonymous users aren't automatically redirected to the login page.
Instead they're taken to the access denied page, which links to the
login/signup pages.
* JSON/XML error responses return `message` instead of `reason`.
Fixes POST/PUT API requests failing with InvalidAuthenticityToken errors
due to missing CSRF tokens.
CSRF protection is only necessary for cookie-based authentication. For
non-cookie-based authentication we can safely disable it. That is, if
the user is already passing their login + api_key, then we don't need
to additionally verify the request with a CSRF token.
ref: 2e407fa476 (comments)