Then I guess I'd have the backend send the user a link with an auth token after joining, that way at least no pasting needs to happen.
but this doesn’t work, because there is only one standard method of authentication, which is by sending username/password
A matrix bot could send the user a short-lived token they can paste to the site to authenticate. Optional QR for mobile.
No need for homeserver changes, changing protocols or touching any user credentials.
Since you’d rely on an existing matrix session, the bot could send the token e2ee, meaning after TOFU you could even protect against malicious homeserver operators.
You could also do the inverse, having the user send the token to the bot.
but it does not authenticate you against the homeserver and does not grant you the access token, meaning the application would not be able to access Matrix APIs on user's behalf
That’s exactly what you want to avoid.
The bot can still get things shared by the user like username, avatar, 3pids and pubkeys.
Can you give me a use-case that my proposed solution is insufficient for due to inability to impersonate the user to the Matrix homeserver?