mattrogowski
Well-known member
- Affected version
- 2.2.13
I'm not sure if this is a bug or I'm misunderstanding how it's intended to work, but I feel it's the former.
Our use case was we need to authenticate the user being used with a super user key via a custom header, as we're using an external user ID stored in the user table to find the XF user. So instead of
The problem is that
To me this is incorrect, as
The current solutions are either:
Our use case was we need to authenticate the user being used with a super user key via a custom header, as we're using an external user ID stored in the user table to find the XF user. So instead of
XF-Api-User
we have XF-Api-Custom-User
, and we find the user by a different column.XF\Api\App::validateUserFromApiHeader()
fires the app_api_validate_request
event, and within this you set $result
to be the user you've validated as. validateUserFromApiHeader
then returns that if it is not null, and execution continues in start()
to set the visitor based on the user returned. If you now make an API call to /api/me
, it finds the correct user you returned and outputs the API response. On first glance it looks like it's all working.The problem is that
validateUserFromApiHeader
also calls \XF::setApiKey($apiKey);
, and updates the last use of the API key. In fact it actually validates the entire API key. However, this won't get run if you return your own user from the app_api_validate_request
event. So while a call to /api/me
works as the user has been set, no other calls work as the API key hasn't actually been set, rendering it largely pointless.To me this is incorrect, as
validateUserFromApiHeader
seems to be doing too much. It's named "validate user", but it's actually "validate user, validate API key, and set API key", which seems counterintuitive to what the event within it does (returns a user, not sets your own API key). If you allow for a user to be returned from app_api_validate_request
which then short-circuits the entire rest of the function, then it should still actually set the API key somewhere else, because the event is only returning a user, not setting a completely custom key. In other words, I may want to find the user myself, but I still want all the scopes the API key has.The current solutions are either:
- Return a user from
app_api_validate_request
by setting$result
which short-circuitsvalidateUserFromApiHeader()
, meaning you need to manually call\XF::setApiKey($apiKey);
and update the last used date (as well as probably validate the API key in general) - Validate the user in
app_api_validate_request
and throw an API error if it doesn't exist, but don't set$result
- now it will continue to validate and set the API key, and initially set the user to be a guest, but you need to re-set the correct user in theapp_api_start_end
event. The reason I can't do everything in this event is that if I need to throw a custom error for the user not existing,getApiErrorResponse
is a protected method, which is why I just set an error inapp_api_validate_request
and let the core code throw the error where it currently does - Extend
XF\Http\Request::getApiUser()
to change how this value is retrieved. This feels more hacky than using events, and also means I can't throw a custom API error if the user isn't found
app_api_validate_request
is to find a user, but it skips the entire rest of the logic to set the API key that isn't user-specific if you return one and leaves you not able to make any API calls.
Last edited: