Passing an api_username for a user that does not exist returns a 500 with no useful context

On the beta branch, when attempting to create a POST on behalf of a user, I use the API and provide the username as the api_username. Because of the way I’m managing users, the user may not exist in Discourse at this time and I’d like to be able to respond to that exception by creating the user. It would be useful if the error had enough context to determine that this case occurred, but instead, it’s raising a Discourse::InvalidAccess and the server is returning a 500.

Strack trace:

lib/auth/default_current_user_provider.rb:57:in `current_user'
lib/current_user.rb:30:in `current_user'
app/helpers/application_helper.rb:59:in `html_classes'
app/views/layouts/application.html.erb:2:in `_app_views_layouts_application_html_erb__210758119167932006_91259420'
app/controllers/application_controller.rb:496:in `build_not_found_page'
app/controllers/application_controller.rb:134:in `rescue_discourse_actions'
app/controllers/application_controller.rb:117:in `block in <class:ApplicationController>'
config/initializers/100-quiet_logger.rb:13:in `call_with_quiet_assets'
config/initializers/100-silence_logger.rb:26:in `call'
lib/middleware/missing_avatars.rb:21:in `call'
lib/middleware/turbo_dev.rb:33:in `call'

I can work around this, but it would be nice if the server responded with something in the 4xx range and enough information to determine the cause of the issue.

2 Likes

Sure I am all for better, more descriptive errors – @techapj can you add to your list?

3 Likes

Just curious, is there an issue or something else I can follow related to this bug? I have a bit of code to work around it that I’d like to rip out once I know that I can :slight_smile:

I am confident @techapj will get to it in due time.

This is actually by design as per:

https://github.com/discourse/discourse/blob/16a383ea1ee73e1d62da49b467a2e9fb7ea607b0/lib/auth/default_current_user_provider.rb#L68-L72

I believe Discourse::InvalidAccess is enough to determine that

  • either username is incorrect
  • or api_key is incorrect

If both of the above is correct than you will get specific error message.

I hope this helps.

3 Likes

Thanks for the reply. In my tests, it would reply with a 500 with no
response body. It’s impossible to know the reason for the failure in that
case. I would think something in the 4xx range with some information
indicating the cause of the error (a username that does not exist) would be
more helpful and appropriate, no?

Are you using official discourse_api gem?

I just tried the same using official discourse_api and got 403 Forbidden with proper error message:

{"errors"=>["You are not permitted to view the requested resource."], "error_type"=>"invalid_access"} (DiscourseApi::UnauthenticatedError)
2 Likes

No, I’m just hitting the API via HTTP. I’ll provide a CURL command when I’m
back to my computer.

Here’s an example curl command with sensitive data stripped out:

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'raw=demo of failing post on behalf of non-existent api-user&title=herp derp jerp' "<my_discourse_instance>/posts?api_key=<valid_api_key>&api_username=<nonexistent_username>" -i

Try making cURL request in this format:

curl -X POST -H "Accept: application/json" -H "Content-Type: application/json" -d '{"raw":"demo of success post"}' <my_discourse_instance>/posts?api_key=<valid_api_key>&api_username=<nonexistent_username>

You will get exact response and error message you are looking for.

3 Likes