User API keys specification

Do you think it would make sense to skip detect-browser javascripts when someone uses

https://sitename.com/user-api-key/new

endpoint? They are most likely being redirected there from an app, so checking if their javascript engine is up to snuff makes little sense and only blocks users that want to generate an api key for in-app usage

But you still need to log in for it to work

Yeah that’s the problem, when user-api-key/new redirects you to a login page it then starts checking your browser and instead of allowing login to generate api key, it complains about your browser being too old, maybe skip those checks if user is here only to generate an api key?

Yeah that is the issue, it’s kind of asking for a JavaScript less way of logging in, this is incredibly complex given the enormous amount off auth options we support and spam prevention measures

1 Like

Doesn’t need to be javascriptless, just login forms don’t really need all the bells and whistles that are used elsewhere on the site? At least for passthrough to the auth/oauth2_basic doesn’t seem to be needed as 99% is done with headers and redirects. I have an app on SailfishOS that works completely fine with the .json’s and passing the api-key, which is great as the browser there is esr78 firefox based and gets blocked in most discourse instances, but the only way to get an api-key seems to be manually entering 200+ char URL in desktop, then pasting the resulting code back on the phone to decode it, absolutely ridiculous

A minor issue and maybe a bigger one:

There’s a required nonce param that’s not mentioned in the documentation:

  def require_params
    %i[public_key nonce scopes client_id application_name].each { |p| params.require(p) }
  end

Now the trickier issue. Discourse calls the public_encrypt method with no arguments:

That means the padding argument defaults to PKCS1_PADDING. From the Ruby documentation:

Encrypt string with the public key. padding defaults to PKCS1_PADDING, which is known to be insecure but is kept for backwards compatibility.

Unfortunately, Node v20.14.0 (the current LTS) returns an error if you attempt to call crypto.privateDecrypt with RSA_PKCS1_PADDING :

function decryptData(data: string, privateKey: string) {
  const buffer = Buffer.from(data, "base64");
  const decrypted = crypto.privateDecrypt(
    {
      key: privateKey,
      padding: crypto.constants.RSA_PKCS1_PADDING,
    },
    buffer
  );
  return decrypted.toString("utf8");
}

TypeError: RSA_PKCS1_PADDING is no longer supported for private decryption, this can be reverted with --security-revert=CVE-2023-46809

A possible fix for Node apps is to run Node with the insecure flag:

node --security-revert=CVE-2023-46809 

A fix on the Discourse end would be easy, but I suspect it would break a lot of existing integrations:

public_key = OpenSSL::PKey::RSA.new(params[:public_key])
@payload = Base64.encode64(public_key.public_encrypt(@payload, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING))
1 Like