1

I am using restkit to login and map the objects of highrise api. I am able to login using /me.xml but stuck after that to fetch the other endpoints like people.xml, tasks.xml etc.

The code for login:

//MYObjectManager is a class inherited from RKObjectManager.

NSURL *url = [NSURL URLWithString:BASE_URL];    
MYObjectManager *sharedManager  = [self managerWithBaseURL:url];
sharedManager.requestSerializationMIMEType = RKMIMETypeXML;
[RKMIMETypeSerialization registerClass:[RKXMLReaderSerialization class] forMIMEType:RKMIMETypeXML];
[sharedManager setAcceptHeaderWithMIMEType:@"application/xml"];
[sharedManager.HTTPClient setAuthorizationHeaderWithUsername:USERNAME password:PASSWORD];

A class UserManager inherited from MYObjectManager for user to load authenticated user as:

    - (void) loadAuthenticatedUser:(void (^)(User *))success failure:(void (^)(RKObjectRequestOperation *, NSError *))failure {
        RKResponseDescriptor *authenticatedUserResponseDescriptors = [RKResponseDescriptor responseDescriptorWithMapping:[MappingProvider userMapping] method:RKRequestMethodGET pathPattern:nil keyPath:@"user" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

       [self addResponseDescriptor:authenticatedUserResponseDescriptors];

       [self getObjectsAtPath:@"me.xml" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
        if (success) {
            User *currentUser = (User *)[mappingResult.array firstObject];            
            success(currentUser);
          }
        } failure:^(RKObjectRequestOperation *operation, NSError *error) {
          if (failure) {
            failure(operation, error);
        }
   }];
}

This works and returns me the token. But now with the use of this token also i am not able to make further requests (seems some cookies are not set by restkit, may be) ContactManager inherited from MYObjectManager as well.

In the success block of user i am making request for people.xml as:

[[UserManager sharedManager] loadAuthenticatedUser:^(User *user) {
    self.apiToken = user.utoken;
    if(self.apiToken){
       // [[ContactManager sharedManager].HTTPClient setDefaultHeader:@"Authorization" value: [NSString stringWithFormat:@"Basic %@", self.apiToken]];

        [[ContactManager sharedManager].HTTPClient setAuthorizationHeaderWithToken:[NSString stringWithFormat:@"Basic %@", self.apiToken]];

        [[ContactManager sharedManager] loadContacts:^(ContactList *contacts) {
            NSLog(@"contacts is: %@", contacts);
        }failure:^(RKObjectRequestOperation *operation, NSError *error){
            NSLog(@"contacts error occured: %@", error);
        }];
    }
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    NSLog(@"login error occured: %@", error);
}];

But this gives error of 401 unauthorized. What is missing? Any help is appreciated.

EDIT - Request and reponses are as follows:

Request header sent for login

restkit.network:RKObjectRequestOperation.m:148 GET 'https://dws10.highrisehq.com/me.xml':
request.headers={
    Accept = "application/xml";
    "Accept-Language" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5";
    Authorization = "Basic ZGlwaWthLmFiYmFkOmRpcGlrYTEyMw==";
    "User-Agent" = "TemplateApp/1.0 (iPhone Simulator; iOS 7.0.3; Scale/2.00)";
}

Response header recieved:

restkit.network:RKObjectRequestOperation.m:218 GET 'https://dws10.highrisehq.com/me.xml' (200 OK / 1 objects) [request=27.9217s mapping=0.0433s total=28.4159s]:
response.headers={
    "Cache-Control" = "private, max-age=0, must-revalidate";
    Connection = "keep-alive";
    "Content-Length" = 447;
    "Content-Type" = "application/xml; charset=utf-8";
    Date = "Thu, 19 Jun 2014 13:41:48 GMT";
    Etag = "\"6315ed097b16e809367d5e5243e719ea\"";
    Server = nginx;
    Status = "304 Not Modified";
    "Strict-Transport-Security" = "max-age=31536000";
    "Timing-Allow-Origin" = "*";
    "X-Frame-Options" = SAMEORIGIN;
    "X-Request-Id" = ee68caa2005ffad955f12175a619b0f3;
    "X-Runtime" = 94;
    "X-Throttle-Count" = 1;
    "X-Throttle-Horizon" = "2014-06-19T13:41:50Z";
    "X-Throttle-Max" = 500;
}

response.body=<?xml version="1.0" encoding="UTF-8"?>
<user>
  <created-at type="datetime">2014-06-19T09:39:44Z</created-at>
  <id type="integer">1045054</id>
  <token>my token value here</token>
  <updated-at type="datetime">2014-06-19T09:39:44Z</updated-at>
  <dropbox>dropbox@09235795.dws10.highrisehq.com</dropbox>
  <name>Dipika Abbad</name>
  <email-address>abbad.deepika@gmail.com</email-address>
  <admin type="boolean">true</admin>
