Native apps typically implement this flow themselves. First the private URI scheme is registered with the operating system at installation time. The native app then opens the system browser and runs a code flow.
An authorization server typically does the backend work, by returning an authorization code on a URL such as this. The browser then notifies the native app, which picks up the code and completes the flow to get tokens:
x-mycompany-myapp:/callback?code=xxx&state=yyy
To see how a end to end flow works, you could maybe run my code sample.
AUTHORIZATION SERVER
ExpressJS is not designed for implementing the authorization server role, though it could be done in theory. Instead aim to use a free cloud or docker based authorization server. There are many subtleties to implementing such a system.
UPDATE
It seems your login page is an SPA that makes an Ajax request to post user credentials. You cannot redirect that since it will lead to CORS errors. A quick fix is to return a response URL in a JSON response payload, then in JavaScript set location.href to that value.
Note that the login flow in a real authorization server is quite a deep topic. Some behaviours are provided in the OAuth Threat Model.