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

aporat/AFSignedHTTPRequestOperationManager

Repository files navigation

AFSignedHTTPRequestOperationManager

Build Status    

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

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