Using App Store Connect API with Fastlane Match

⋅ 6 min read ⋅ Fastlane

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.

  1. Issuer ID.
  2. Key ID.
  3. Key file or Key content.

I will show you how to generate these three in the next section.

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.

  1. Log in to App Store Connect.
  2. Select Users and Access.
  3. Select the API Keys tab.
  4. Click Generate API Key or the Add (+) button.
  5. Enter a name for the key. The name is for your reference only and is not part of the key itself.
  6. 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.
  7. Click Generate.

The new key's name, key ID, a download link, and other information appear on the page.

Your newly created key will show up on the page.
Your newly created key will show up 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.

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

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 Tweet Share
Previous
How 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.

Next
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.

← Home