Sorry for the wall of text, but I’m struggling to figure out how to solve this, and I figured I’d provide as much detail as I can.
I’ve got a project using a Django backend, with Django Rest Framework to serve an API, and a Vue.js frontend SPA to consume the API. I’m running into some kind of CORS issue during authentication.
I’ve been using mozilla-django-oidc to implement the Authorization Code flow with Okta. This works fine pretty much out of the box, and if I navigate to the API in my browser, I can login to Okta and I get a Django session. I’ve also enabled SessionAuthentication for DRF, which allows the same session cookies generated by Django to be accessible by the SPA (both SPA and API are on the same domain), provided I login first directly through the API. This all works fine until the id token expires. In Django, when the id token expires, I get a redirect to https://mydomain.okta.com/oauth2/v1/authorize?...
, the Authorization Code flow completes and I get sent on through to the originally requested page. Where things fail is in an ajax request from the SPA to the API with an expired id token. I get the same redirect, but this time it fails due to CORS.
Access to XMLHttpRequest at 'https://mydomain.okta.com/oauth2/v1/authorize?response_type=code&client_id=X&redirect_uri=http%3A%2F%2F127.0.0.1%3A8000%2Foidc%2Fcallback%2F&state=X&scope=openid+email+profile&prompt=none&nonce=X' (redirected from 'http://127.0.0.1:8080/api/X') from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I’ve tried to identify why it’s failing.
On local development, I’m running my API on 127.0.0.1:8000 and my SPA on 127.0.0.1:8080, so clearly the origins don’t match. I have Vue setup with a proxy so it looks like requests are coming from 8080, but the redirect_uri in the request to Okta is still using 8000.
When I deploy to a test server, I’m using docker containers for the API and SPA and a reverse proxy to route requests and also for SSL. In this case, the API and SPA have the same origin (I think). Yet I still get the same error message.
Access to XMLHttpRequest at 'https://mydomain.okta.com/oauth2/v1/authorize?response_type=code&client_id=X&redirect_uri=http%3A%2F%2Fmydomain.com%2Foidc%2Fcallback%2F&state=X&scope=openid+email+profile&prompt=none&nonce=X' (redirected from 'https://mydomain.com/api/X') from origin 'https://mydomain.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
If you notice, the redirect_uri is http, not https. I suspect that is why this is failing. Though I’m not entirely confident because if I navigate my browser to the API, I am on https, but the redirect_uri is still http, and it still successfully authenticates.
Any insight would be really helpful.
- What am I doing wrong or missing here?
- Am I approaching the authentication flow all wrong for an API+SPA app? Should I do authentication on the SPA instead? How does the API then know who’s logged in?