I have the following architecture: iOS client uses NSURLConnection with willSendRequestForAuthenticationChallenge
to auth against Django-rest-framework based REST service. It works fine when login is ascii only, but when I use non-ascii letters, it even does not send HTTP_AUTHORIZATION
!
That is probably because RFC does not cover non-ascii chars in HTTP basic auth.
What is the best approach to solve it? Will digest auth help?
I can't encode login to url, since I do not want it to be displayed in server logs. And I also want to stay with willSendRequestForAuthenticationChallenge
.
PS: I can use form-based auth or json-based on Django side (by implementing BaseAuthentication
) but on iOS I will need to create NSURLAuthenticationChallenge
which seems to be a big deal
Generally you would be out of luck with both HTTP Basic & Digest authentication, it's only ASCII characters and there's simply no way to get around that.
However, because you're controlling the backend then you can use this trick: encode both the username and password in base64 on the iOS side like this:
NSData *usernameData = [username dataUsingEncoding:NSUTF8StringEncoding];
NSString *usernameBase64 = [usernameData base64EncodedStringWithOptions:0];
Then create your NSURLCredential
with the encoded strings. Since HTTP Basic Authentication already encodes the credentials in base64, by doing this you will be encoding the credentials twice before sending them to the server.
Now on the DRF side, create a subclass of BasicAuthentication
and call it Base64BasicAuthentication
for instance. Override authenticate_credentials
like this:
def authenticate_credentials(self, userid, password):
userid = base64.b64decode(userid)
password = base64.b64decode(password)
return super(Base64BasicAuthentication, self).authenticate_credentials(userid, password)
And then just use the Base64BasicAuthentication
as your default auth class in Django REST Framework. It's a bit of a hack, but it should do the job.