I have two Python routes which allow my frontend on React to authorize with Github Oauth. It happens like that:
- Frontend user goes to
BACKEND_URL/api/v1/oauth/github
from pageFRONTEND_URL/login
- Backend returns redirect to
;redirect_uri=FRONTEND_URL/login?app=github&scope=user:email
- Frontend redirects to Github and gets code in
FRONTEND_URL/login?app=github&code=CODE
- Then useEffect fetches
BACKEND_URL/api/v1/oauth/github/access?code=CODE
and gets access token
I am new to Oauth, do I have correct implementation? I'm asking because now I am trying to add state
to Oauth requests. But how can I do that?
Frontend code:
useEffect(() => {
const code = searchParams.get("code");
const app = searchParams.get("app");
if (!code || !app) {
return;
}
axios.get(`${BACKEND_URL}/api/v1/oauth/${app}/access?code=${code}`);
}, []);
<Link to={`${BACKEND_URL}/api/v1/oauth/github`}>Login with GitHub</Link>
Backend code:
@app.get('/api/v1/oauth/github')
def github():
return RedirectResponse(";redirect_uri=FRONTEND_URL/login?app=github&scope=user:email", status_code=307)
@app.get('/api/v1/oauth/github/access')
def github_access(code: str):
r = requests.post(f";client_secret=CLIENT_SECRET&code={code}")
...
return "token"
Tried to find out answer in chat gpt. But it suggested using variant below. But it looks strange. Is it a good practice?
state_storage = {}
@app.get('/api/v1/oauth/github')
def github():
state = str(uuid.uuid4())
state_storage[state] = True
return RedirectResponse(";redirect_uri=FRONTEND_URL/login?app=github&scope=user:email", status_code=307)
@app.get('/api/v1/oauth/github/access')
def github_access(code: str):
if state not in state_storage:
raise HTTPException(status_code=400)
del state_storage[state]
r = requests.post(f";client_secret=CLIENT_SECRET&code={code}")
...
return "token"