</user>

request header for people i sent is:

restkit.network:RKObjectRequestOperation.m:148 GET 'https://dws10.highrisehq.com/people.xml':
request.headers={
    Accept = "application/xml";
    "Accept-Language" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5";
    Authorization = "Basic <my api token from above response body>";
    "User-Agent" = "TemplateApp/1.0 (iPhone Simulator; iOS 7.0.3; Scale/2.00)";
}

response recieved:

response.body=HTTP Basic: Access denied.
2014-06-19 19:19:31.797 TemplateApp[3403:a0b] contacts error occured: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (200-299), got 401" UserInfo=0xbd6f8d0 {NSLocalizedRecoverySuggestion=HTTP Basic: Access denied.
, AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest: 0xb9e3b60> { URL: https://dws10.highrisehq.com/people.xml }, NSErrorFailingURLKey=https://dws10.highrisehq.com/people.xml, NSLocalizedDescription=Expected status code in (200-299), got 401, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0xbd8b0a0> { URL: https://dws10.highrisehq.com/people.xml } { status code: 401, headers {
    "Cache-Control" = "no-cache";
     Connection = "keep-alive";
    "Content-Length" = 27;
    "Content-Type" = "text/html; charset=utf-8";
    Date = "Thu, 19 Jun 2014 13:49:30 GMT";
    Server = nginx;
    Status = "401 Unauthorized";
    "Strict-Transport-Security" = "max-age=31536000";
    "Www-Authenticate" = "Basic realm=\"Application\"";
    "X-Frame-Options" = SAMEORIGIN;
    "X-Request-Id" = 9a420bfa16fa4620eeb9469e5ad7345d;
    "X-Runtime" = 5;
    "X-Throttle-Count" = 1;
    "X-Throttle-Horizon" = "2014-06-19T13:49:40Z";
    "X-Throttle-Max" = 500;
} }}
Dips
  • 93
  • 1
  • 1
  • 8
  • Show the headers you do get, and you should know what the server is expecting if you want to be able to match it. – Wain Jun 19 '14 at 18:00

2 Answers2

0

Put the following in your app delegate:

RKLogConfigureByName("RestKit/Network", RKLogLevelTrace); 
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);

And see the console to inspect the requests and verify if you are setting the correct headers

Sandro Machado
  • 9,921
  • 4
  • 36
  • 57
  • Hey that did help a lot, Thanks ! Thing is i have no clear idea about what it needs in header. I tried to just pass Authorization header in format - 1) Basic 2) Bearer 3) token but none worked. – Dips Jun 19 '14 at 15:45
  • You should have an header like: "Authorization: Basic XXXTOKENXXX" – Sandro Machado Jun 19 '14 at 16:21
  • This answer is currently a comment and needs more detail. – Wain Jun 19 '14 at 18:00
  • Ok Try to create a string like: req.Headers["Authorization"] = "Basic " + Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(String.Format("{0}: {1}", userName, userPassword))); But In objective C. You can find more information here: https://groups.google.com/forum/#!topic/37signals-api/UED1WPJsFKg – Sandro Machado Jun 20 '14 at 09:43
  • I already did try to form a base64 form of string "username:password" and sent as Authorization: Basic but still error 401 – Dips Jun 20 '14 at 11:38
  • Infact i also tried to send string as apitoken:password as mentioned in highrise api doc [here](https://github.com/basecamp/highrise-api), but still of no use. – Dips Jun 20 '14 at 11:39
  • Both the below two lines of code gives same value for "Authorization" header key. So i guess restkit internally does the base64 conversion. `[sharedManager.HTTPClient setAuthorizationHeaderWithUsername:USERNAME password:PASSWORD];` `//[sharedManager.HTTPClient setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Basic %@",[sharedManager base64String:[NSString stringWithFormat:@"%@:%@", USERNAME, PASSWORD]]]];` – Dips Jun 20 '14 at 12:29
  • try the example in github(https://github.com/basecamp/highrise-api) but with your api token to validate if it is a problem with your token: curl -u 605b32dd:X https://example.highrisehq.com/people/1.xml – Sandro Machado Jun 20 '14 at 14:13
  • the token is same in highrise account.. i have compared them – Dips Jun 20 '14 at 15:18
0

Issue solved. It need to set Username as the token and password the dummy one.

Dips
  • 93
  • 1
  • 1
  • 8