HTTP digest authentication no longer works in our app since iOS 10 due to wrong nonce-count in Authorization: Digest header generated by NSURLSession.
The same code works in iOS 9, but fail to auth in iOS 10
- Create a POST request with NSURLRequest
- Fire it with NSURLSession
- Handle NSURLAuthenticationMethodHTTPDigest in
urlSession(_:didReceive:completionHandler:)
delegate - The server responds with a 401 and qop="auth" string as expected
The app requests again with the Authorization: Digest header set.
According to RFC2617:
nonce-count
This MUST be specified if a qop directive is sent (see above), and MUST NOT be specified if the server did not send a qop directive in the WWW-Authenticate header field. The nc-value is the hexadecimal count of the number of requests (including the current request) that the client has sent with the nonce value in this request. For example, in the first request sent in response to a given nonce value, the client sends "nc=00000001". The purpose of this directive is to allow the server to detect request replays by maintaining its own copy of this count - if the same nc-value is seen twice, then the request is a replay. See the description below of the construction of the request-digest value.
However, the nonce-count start at "nc=00000002" even for the first request in iOS 10, which cause the server to reject it.
Expect server response 200 OK
iOS 9 & Before:
POST /Tunnel/Message.aspx HTTP/1.1
Host: 172.18.70.12:3454
Accept: */*
Content-Type: application/xml
User-Agent: iViewer/1 CFNetwork/758.5.3 Darwin/15.6.0
Connection: keep-alive
Cookie:
AuthType: digest
Accept-Language: zh-tw
Content-Length: 69
Accept-Encoding: gzip, deflate
Authorization: Digest username="admin", realm="ND8422P",
nonce="cc17a78cdd96d54e012eadefe7d13d82", uri="/Tunnel/Message.aspx",
response="51587db4bcf6eeece68c4ec21108f170",
cnonce="47b8df8a980f280038834b7817250e90", nc=00000001, qop="auth"
<?xml version="1.0" encoding="UTF-8"?><GetServerInfo></GetServerInfo>
HTTP/1.0 200 OK
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Content-Type: text/xml
Content-Length: 1127
iOS 10:
POST /Tunnel/Message.aspx HTTP/1.1
Host: 172.18.70.12:3454
Accept: */*
Content-Type: application/xml
User-Agent: iViewer/1 CFNetwork/808.0.2 Darwin/16.0.0
Connection: keep-alive
Cookie:
AuthType: digest
Accept-Language: en-us
Content-Length: 69
Accept-Encoding: gzip, deflate
Authorization: Digest username="admin", realm="ND8422P",
nonce="4b8bf8549da0c3010f031472e95f387d", uri="/Tunnel/Message.aspx",
response="91cf44bc0aadf2f743164d03b5c708c7",
cnonce="b5f9e6c69e19c1b396298d68f2aefe7e", nc=00000002, qop="auth"
<?xml version="1.0" encoding="UTF-8"?><GetServerInfo></GetServerInfo>
HTTP/1.0 401 Unauthorized
WWW-Authenticate: Digest qop="auth", realm="ND8422P", nonce="8e8b0538bb08876ac4d8203f1d14e9ac"
CSeq: 0
Is anyone facing the same issue?
The only related post I could find is: Apple Developer Forums : Problem of the digest authentication, but no further information.
How do you fix it or get workaround on client app side without asking server side to ignore the wrong nonce-count?
Thanks.
We have the same problem in our company as described here: Cordova app can't connect with Dynamics NAV Web-Service (ODATA) after update to iOS 10
We can reproduce the issue both in our App and the Safari Browser with iOS 10 devices. There does not seem to be a simple client side workaround. We opened a Bug Report with Apple.
Chances are, the OS is sending a HEAD request first, and your server-side code isn't getting it. I would try running Charles Proxy to verify that this is what's happening.
That said, skipping a nonce count is not inherently an indication of any sort of attack. It could occur even in iOS 9 if a request got lost somehow (e.g. a network error). What's important is to ensure that the count doesn't go backwards. So I would argue that your server code is buggy and should not be rejecting that to begin with.
Apple Developer Technical Support confirm that is a bug of iOS 10. Hope it will be fixed soon.
Update: Apple fixed this issue in iOS 10.2 Beta 3
In our case the problem was solved with the 10.2 Beta release.