Using App Store Connect API with Fastlane Match
Table of Contents
Starting February 2021, two-factor authentication or two-step verification will be required for all users to sign in to App Store Connect. This extra layer of security for your Apple ID helps ensure that you’re the only person who can access your account.
From Apple Support
Right now, Apple is enforcing two-factor authentication (2FA) for all accounts. If you don't use any Continuous Integration (CI) and always submit your app via Xcode, you have nothing to worry about. You can checkout Apple suport and enabled 2FA if you don't already have it enabled.
But if you use Fastlane with a username and password authentication for your CI, it is a time for the change.
Apple announced the App Store Connect API back in WWDC18. It provides an official way to interact with App Store Connect, and Fastlane already supports this. Let's see what we need to do to adopt it.
Requirements
To be able to use App Store Connect API, Fastlane needs three things.
- Issuer ID.
- Key ID.
- Key file or Key content.
I will show you how to generate these three in the next section.
You can easily support sarunw.com by checking out this sponsor.
Debug 10x faster with Proxyman: Your ultimate tool to capture HTTPs requests/ responses, natively built for your iPhone and macOS. Special deal for Black Friday: Get 30% off for all Proxyman licenses with code “BLACKFRIDAY2024”.
Creating an App Store Connect API Key
To generate keys, you must have Admin permission in App Store Connect. If you don't have that permission, you can direct the relevant person to this article and follow the following instructions. You need three things at the end of the process.
- Log in to App Store Connect.
- Select Users and Access.
- Select the API Keys tab.
- Click Generate API Key or the Add (+) button.
- Enter a name for the key. The name is for your reference only and is not part of the key itself.
- Under Access, select the role for the key. The roles that apply to keys are the same roles that apply to users on your team. See role permissions.
- Click Generate.
The new key's name, key ID, a download link, and other information appear on the page.
You can grab all three necessary information here.
<1> Issue ID.
<2> Key ID.
<3> Click "Download API Key" to download your API private key. The download link appears only if the private key has not yet been downloaded. Apple does not keep a copy of the private key. So you can download it only once.
Now you got everything you need to use App Store Connect API, let's put it into use.
Using an App Store Connect API Key
The API Key file (p8 file that you download), the key id, and the issuer id are needed to create the JWT token for authorization. There are multiple ways that these pieces of information can be input into Fastlane using Fastlane's new action, app_store_connect_api_key
. I will show only one way to do this. You can learn other ways in fastlane documentation. I show this method because I think it is the easiest way to work with most CI out there, where you can set environment variables.
Use return value and pass in as an option
First, you need to create a JWT token for authorization using the app_store_connect_api_key
action. Then you inject that as an argument to other Fastlane actions (match in this case).
lane :release do
api_key = app_store_connect_api_key(
key_id: ENV['ASCAPI_KEY_ID'],
issuer_id: ENV['ASCAPI_ISSUER_ID'],
key_content: ENV['ASCAPI_KEY_CONTENT']
)
match(
type: 'appstore',
app_identifier: ["com.sarunw.app"],
api_key: api_key,
readonly: true
)
...
end
In this example, we put issuer id, key id, and key content into three environment variables, ASCAPI_ISSUER_ID
, ASCAPI_KEY_ID
, and ASCAPI_KEY_CONTENT
, respectively. Then we call app_store_connect_api_key
with those variables and get back an authentication key for the match
action.
Use the shared value in lane context
Under the hood, the app_store_connect_api_key
action sets shared variable (Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
) for other action to easily use. Other actions (like match
) will automatically load the API Key from Actions.lane_context
if you don't provide api_key
argument.
You can shorten the code to something like this:
lane :release do
app_store_connect_api_key(
key_id: ENV['ASCAPI_KEY_ID'],
issuer_id: ENV['ASCAPI_ISSUER_ID'],
key_content: ENV['ASCAPI_KEY_CONTENT']
)
match(
type: 'appstore',
app_identifier: ["com.sarunw.app"],
readonly: true
)
...
end
Use default ENV name
Each key in Fastlane action has a default environment key that automatically loads if set (and you don't explicitly provide them as method arguments).
Here is the list of defaults key for our parameters.
Key | Description | ENV key |
---|---|---|
key_id | The key ID | APP_STORE_CONNECT_API_KEY_KEY_ID |
issuer_id | The issuer ID | APP_STORE_CONNECT_API_KEY_ISSUER_ID |
key_content | The content of the key p8 file | APP_STORE_CONNECT_API_KEY_KEY |
key_filepath | The path to the key p8 file | APP_STORE_CONNECT_API_KEY_KEY_FILEPATH |
duration | The token session duration | APP_STORE_CONNECT_API_KEY_DURATION |
in_house | Is App Store or Enterprise (in house) | APP_STORE_CONNECT_API_KEY_IN_HOUSE |
So if you set those three keys set in your CI environment variables, you can further shorten the code.
lane :release do
app_store_connect_api_key()
match(
type: 'appstore',
app_identifier: ["com.sarunw.app"],
readonly: true
)
...
end
Caveats
Newline problem
This doesn't happen to me, but if your CI has a problem with a newline character when setting an environmental variable with newline characters (like a private key), you might consider using a base64 encoded version of your private key (p8 file). Reference issue.
To do that, first, encode your p8 file.
cat AuthKey_ABCDEFGH.p8 | base64
Then use an encoded version of your p8 file in key_content
and add the is_key_content_base64
key with a value of true
.
app_store_connect_api_key(
key_id: "D83848D23",
issuer_id: "227b0bbf-ada8-458c-9d62-3d8022b7d07f",
key_content: "Base64_encode_of_-----BEGIN EC PRIVATE KEY-----\nfewfawefawfe\n-----END EC PRIVATE KEY-----",
is_key_content_base64: true
)
Missing some actions
Some actions such as download_dsyms that used to work with cookie-based web session won't work with Appstore Connect API since Apple does not have all endpoint available yet. But this problem should be getting better if Apple keeps updating their API.
You can easily support sarunw.com by checking out this sponsor.
Debug 10x faster with Proxyman: Your ultimate tool to capture HTTPs requests/ responses, natively built for your iPhone and macOS. Special deal for Black Friday: Get 30% off for all Proxyman licenses with code “BLACKFRIDAY2024”.
Conclusion
In this article, I just show you one way to handle the situation, but this isn't the only way. If you interest in other ways to handle this, check out a nice article from Josh Holtz, Lead maintainer of the Fastlane. He goes through all possible scenarios and solutions for each case.
Read more article about Fastlane or see all available topic
Enjoy the read?
If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.
Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.
If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.
Become a patron Buy me a coffee Tweet ShareHow to fix "no identity found - Command CodeSign failed with a nonzero exit code" error in Xcode
There might be several reasons that cause this error. I will share one that just happened to me.
Tuist Template: What is it and how to create them
The template is a way to group repetitive code structure into a reusable component. You will learn how to create them in this article.