Skip to content

Automatically sign AFNetworking api requests with SHA-256 hash signature and timestamp

License

Notifications You must be signed in to change notification settings

cenllv/AFSignedHTTPRequestOperationManager

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AFSignedHTTPRequestOperationManager

   Dependency Status

Automatically sign AFNetworking api requests with SHA-256 hash signature and timestamp.

Sample usage is available in the example project.

The purpose of the SHA256 signature is to guarantee that restful API requests are being delivered only by authorized api clients.

For example,

    [[APIClient sharedClient] POST:@"/users" parameters:@{@"some" : @"parameters"} success:^(AFHTTPRequestOperation *operation, id responseObject) {
        
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        
    }];

will generate a set of auth parameters which can be verified on the server.

{
  :some           => "parameters",
  :auth_timestamp => 1273231888,
  :auth_signature => "28b6bb0f242f71064916fad6ae463fe91f5adc302222dfc02c348ae1941eaf80",
  :auth_version   => "2",
  :auth_key       => "my_key"
}

Requirements

AFSignedHTTPRequestOperationManager reiles on AFNetworking 2.0 and IGDigest.

Installation

CocoaPods

Add the following line to your Podfile:

pod 'AFSignedHTTPRequestOperationManager'

Then run the following in the same directory as your Podfile:

pod install

Manual

Copy the folder src to your project.

Usage

AFSignedHTTPRequestOperationManager is a subclass of AFHTTPRequestOperationManager, so use the class as a normally use a AFNetworking api client.

extend AFSignedHTTPRequestOperationManager

#import "AFSignedHTTPRequestOperationManager.h"

@interface APIClient : AFSignedHTTPRequestOperationManager

+ (instancetype)sharedClient;

@end
#import "APIClient.h"

@implementation APIClient

+ (instancetype)sharedClient {
    static APIClient *_sharedClient = nil;
    static dispatch_once_t onceKosherPenguinToken;
    dispatch_once(&onceKosherPenguinToken, ^{
        _sharedClient = [[APIClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://www.example.com"]];
    });
    
    return _sharedClient;
}

- (id)initWithBaseURL:(NSURL *)url {
    self = [super initWithBaseURL:url];
    if (self) {
        self.responseSerializer = [AFJSONResponseSerializer serializer];
        self.clientId = @"CLIENT_ID";
        self.clientSecret = @"CLIENT_SECRET";
    }
    
    return self;
}


@end

Call your API

    [[APIClient sharedClient] POST:@"/users" parameters:@{@"site_id" : @10} success:^(AFHTTPRequestOperation *operation, id responseObject) {
        
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        
    }];

On the backend

Ruby - Use https://github.com/mloughran/signature

PHP Example

    $client_id = 'CLIENT_ID';
    $client_secret = 'CLIENT_SECRET';

    $auth_version = $app->request->params('auth_version');
    $auth_client_id = $app->request->params('auth_client_id');
    $auth_signature = $app->request->params('auth_signature');
    $auth_timestamp = $app->request->params('auth_timestamp');

    if ($auth_version != "2") {
        throw new Exception('Incorrect client version');
    }

    if ($auth_client_id != $client_id) {
        throw new Exception('Incorrect client id');
    }
  
    if ($auth_timestamp <= time() - (60*60*12) || $auth_timestamp >= time() + 60*60*12) {
        throw new Exception('Incorrect auth timestamp');
    }

    
    // generate the auth_signature
    $params = $app->request->params();
    ksort($params);
    
    foreach ($params as $key => $value) {
        if (substr($key, 0, 5)=='auth_') {
            unset($params[$key]);
        }
    }
    
    $signatureString = '';
    foreach ($params as $key => $value) {
        
        if (is_array($value)) {
            foreach ($value as $item) {
                $signatureString[] = $key . '[]=' . $item;
            }
        } else {
            $signatureString[] = $key . '=' . $value;
        }
    }
    
    $signatureString = $app->request->getMethod() . "\n" . urldecode($app->request->getPathInfo()) . "\n" . urldecode(implode('&', $signatureString));
    $checksum = hash_hmac('sha256', $signatureString, $client_secret);
    
    if ($checksum!=$auth_signature) {
        throw new Exception('Incorrect auth signature ' . $signatureString);
    }

About

Automatically sign AFNetworking api requests with SHA-256 hash signature and timestamp

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Objective-C 99.6%
  • Ruby 0.4%