cocoa - NSURLRequest with UTF8 password -


here method i've written connect server , user auth token:

+ (void)getauthtokenforusername:(nsstring *)username                        password:(nsstring *)password               completionhandler:(void (^)(nsstring *, nserror *))completionhandler {     username = [username urlencodedstring];     password = [password urlencodedstring];      nsstring *format = @"https://%@:%@@api.example.com/v1/user/api_token?format=json";     nsstring *string = [nsstring stringwithformat:format, username, password];     nsurl *url = [nsurl urlwithstring:string];     [nsurlconnection sendasynchronousrequest:[nsurlrequest requestwithurl:url]                                        queue:[nsoperationqueue mainqueue]                            completionhandler:^(nsurlresponse *urlresponse, nsdata *data, nserror *error)     {         nsstring *token;         if (data) {             nsdictionary *dictionary = [nsjsonserialization jsonobjectwithdata:data options:0 error:&error];             token = [nsstring stringwithformat:@"%@:%@", username, dictionary[@"result"]];         }         completionhandler(token, error);     }]; } 

a url looks this: https://username:hello%c2%b0@api.example.com/v1/user/api_token?format\=json, password hello°. urlencodedstring method encodes in example, request never works. problem not escaping or server, because can curl same url , nice json , authentication works, though there non-ascii character in password. works other programming languages ruby or python. same url never works nsurlconnection , doesn't work in safari, of course uses nsurlconnection. 'the operation not completed' '401 forbidden' every time.

(my code works fine when password contains ascii characters. tried using nsurlcredential methods, same problem.)

what need nsurlconnection work such url https://username:hello%c2%b0@api.example.com/v1/user/api_token?format\=json password contains non-ascii characters?

i have performed several tests against mockup server , think have solution you.

first of all, when add username & password url, not send server part of url. sent part of authorization header (see basic access authentication).

the fastest workaround do

nsurlrequest* request = [nsurlrequest requestwithurl:url]; nsstring* usernamepassword = [[nsstring stringwithformat:@"%@:%@", username, password] base64encode]; [request setvalue:[nsstring stringwithformat:@"basic %@", usernamepassword] forhttpheaderfield:@"authorization"]  

to understand problem, let's go bit deeper. let's forget nsurlconnection sendasynchronousrequest: , let create old-fashioned connection nsurlconnectiondelegate. in delegate, let's define following methods:

- (bool)connection:(nsurlconnection *)connection canauthenticateagainstprotectionspace:(nsurlprotectionspace *)protectionspace {     return yes; }  - (void)connection:(nsurlconnection *)connection didreceiveauthenticationchallenge:(nsurlauthenticationchallenge *)challenge {     nslog(@"proposal: %@ - %@", challenge.proposedcredential.user, challenge.proposedcredential.password);      nsurlcredential* credential = [nsurlcredential credentialwithuser:@"username"                                                                  password:@"hello°"                                                           persistence:nsurlcredentialpersistencenone];      [challenge.sender usecredential:credential forauthenticationchallenge:challenge]; } 

if don't create these methods, username & password url won't ever added http header. if add them, you'll see proposed password hello%c2%b0. obviously, that's wrong.

you can see problem directly from

nslog(@"password: %@", [[nsurl urlwithstring:@"http://username:hello%c2%b0@www.google.com"] password]); 

which prints

hello%c2%b0   

i believe bug in framework. nsurl returns password encoded , nsurlcredential doesn't decode left invalid password.


Comments

Popular posts from this blog

linux - xterm copying to CLIPBOARD using copy-selection causes automatic updating of CLIPBOARD upon mouse selection -

c++ - qgraphicsview horizontal scrolling always has a vertical delta -