Many OAuth providers only accept redirect URIs that use HTTPS, and some reject localhost altogether. Expose gives your local app a public HTTPS URL that you can register as the redirect URI.
The redirect URI you register with the provider has to match exactly, so use a URL that doesn't change. With Expose Pro:
expose share http://localhost:3000 --subdomain=my-app
Your app is now at a URL such as https://my-app.eu-1.sharedwithexpose.com. Reserve the subdomain so nobody else can use it, or use your own domain.
On the free plan the URL is random on each connection, so you would need to update the provider's settings every time.
In the provider's developer console, add your callback URL to the allowed redirect URIs, for example:
https://my-app.eu-1.sharedwithexpose.com/auth/callback
Your app builds the redirect URI it sends to the provider, and it must be the same one you registered. Set the base URL your framework or auth library uses, for example APP_URL in Laravel or AUTH_URL in Auth.js, to the Expose URL while you test.
Then start the login from the public URL, not from localhost. Session and state cookies are set for the host you start on, and the callback has to arrive on the same host.
The Expose dashboard at http://127.0.0.1:4040 shows the callback request with its code and state parameters and your app's response, which makes it easy to see where a login fails.
localhost and returned on the Expose URL. Start on the Expose URL.