JPortal CORS Proxy#
A Node.js/Express server that acts as a CORS proxy specifically for the JIIT Web Portal API. This proxy enables the codeblech/jportal frontend to bypass CORS restrictions that were recently implemented by JIIT’s backend.
Why This Exists#
JIIT recently added CORS restrictions to their Web Portal API (webportal.jiit.ac.in:6011) that only allow same-origin requests. This breaks third-party frontends like jportal that are hosted on different domains (e.g., GitHub Pages).
The official JIIT portal works because it’s served from the same origin as the API. Third-party apps see sec-fetch-site: cross-origin headers that the backend rejects. Since these sec-fetch-* headers are controlled by the browser and cannot be modified by JavaScript, we need a proxy server.
This proxy:
- Receives requests from the jportal frontend
- Forwards them to the JIIT API with the correct
Originheader - Returns responses with proper CORS headers
- Is locked down to only proxy JIIT API requests (security)
Why Node.js Instead of Cloudflare Workers?#
TLDR: Cloudflare Workers cannot proxy to custom ports.
JIIT’s API runs on port 6011 (https://webportal.jiit.ac.in:6011). Cloudflare Workers strip custom ports from URLs and only support standard ports (80/443). This makes them unsuitable for this use case.
See cloudflare/README.md for details on why the Cloudflare Worker implementation doesn’t work.
Security#
This proxy is locked down and only allows:
- Proxying to
https://webportal.jiit.ac.in:6011(no other domains) - Requests from whitelisted origins (jportal domains)
- Standard HTTP methods: GET, POST, HEAD, OPTIONS
This prevents abuse of the proxy as an open proxy.
Deployment to Render#
Prerequisites#
- A Render account (free tier works)
- A GitHub account
- This repository pushed to your GitHub
Automatic Deployment (Recommended)#
Push to GitHub
git clone https://github.com/codeblech/jportal-cors-proxy.git cd jportal-cors-proxy git remote set-url origin https://github.com/YOUR-USERNAME/jportal-cors-proxy.git git push -u origin mainDeploy to Render
- Go to Render Dashboard
- Click “New +” → “Web Service”
- Connect your GitHub repository
- Render will automatically detect
render.yamland configure everything - Click “Create Web Service”
Your proxy URL
- Render will provide a URL like:
https://jportal-cors-proxy.onrender.com - Save this URL for configuring jportal
- Render will provide a URL like:
Manual Deployment#
If you prefer manual configuration:
Create New Web Service on Render
Configure:
- Name:
jportal-cors-proxy - Region: Singapore (or closest to India)
- Branch:
main - Runtime: Node
- Build Command:
npm install - Start Command:
npm start - Plan: Free
- Name:
Environment Variables:
NODE_ENV:productionJIIT_API_BASE:https://webportal.jiit.ac.in:6011ALLOWED_ORIGINS:https://yashmalik.tech,https://codeblech.github.io,http://localhost:5173
Health Check:
- Path:
/health
- Path:
Deploy
Local Development#
Setup#
Clone and install
git clone https://github.com/codeblech/jportal-cors-proxy.git cd jportal-cors-proxy npm installCreate
.envfilecp .env.example .envStart development server
npm run devServer will run at
http://localhost:3000
Testing#
Test the proxy:
# Health check
curl http://localhost:3000/health
# Info endpoint
curl http://localhost:3000/
# Test proxied request (example: token generation)
curl -X POST http://localhost:3000/proxy/StudentPortalAPI/token/generate \
-H "Content-Type: application/json" \
-H "Origin: http://localhost:5173" \
-d '{
"username": "your-enrollment",
"password": "your-password",
"memberType": "S"
}'
Usage#
API Endpoints#
The proxy supports two URL formats:
Method 1: Query parameter
https://your-proxy.onrender.com/proxy?path=/StudentPortalAPI/token/generate
Method 2: Path-based
https://your-proxy.onrender.com/proxy/StudentPortalAPI/token/generate
Example: Token Generation#
Original JIIT API call:
POST https://webportal.jiit.ac.in:6011/StudentPortalAPI/token/generate
Content-Type: application/json
{
"username": "...",
"password": "...",
"memberType": "S"
}
Through the proxy:
POST https://your-proxy.onrender.com/proxy/StudentPortalAPI/token/generate
Content-Type: application/json
{
"username": "...",
"password": "...",
"memberType": "S"
}
Integrating with jportal#
Update jportal to use the proxy URL when creating WebPortal instances:
const portal = new WebPortal({
useProxy: true,
proxyUrl: 'https://your-proxy.onrender.com' // Your Render proxy URL
});
See codeblech/jsjiit for more details.
Architecture#
┌─────────────────┐
│ jportal (PWA) │
│ GitHub Pages │
└────────┬────────┘
│ CORS request
│ (cross-origin)
▼
┌─────────────────────┐
│ Node.js/Express │
│ Render Web Service │
└────────┬────────────┘
│ Request to port 6011
│ (Origin header set)
▼
┌─────────────────────┐
│ JIIT Web Portal │
│ Backend API:6011 │
└─────────────────────┘
How It Works#
Client Request: jportal makes a request to the proxy (e.g.,
render.com/proxy/StudentPortalAPI/token/generate)Proxy Processing:
- Validates the request origin is whitelisted
- Validates the target URL is a JIIT API endpoint
- Creates a new request to JIIT with:
- Same method, headers, and body
Origin: https://webportal.jiit.ac.in:6011header (makes it appear same-origin)
JIIT API:
- Sees
sec-fetch-site: same-origin(because request comes from server, not browser) - Processes the request normally
- Returns response
- Sees
Proxy Response:
- Receives JIIT response
- Adds CORS headers (
Access-Control-Allow-Origin, etc.) - Returns to jportal
Client Receives: jportal receives the response with proper CORS headers and can process it
Cost#
Render’s free tier includes:
- 750 hours per month (enough for 24/7 operation)
- Automatic sleep after 15 minutes of inactivity
- Automatic wake on request
For a student portal proxy, the free tier is sufficient.
Security Considerations#
- Whitelisted Origins: Only requests from known jportal domains are allowed
- Locked Down Target: Only JIIT API can be proxied
- No Credential Storage: Proxy doesn’t store or log credentials
- HTTPS Only: All communication is encrypted (Render provides free SSL)
- Standard Headers: All standard security headers are preserved
Troubleshooting#
“Invalid target URL” error#
- Make sure your request path starts with
/StudentPortalAPI - Check that you’re using the correct proxy URL format
“502 Bad Gateway” error#
- JIIT’s backend might be down
- Check JIIT portal availability at https://webportal.jiit.ac.in:6011
- Proxy might be sleeping (Render free tier) - retry after a few seconds
CORS errors still occurring#
- Verify your origin is in the
ALLOWED_ORIGINSlist - Check proxy logs on Render dashboard
- Ensure you’re using the correct proxy URL in jportal
Proxy is slow#
- Render free tier sleeps after 15 minutes of inactivity
- First request after sleep takes 30-60 seconds
- Subsequent requests are fast
- Consider upgrading to paid tier for 24/7 availability
Environment Variables#
Create a .env file (see .env.example):
PORT=3000 # Server port (Render provides this automatically)
JIIT_API_BASE=https://webportal.jiit.ac.in:6011 # JIIT API URL with port
ALLOWED_ORIGINS=https://yashmalik.tech,https://codeblech.github.io # Whitelisted origins
Project Structure#
jportal-cors-proxy/
├── server.js # Main Express server (Node.js proxy)
├── package.json # Node.js dependencies
├── render.yaml # Render deployment configuration
├── .env.example # Environment variable template
├── .gitignore # Git ignore rules
├── README.md # This file
└── cloudflare/ # Archived Cloudflare Worker (non-functional)
├── index.ts # Original Worker code
├── wrangler.toml # Worker configuration
├── tsconfig.json # TypeScript config
└── README.md # Explanation of why it doesn't work
Contributing#
Issues and pull requests are welcome! Please ensure:
- Security best practices are maintained
- Only JIIT API proxying is allowed
- Origin whitelist is properly validated
License#
MIT License - see LICENSE file for details
Related Projects#
- codeblech/jportal - Progressive Web App for JIIT student portal
- codeblech/jsjiit - JavaScript wrapper for JIIT Web Portal API
Disclaimer#
This proxy is an educational project to demonstrate CORS workarounds. It is not affiliated with or endorsed by JIIT. Use responsibly and in accordance with your institution’s policies.