HTTP digest authentication fail due to wrong nonce

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.


    Apple Developer Technical Support confirm that is a bug of iOS 10. Hope it will be fixed soon.

    Thank you for contacting Apple Developer Technical Support (DTS). We believe this issue is a bug. Please file a bug report using the Bug Reporter tool https://developer.apple.com/bug-reporting/.

    Update: Apple fixed this issue in iOS 10.2 Beta 3


    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 (eg 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.


    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.

    链接地址: http://www.djcxy.com/p/22296.html

    上一篇: 如何在UIWebView中显示身份验证挑战?

    下一篇: 由于错误的nonce,HTTP摘要认证失败