Enable CORS for Token API in WSO2 API Manger so that your React App can generate/renew Refresh/Access tokens
I was working on a React App which communicates with some resources exposed (secured using OAuth2) in WSO2 API Manager (APIM) 2.6.0 and fetches some data. There is a single application created in API Store (for my React app) which is subscribed to multiple APIs in API Store. For this application there are production keys generated (manually via UI) using a client id and a client secret (which were created at the time of creating the application in API Store). Access token is set to expire at a certain time by default in APIM and my React app had to renew the access token using password grant type and retry fetching data with the newly created access token.
So far I had done was the following regarding Cross-Origin Resource Sharing (CORS) configurations in APIM,
- I have enabled CORS at the global level, i.e. enabling
- I have enabled CORS at API level at the time of publishing my API. This is done at create API Implement stage in API Publisher.
I managed to successfully fetch data from my API using a valid access token.
How ever I got the following error (web browser > inspect > console) when trying to renew the access token through Token API, using password grant type via my React app.
Access to fetch at ‘https://localhost:8243/token' from origin ‘http://localhost:3000' 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 an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
This is because the global CORS configurations are valid only for the APIs created using API Publisher (NOT token APIs). Apart from that as I mentioned earlier you can maintain per API CORS configurations as well.
CORS config for Token API
To enable CORS for Token APIs, we need to add the following handler config into the handlers list in _TokenAPI_.xml and _RevokeAPI_.xml files which are located in <APIM_HOME>/repository/deployment/server/synapse-configs/default/api/
(here I have included the full handlers configuration, you have to insert the black bold text part to the config)
<property name=”apiImplementationType” value=”ENDPOINT”/> <property name=”allowHeaders”value=”authorization,Access-Control-Allow-Origin,Content-Type,SOAPAction”/>
<property name=”allowedOrigins” value=”http://localhost:3000"/>
<property name=”allowedMethods” value=”GET,PUT,POST,DELETE,PATCH,OPTIONS”/>
How did I find this code? Well it was there at the handlers section inside the config of my newly created custom API; same location as mentioned above where the token APIs reside.
After restarting APIM and retrying to renew the access token through my React app, it was successful. Token API returns the following JSON response.
Note: I know most of you are lazy to find and mention full domains as whitelisted domains and tend to use wildcard (*) for ease. But this is a security threat since anyone can access these endpoints. Hence it is advised to specifically add the full domain name to domain white list, i.e. finance.yourfirm.com, legal.yourfirm.com, etc… Also note that you cannot use wildcard here to represent several subdomains in one go like *.yourfirm.com.
Fetch request mode: no-cors
Now pay attention to the error message I received earlier. As recommended in the error message itself, and just as I did, you may also try (for fun) by setting the request mode to no-cors for opaque response servers. But it turns out that this cause the Authorization header to drop in the request we are sending. Therefore we get a 401 Unauthorized HTTP response from the token endpoint: https://localhost:8243/token. Hence we can’t use this option here.
Let me know if any of you need help regarding this.