I am using Basic Authentication in my project. To get the token, I send a get request, get the token object, store it as NSUserDefault and I need attach this token to all of my API calls (besides login of course).
What is the right way of making API calls with a token in AFNetworking/RestKit?
This is what my token object looks like:
response.body={"Id":"84f4faf2","TokenValidity":"1.00:00:00","ValidTo":"2013-11-02T04:24:00.0817221Z","Parameters":{"AccountId":"1041"},"Token":"sF6G3czrqZmm70FtDKZxDoNC21tglUvo1+HqraqQU/Y="}
To get the token I subclassed the AFHTTPClient and made the token call as described in Stack Overflow question Using AFNetworking and HTTP Basic Authentication.
Currently I store the response body to id response object, set the create a NSUserDefault from that object and tried to call it.
This is how I get the token
#import "AFHTTPClient.h"
#import <AFNetworking/AFHTTPClient.h>
@interface SBAPIManager : AFHTTPClient
-(void)setUsername:(NSString *)username andPassword:(NSString *)password;
- (void)setAuthorizationHeaderWithToken:(NSString *)token;
+(SBAPIManager *)sharedManager;
@end
#import "SBAPIManager.h"
#import "AFNetworking/AFJSONRequestOperation.h"
#import "AFNetworking/AFNetworkActivityIndicatorManager.h"
@implementation SBAPIManager
#pragma mark - Methods
-(void)setUsername:(NSString *)username andPassword:(NSString *)password
{
[self clearAuthorizationHeader];
[self setAuthorizationHeaderWithUsername:username password:password];
}
-(void)setAuthorizationHeaderWithToken:(NSString *)token
{
[self setAuthorizationHeaderWithToken:token];
}
#pragma mark - initialization
-(id)initWithBaseURL:(NSURL *)url
{
self = [super initWithBaseURL:url];
if (!self)
return nil;
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:@"Accept" value:@"application/json"];
[self setParameterEncoding:AFJSONParameterEncoding];
[[AFNetworkActivityIndicatorManager sharedManager]setEnabled:YES];
return self;
}
#pragma mark - singleton methods
+(SBAPIManager *)sharedManager
{
static dispatch_once_t pred;
static SBAPIManager *_sharedManager =nil;
dispatch_once(&pred, ^{_sharedManager =[[self alloc]initWithBaseURL:[NSURL URLWithString:@"https://qstage.azurewebsites.net"]]; });
return _sharedManager;
}
@end
[[SBAPIManager sharedManager]setUsername:_nickname andPassword:_StoreIdentifierForVendor];
[[SBAPIManager sharedManager]getPath:@"/Accounts/Token" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSUserDefaults *TokenSession = [NSUserDefaults standardUserDefaults ];
[TokenSession setObject:responseObject forKey:@"TOKEN"];
NSLog(@"JSON");
NSLog(@"token %@",[self Token]);
} failure:^(AFHTTPRequestOperation *operation,NSError *error) {
//Error stuff here
}];
} failure:nil];
}
After creating the TokenSession object I do a Base64 encoding to TokenSession and use it with setAuthorizationHeaderWithToken method right before making an API call. But I get an [__NSCFDictionary dataUsingEncoding:]: unrecognized selector sent to instance
error. So before I try to fix this, I would appreciate, if someone can tell me, whether the way I am doing is the right way of making API calls or not.
The responseObject
you receive and store into user defaults is a dictionary (because you have configured AFNetworking to automatically deserialise JSON for you). So when you come to use it as a string you get an exception.
You either need to complete the download to just get the JSON string or you need to re serialise the dictionary (NSJSONSerialization
) into a string before you try to use it.