Signing the HTTP Request
Sign the canonical request and send the custom authorization header to the Apple News API.
Overview
When communicating using HTTP protocol, the server validates the identity of the client and provides authorization for specific actions. By signing the HTTP request, the Apple News API authenticates the client and authorizes your news channel. See About the Apple News Security Model.
On this page, you’ll learn how to:
Create a canonical request.
Sign the canonical request.
Create a custom authorization header.
Send the header and the request to the Apple News API.
Copy This Code
Open any text editor to copy this code. Save the file as read_channel.py.
import base64
import hmac
import requests
import sys
from datetime import datetime
import hashlib
class PublisherAPI:
channel_id = ""
current_action = ""
key_id = ""
key_secret = ""
url = ""
def send_request(self, method, url, content_type=None):
date = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
canonical_request = method + url + date
canonical_request = canonical_request.encode()
signature = self.create_signature(canonical_request)
authorization = "HHMAC; key=%s; signature=%s; date=%s" % (
self.key_id, signature, date)
headers = {"Authorization": authorization}
return requests.request(method, url, headers=headers)
def create_signature(self, canonical_request):
key_bytes = base64.b64decode(self.key_secret)
message = canonical_request
secret = self.key_secret.encode("utf-8")
signature = base64.b64encode(
hmac.new(key_bytes, message,digestmod=hashlib.sha256).digest()).decode("utf-8")
return signature
def read_channel(self):
method = "GET"
url = self.url + "%s" % self.channel_id
return self.send_request(method, url)
def main(self):
if self.current_action == "readChannel":
response = self.read_channel()
else:
response = {
"status_code": 400,
"response": "{\"errors\":[{\"code\":\"UNKNOWN_COMMAND\"}]}"
}
return response
if __name__ == '__main__':
if not len(sys.argv) > 4:
print ('no or missing arguments')
exit()
publisherAPI = PublisherAPI()
publisherAPI.url = sys.argv[1] + "/channels/"
publisherAPI.channel_id = sys.argv[2]
publisherAPI.key_id = sys.argv[3]
publisherAPI.key_secret = sys.argv[4]
publisherAPI.current_action = "readChannel"
response = publisherAPI.main()
print(response.status_code)
print(response.text)Run the Script
Start the command prompt and change to the directory containing read_channel.py. Run this script to make a properly authenticated Read Channel Information request to the Apple News API. This script takes four arguments: API URL (https://news-api.apple.com), Channel ID, Key ID, and the Secret.
python read_channel.py https://news-api.apple.com channel_id key_id key_secretResult
The server returns a successful response. The response includes information about the channel, as shown here. See Channel and ChannelLinks.
{
"data": {
"createdAt": "2016-06-13T00:25:43Z",
"modifiedAt": "2016-06-13T23:30:05Z",
"id": "42424242-4242-4242-4242-424242424242",
"type": "channel",
"shareUrl": "https://apple.news/Taaaaaaaaaaaaaaaaaaaaaa",
"links": {
"defaultSection": "https://news-api.apple.com/sections/42424242-4242-4242-4242-424242424242",
"self": "https://news-api.apple.com/channels/42424242-4242-4242-4242-424242424242"
},
"name": "My Channel",
"website": "http://mychannel.com"
}
}How It Works
The canonical request combines the method, the URL, and the current date, as shown here:
date = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
canonical_request = method + url + dateThe date is formatted as shown here:
{Year with century as a decimal number}-{Month as a zero-padded decimal number}-{Day of the month as a zero-padded decimal number}T{Hour (24-hour clock) as a zero-padded decimal number}:{Minute as a zero-padded decimal number}:{Second as a zero-padded decimal number}Z
The date format looks like this:
2018-08-10T23:55:11ZThe canonical request looks like this:
GEThttps://news-api.apple.com/channels/{channel-id}2018-08-10T23:57:00ZYou create a custom authorization header by combining the Key ID, the signed canonical request, and the formatted current date, as shown here:
{'HHMAC; key={Key ID}; signature={Signed Canonical Request}; date={Formatted Current Date'}
The header looks like this:
{'Authorization': 'HHMAC; key={Key ID}; signature=1rBvQKZeQ6M3/dVMtv95Dc51V+QViaqUB0bF6exzYtwFinally, you send the header and the request to the Apple News API. The request looks like this:
return requests.request(method, url, headers=headers)