0

I am writing an application to authorise itself into Spotify. I used the node app.js example to get things working and an now re-writing natively into Objective C. I have extracted the authorisation code via a callback function

NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://accounts.spotify.com/api/token"]];
request.HTTPMethod = @"POST";


// put in the header fields
NSString *headerString = [NSString stringWithFormat:@"%@:%@",clientID,clientSecret];
NSData *nsdata = [headerString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
base64Encoded = [ NSString stringWithFormat:@"Basic %@", base64Encoded];
[request setValue:base64Encoded forHTTPHeaderField:@"Authorization"];
NSLog(@"request.header %@", request.allHTTPHeaderFields.description);

// put in the body form
NSString * stringData = [NSString stringWithFormat:@"grant_type:%@, code:%@, redirect_uri:\"%@\"", @"authorization_code",authorisationCode,redirectUri];
NSData * requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBodyData;
NSLog(@"request.body %@", [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]);

I then post this request and get {"error":"server_error","error_description":"Unexpected status: 415"} returned.

I have found a variety of questions on this topic revolving around the Content-Type needing to be application/x-www-form-urlencoded but this was no direct cure.

Anyone got any suggestions for me?

Jean-Rémy Revy
  • 5,607
  • 3
  • 39
  • 65
  • I should say that using Postman I have proven that the base64 encoding is correct and that using 'application/x-www-form-urlencoded' works correctly and supplies me with an access_code – Mark Stuart-Walker Feb 04 '17 at 16:33

1 Answers1

0

I found the answer here NSURLRequest : Post data and read the posted page

It appears that the raw data within the HTTPBody needs to be formatted differently - no JSON at all. The above link has a useful function which I updated slightly

-(NSData*)encodeDictionary:(NSDictionary*)dictionary {

NSMutableArray *parts = [[NSMutableArray alloc] init];
for (NSString *key in dictionary) {

    NSString *encodedValue = [[dictionary objectForKey:key] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];
    NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];

    NSString *part = [NSString stringWithFormat: @"%@=%@", encodedKey, encodedValue];
    [parts addObject:part];
}

NSString *encodedDictionary = [parts componentsJoinedByString:@"&"];
return [encodedDictionary dataUsingEncoding:NSUTF8StringEncoding];

}

and ..

[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
//NSLog(@"request.header %@", request.allHTTPHeaderFields.description);

// put in the body form using the new function
NSDictionary * parameters = [[NSDictionary alloc] initWithObjectsAndKeys:@"authorization_code",@"grant_type",authorisationCode,@"code",redirectUri,@"redirect_uri", nil ];
NSData * requestBodyData = [self encodeDictionary:parameters];
request.HTTPBody = requestBodyData;
Community
  • 1
  • 1