This makes personal access token the only possible authentication for the API. For API requests without a personal access token, they get a specific error that the credentials are missing. I chose to use 401 for this, because that seemed more appropriate than 400. In the specs, `login_api` now takes no arguments. It just sets to use personal access tokens for requests. This was chosen over removing the method completely, because there are a significant number of specs that want to test for unauthenticated access. I'm not sure whether such specs are actually useful, since they all hit the same condition at the top of the main route block. We should consider changing the specs in the future to provide an access token that is valid, but does not grant access to the objects, in order to test for specific authorization. We already do this in some cases, but not in others. With this change, the only error that Rodauth can generate for API requests is for invalid credentials, so simplify the json_response_body method, and generate the response body up front so we don't need to generate it per-request. Also remove /login from openapi.yml, as it is no longer valid.
29 lines
792 B
Ruby
29 lines
792 B
Ruby
# frozen-string-literal: true
|
|
|
|
require "rodauth"
|
|
|
|
module Rodauth
|
|
Feature.define(:personal_access_token, :PersonalAccessToken) do
|
|
auth_value_method :pat_authorization_remove, /\ABearer:?\s+pat-/
|
|
session_key :session_pat_key, :pat_id
|
|
|
|
def session
|
|
return @session if defined?(@session)
|
|
|
|
@session = s = {}
|
|
|
|
token = request.env["HTTP_AUTHORIZATION"].to_s.sub(pat_authorization_remove, "")
|
|
token_id, key = token.split("-", 2)
|
|
|
|
return s unless (uuid = UBID.to_uuid(token_id))
|
|
return s unless (api_key = ApiKey[owner_table: "accounts", id: uuid, is_valid: true])
|
|
return s unless timing_safe_eql?(api_key.key, key)
|
|
|
|
set_session_value(session_key, api_key.owner_id)
|
|
set_session_value(session_pat_key, uuid)
|
|
|
|
s
|
|
end
|
|
end
|
|
end
|