Hello,
I am trying to create a certificate via App Store Connect API.
First, I created csr by the following command. I confirmed that the generated csr can be successfuly registered to developer.apple.com manually.
openssl genrsa 2048 > private.key
openssl req -new -key private.key -out private.csr -subj "/emailAddress=<my email address>/O=<my name>/C=JP"
Then, I tried to create a certificate using certificates API. The token is generated using an API key with Developer role (I tried also Admin and AppManager role and all are same).
curl -i \
-H'Authorization: Bearer <token>' \
-H'Content-Type: application/json' \
-d '{"data":{"attributes":{"certificateType":"IOS_DISTRIBUTION","csrContent":"'$(cat private.csr | base64)'"},"type":"certificates"}}' \
https://api.appstoreconnect.apple.com/v1/certificates
The response was:
HTTP/1.1 401 Unauthorized
Server: daiquiri/3.0.0
Date: Tue, 29 Oct 2019 03:31:38 GMT
Content-Type: application/json
Content-Length: 350
Connection: keep-alive
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Request-ID: QUKNKFNK2BDNPUUDIDEHJY7W
X-Rate-Limit: user-hour-lim:3600;user-hour-rem:3592;
x-daiquiri-instance: daiquiri:18493001:mr85p00it-hyhk03154801:7987:19N28
{
"errors": [{
"status": "401",
"code": "NOT_AUTHORIZED",
"title": "Authentication credentials are missing or invalid.",
"detail": "Provide a properly configured and signed bearer token, and make sure that it has not expired. Learn more about Generating Tokens for API Requests https://developer.apple.com/go/?id=api-generating-tokens"
}]
}
This error message says that my token is wrong or missing. Next, so I checked if the token is valid or not by invoking other API.
curl -i \
-H'Authorization: Bearer <token>' \
https://api.appstoreconnect.apple.com/v1/certificates
This API call succeeded and showed the list of my certificates.
Are there something wrong in my commands?
(I wonder that the api is not available currently...)
Appendix: my ruby script to generate jwt
require 'jwt'
require 'base64'
require 'optparse'
params = {}
opt = OptionParser.new
opt.on('-i val', '--iss') { |v| params[:iss] = v }
opt.on('-k val', '--kid') { |v| params[:kid] = v }
opt.parse!
private_key = STDIN.readlines.join
key = OpenSSL::PKey::EC.new(private_key)
payload = {
iss: params[:iss],
exp: Time.now.utc.to_i + 10 * 60,
aud: 'appstoreconnect-v1'
}
header_fields = {
"kid": params[:kid],
"typ": 'JWT'
}
token = JWT.encode(payload, key, 'ES256', header_fields=header_fields)
puts token
Thank you.