Zero dependency library for generating a Mastercard API compliant OAuth signature.
Swift 4.2
Before using this library, you will need to set up a project in the Mastercard Developers Portal.
As part of this set up, you'll receive credentials for your app:
- A consumer key (displayed on the Mastercard Developer Portal)
- A private request signing key (matching the public certificate displayed on the Mastercard Developer Portal)
MastercardOAuth1Signer
is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'MastercardOAuth1Signer'
You can then import the framework from Swift:
import MastercardOAuth1Signer
Note: Use of this library as a pod requires Xcode 10 or later.
You can use the utility KeyProvider.swift
to create a SecKey
object representing your developer private key.
For that, simply pass in a bundle path for your PKCS#12 key store along with its password:
let signingKey = KeyProvider.loadPrivateKey(fromPath: certificatePath, keyPassword: "<<PASSWORD>>")!
The method that does all the heavy lifting is OAuth.authorizationHeader()
. You can call into it directly and as long as you provide the correct parameters, it will return a string that you can add into your request's Authorization
header.
let header = try? OAuth.authorizationHeader(forUri: uri, method: method, payload: payloadString, consumerKey: consumerKey, signingPrivateKey: signingKey)
To run the example project, first clone this repo and then pod install
from the project directory.
Example usage:
let uri = URL(string: "https://sandbox.api.mastercard.com/service")!
let method = "GET"
let examplePayload: [String: String] = ["languageId": 1,
"geographicId": 0]
let payloadJSON = (try? JSONSerialization.data(withJSONObject: examplePayload, options: [])) ?? Data()
let payloadString = String(data: payloadJSON, encoding: .utf8)
let consumerKey = "<insert consumer key from developer portal>"
let signingKey = "<initialize private key matching the consumer key>"
let header = try? OAuth.authorizationHeader(forUri: uri, method: method, payload: payloadString, consumerKey: consumerKey, signingPrivateKey: myPrivateKey)
let headers: HTTPHeaders = ["Authorization": header!,
"Accept": "application/json",
"Referer": "api.mastercard.com"]
OpenAPI Generator generates API client libraries from OpenAPI Specs. It provides generators and library templates for supporting multiple languages and frameworks.
To use MastercardOAuth1Signer with a generated client library in Swift 5, follow the below steps:
- Create a new class to which generates and adds an auth header in the URLRequest.
import MastercardOAuth1Signer
class RequestAuthDecorator: NSObject {
static func addAuthHeaders(request: URLRequest) -> URLRequest {
var urlRequest = request
let certificatePath = Bundle(for: RequestAuthDecorator.self).path(forResource: "<<FILENAME>>", ofType: "p12")
let signingKey = KeyProvider.loadPrivateKey(fromPath: certificatePath!, keyPassword: "<<PASSWORD>>")!
let consumerKey = "CONSUMER_KEY"
var payloadString :String? = nil
if urlRequest.httpBody != nil
{
payloadString = String.init(data: urlRequest.httpBody!, encoding: .utf8)
}
let header = try? OAuth.authorizationHeader(forUri: urlRequest.url!, method: urlRequest.httpMethod!, payload: payloadString, consumerKey: consumerKey, signingPrivateKey: signingKey)
urlRequest.setValue(header!, forHTTPHeaderField: "Authorization")
return urlRequest;
}
}
- Create a subclass of 'URLSessionRequestBuilder' & 'URLSessionDecodableRequestBuilder' and override the 'createUrlRequest' method in both classes to insert the auth header in the request.
class CustomURLSessionRequestBuilder<T>: URLSessionRequestBuilder<T> {
override func createURLRequest(urlSession: URLSession, method: HTTPMethod, encoding: ParameterEncoding, headers: [String : String]) throws -> URLRequest {
let request: URLRequest = try super.createURLRequest(urlSession: urlSession, method: method, encoding: encoding, headers: headers);
let requestWithAuthHeader = RequestAuthDecorator.addAuthHeaders(request: request);
return requestWithAuthHeader;
}
}
class CustomURLSessionDecodableRequestBuilder<T:Decodable>: URLSessionDecodableRequestBuilder<T> {
override func createURLRequest(urlSession: URLSession, method: HTTPMethod, encoding: ParameterEncoding, headers: [String : String]) throws -> URLRequest {
let request: URLRequest = try super.createURLRequest(urlSession: urlSession, method: method, encoding: encoding, headers: headers);
let requestWithAuthHeader = RequestAuthDecorator.addAuthHeaders(request: request);
return requestWithAuthHeader;
}
}
- Create a subclass of 'RequestBuilderFactory' to override 'getBuilder' & 'getNonDecodableBuilder'. Make these methods to return above created 'CustomURLSessionRequestBuilder' & 'CustomURLSessionDecodableRequestBuilder' respectively.
class CustomURLSessionRequestBuilderFactory: RequestBuilderFactory {
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type {
return CustomURLSessionRequestBuilder<T>.self
}
func getBuilder<T:Decodable>() -> RequestBuilder<T>.Type {
return CustomURLSessionDecodableRequestBuilder<T>.self
}
}
- Open the generated
APIs.swift
and assign theCustomURLSessionRequestBuilderFactory
to requestBuilderFactory in 'OpenAPIClientAPI' class.
public static var requestBuilderFactory: RequestBuilderFactory = CustomURLSessionRequestBuilderFactory()
See also:
- Luke Reichold, luke@reikam.com
- Mastercard