Error 4700 Invalid Redirect on every new OAuth app
redirect URL confirmed saved correctly
reproduced with Zoom’s own ‘Add app now’ generated authorization URL across 3 separate apps.
Client ID is ESe9Pb6wRT6w_asE76cKWA
@LenCole localhost is not a supported for redirect URL.
@LenCole Hi,
As already mentioned by @chunsiong.zoom, localhost isn’t supported for redirect URLs - you either use your staging/development environment’s redirect URL (the simplest option if you already have one deployed), or create a local domain via /etc/hosts (or the Windows hosts file), e.g. yourdomain.dev, pointed at whatever port your app runs on locally.
I’m sharing my whole nginx config above just for reference, but you really only need a simple sample. Below is a minimal example using yourdomain.dev, plus the openssl command to generate a self-signed cert with a proper SAN (subjectAltName), and how to trust it locally so browsers don’t complain.
.dev domain to your local app.macOS / Linux - edit /etc/hosts (needs sudo):
##
# Host Database
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
127.0.0.1 yourdomain.dev
127.0.0.1 api.yourdomain.dev
127.0.0.1 admin.yourdomain.dev
Apply on Linux (usually not needed, but flush DNS cache just in case):
sudo systemd-resolve --flush-caches # or
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder # macOS
Windows - edit C:\Windows\System32\drivers\etc\hosts as Administrator (Notepad “Run as administrator”):
127.0.0.1 localhost
127.0.0.1 yourdomain.dev
127.0.0.1 api.yourdomain.dev
127.0.0.1 admin.yourdomain.dev
Then flush DNS:
ipconfig /flushdns
Note: the hosts file only maps the domain to 127.0.0.1 - it doesn’t know about ports. Your app still runs on whatever port it normally does (e.g. 3000, 8080, 5173, etc.). That’s what nginx is for below - it listens on the standard ports (80/443) for yourdomain.dev and reverse-proxies to your actual local port, so you don’t need yourdomain.dev:3000 in the URL.
Modern browsers reject certs that only set CN - you need subjectAltName (SAN). Example:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout yourdomain.dev.key \
-out yourdomain.dev.crt \
-subj "/C=US/ST=Florida/L=Saint Petersburg/O=YourCompany, Inc./OU=IT/CN=yourdomain.dev" \
-addext "subjectAltName=DNS:yourdomain.dev,DNS:*.yourdomain.dev,DNS:api.yourdomain.dev,DNS:admin.yourdomain.dev"
Key points:
-addext "subjectAltName=..." - list every hostname you’ll hit in the browser (including wildcard if you want one cert for all subdomains)."), not smart quotes - copy/pasting from some editors/forums can silently corrupt the -subj/-addext strings and cause a cryptic OpenSSL error.Replace 3000 below with whatever port your app actually runs on locally (Next.js dev server, Vite, Express, etc.):
server {
listen 443 ssl;
server_name yourdomain.dev api.yourdomain.dev admin.yourdomain.dev;
ssl_certificate /path/to/yourdomain.dev.crt;
ssl_certificate_key /path/to/yourdomain.dev.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:3000; # <-- your app's local port
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
server {
listen 80;
server_name yourdomain.dev api.yourdomain.dev admin.yourdomain.dev;
return 301 https://$host$request_uri;
}
If your app talks to a separate API on a different port, add another server_name block (e.g. api.yourdomain.dev) pointing proxy_pass at that port instead, same pattern as in my full config above.
macOS:
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain yourdomain.dev.crt
Windows (PowerShell as Administrator):
Import-Certificate -FilePath "yourdomain.dev.crt" -CertStoreLocation Cert:\LocalMachine\Root
Linux (Ubuntu/Debian):
sudo cp yourdomain.dev.crt /usr/local/share/ca-certificates/yourdomain.dev.crt
sudo update-ca-certificates
After that, restart your browser (some browsers, like Chrome, also need you to restart the whole app, not just close the tab) and https://yourdomain.dev should load without any certificate warning, and you can use that as your redirect URL.
Thanks,
Naeem Ahmed