6

I'm developing a react (16.9.0) single page app that uses axios (0.19.0). The axios requests use token authentication to access a server running django-rest-framework (3.6.4) and django-cors-headers (3.1.1). The authentication tokens are generated by django-rest-auth (0.9.5) during login.

The app works reliably in Chrome and Firefox. In Safari, some of requests fail due to 401 errors.

This requests succeeds in all three browsers:

INFO basehttp: "GET /apis/games/?slug=pop HTTP/1.1" 200 60932```

the code that generates it looks like:

    axios
      .get(`${simplUrl}/apis/games/?slug=${gameSlug}`, {
        headers: { Authorization: simplToken },
      })
      .then(res => {
        this.setState({
          game: res.data[0],
        });
      ...

This request failed with Safari:

INFO basehttp: "OPTIONS /apis/runs/43 HTTP/1.1" 200 0
INFO basehttp: "DELETE /apis/runs/43 HTTP/1.1" 301 0
INFO basehttp: "OPTIONS /apis/runs/43/ HTTP/1.1" 200 0
WARNING basehttp: "DELETE /apis/runs/43/ HTTP/1.1" 401 58

but succeeded with Chrome:

INFO basehttp: "OPTIONS /apis/runs/43 HTTP/1.1" 200 0
INFO basehttp: "DELETE /apis/runs/43 HTTP/1.1" 301 0
INFO basehttp: "OPTIONS /apis/runs/43/ HTTP/1.1" 200 0
INFO basehttp: "DELETE /apis/runs/43/ HTTP/1.1" 204 0

the code that generates it looks like:

      const url = `${simplUrl}/apis/runs/${run.id}`;
      // console.log('url:', url);
      axios
        .delete(url, {
          headers: { Authorization: simplToken },
        })
        .then(res => {
          // console.log(res);
          afterDelete();
        });

The Safari 401 response was:

"detail": "Authentication credentials were not provided."

This is the information Safari logged for the failed DELETE request: enter image description here

The DRF apis views use are based on this mixing:

class CommonViewSet(viewsets.ModelViewSet):
    authentication_classes = (TokenAuthentication, BasicAuthentication, SessionAuthentication)
    permission_classes = (IsAuthenticated,)

For local development, the DRF server's CORS settings are:

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_HEADERS = [
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
]

I don't understand why some requests fail in Safari while others do not. Mostly, I want to insure all requests work in all three browsers.

softweave
  • 1,455
  • 2
  • 16
  • 27
  • Please show example of your "simplToken" var and how do you set it. – mon io Feb 02 '20 at 16:12
  • Add slash to the DELETE request url /apis/runs/43/ (SLASH ON THE END). I think problem is that when you call /apis/runs/43 (WITHOUT SLASH) safari redirect you correctly (to this with slash) but without auth token in Authorization header (header is not forwarded). Also chrome does the same thing but it redirects Authorization header. – mon io Feb 02 '20 at 18:13
  • Your suggestion solved the problem. Thanks @mon io. – softweave Feb 02 '20 at 21:20

2 Answers2

6

The solution was to add a trailing slash to urls referencing a single object. The DRF Router docs indicate the correct pattern is:

URL pattern: ^users/{pk}/$ Name: 'user-detail'

Whether it's a bug or a feature that Safari doesn't include the authentication token in redirected requests resulting a 401 error, I'll leave to the reader.

softweave
  • 1,455
  • 2
  • 16
  • 27
0

Did you see this ?,I'm not really sure but this discussion may help.

Also, as the error is related to token, try to verify that its sent or added to the request correctly or if it has a type like bearer or somthing.

Also try to log the incoming request headers and its body, so you can make sure that nothing is missing or corrupted.

As this issue happen with DELETE, try to comapre all requests to each other to find out what is missing.

Mahmoud Adel
  • 1,262
  • 2
  • 13
  • 23
  • Thanks for replying. I added Safari's network logging for the delete. Will look into adding server side logging/debugging. – softweave Feb 02 '20 at 16:30
  • So you do a request first, then get redirected, then attempting to do the request again without a token, then get an unauthorized response. Well, for the 3rd and 4th requests there is nothing wrong, there is no token with delete request so you get unauthorized, but why you get redirected after the first request at first place and why the request is being sent again without a token. – Mahmoud Adel Feb 02 '20 at 16:44
  • try to use safari with no extensions or at default setting or something, maybe there is something that makes it misbehaving like that – Mahmoud Adel Feb 02 '20 at 16:46
  • I was seeing but not understanding Safari's network log. Adding a slash to the delete request url solved the problem -- and a host of similar url problems on other pages (e.g. "GET /apis/runs/44/ ) – softweave Feb 02 '20 at 21:01
  • This is odd actually its the first time for me to see this, this drived me to search more about that actually I didn't find much results but this may add more info https://stackoverflow.com/questions/11348479/safari-adds-trailing-slash – Mahmoud Adel Feb 03 '20 at 07:51
  • I want to know more about this so, Did you added a trailing slash in axios's URL so chrome and firefox ingnoring it but safari uses it? or Did you added a condition to handel safari case? – Mahmoud Adel Feb 03 '20 at 07:57
  • It appears the trailing slash is required by server. As shown in the server logs I included, both Safari and Chrome had to add the slash with the original url. However, Safari failed to include the auth token when submitting the redirected request. After adding the trailing slash to the axios urls, the server accepts the request immediately. – softweave Feb 03 '20 at 11:05
  • I know about trailing slash in drf router, I didn't mention it because I thought you already disabled it as usual, trailing slash is not a required or a recommended thing or even a standard its just a conventional thing in Django. Its written in the drf router doc you have included. read simple router section https://www.django-rest-framework.org/api-guide/routers/#simplerouter – Mahmoud Adel Feb 03 '20 at 12:39