We have an Angular front end and a web service on a different port on the same development machine. The web service is configured to allow access from localhost and the port where the Angular application is hosted.
We are using JWT authentication which works for the initial authentication against the web service. We receive a auth token and store it in the Angular local storage and a refresh token that is stored as a cookie with HttpOnly set. Currently we are in a development environment where SSL is not enabled on either the client or the web service.
The problem comes when our auth token expires. Our application sends a request to renew the token, but that request does not have the refresh token cookie.
We have tried setting up a proxy in Angular to forward API requests from the Angular domain to the web service. In this case, the refresh token cookie is forwarded to the web service and we get new tokens back. Unfortunately, this will not work after the application is built and deployed and we need to be able to deploy and develop in environments where SSL is not enabled.
Here's the relevant code in our Angular application that handles sending the refresh token. Below is the method invoked in the authorization service.
public refreshToken() {
return this.http.post(this.appConfigService.getGrouperWebServiceUrl()+'/auth/refresh', {})
.pipe(
map((res: LoginResponse) => {
this.setSession(res);
return res;
})
);
}
The POST request is intercepted by an Angular interceptor.
intercept(req: HttpRequest < any > , next: HttpHandler):
Observable < HttpEvent < any >> {
// ...
if (req.url.indexOf('refresh') !== -1) {
console.log("token interceptor: refresh");
return next.handle(this.configureRefresh(req));
}
// ...
}
configureRefresh(req: HttpRequest < any > ) {
return req.clone({
withCredentials: true
});
}
Below is the raw request for a refresh request using the Angular proxy so the request appears to originate from the same origin as the web service. Note the refreshToken cookie is include in the request.
POST /proxy/auth/refresh HTTP/1.1
Host: localhost:4200
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 2
Origin: http://localhost:4200
Connection: keep-alive
Referer: http://localhost:4200/userHome
Cookie: refreshToken=/*token redacted*/
Below is the raw request for a refresh without the proxy. Note that the refreshToken cookie is not included in the request.
POST /auth/refresh HTTP/1.1
Host: localhost:8081
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 2
Origin: http://localhost:4200
Connection: keep-alive
Referer: http://localhost:4200/userHome
How can we get the refreshToken cookie to be included in the request headers when we're doing a cross-origin request?
We did see this response https://stackoverflow.com/a/46412839/8517076, but it didn't seem to help. We're already setting the recommended headers in the web service.