Skip to content

Apple Business Manager in Okta Workflows

A few months back, Apple released an update to Apple Business Manager and Apple School Manager to allow API access to customers. Apple has thoroughly documented the API

I tried to implement the new API in Okta Workflows, and got it mostly working, but I wasn’t happy with it.

Apple requires an assertion which can live up to 180 days. Once you have that assertion, you can request a bearer token, and with that bearer token, you can perform API calls. 

Bart Reardon created a shell script that requests that assertion. What I had done was take that assertion generated by the script, and used it as an input. That would mean, that twice a year, I’d need to run the shell script on my local computer and replace that assertion. That’s a sloppy workflow that I was unhappy with. I spent a long time trying to troubleshoot how to get Workflows to generate the assertion on my behalf and discard it as needed. Eventually I gave up, but asked a colleague to take a look and see if he can get it working.

JM spent some time and came up with this solution. 

When setting up the ABM connector, you’ll need to pass through authentication parameters. All of these are outlined in Bart Reardon’s script above. They are setup in Apple Business Manager, where you can generate those unique values and create the credentials in Okta Workflows.

Settings and authentication details for the Apple Business Manager connector including key, description, icon, accent color, and authentication parameters.

Okta Workflows require a few flows to create a new connector. 

First we need the httpHelper which is the meat of the connector. It calls the API and passes the data you will be passing it.

Let’s take a closer look at each card. 

User interface of a helper flow in Okta Workflows showing input fields for relative URL, bearer token, and method, along with authentication parameters like client ID and private key.
Screenshot of a concatenation action in Okta Workflows, showing text input fields for constructing a full URL using a base URL and a relative URL.

EDIT: While v1 is the current version of the API, this may change in the future. You may choose to have the user input the version into the card rather than having it hard-coded. If Apple moves some endpoints to v2 and other not, this will break. For the moment, I’m happy having the version in the connector instead of the individual workflows, because if Apple updates everything, then I can change it with one change, but I want to warn those who may be reading this.

Okta Workflows interface showing a concatenate action to create a bearer token string.
Okta Workflows interface showing the 'Construct' object with authorization input and header field.
A screenshot of the HTTP Raw Request settings in Okta Workflows, showing fields for URL, method, headers, query, and body.
User interface of a flow control return card in a workflow automation tool, displaying fields for status code, headers, and body.

Next we need to get the bearer token, and that is where JM’s magic happened. 

A user interface for a connector action in Okta Workflows showing authentication parameters such as client_id, key_id, and private_key, along with options, inputs, and selected outputs.
A screenshot of a workflow showing text replacement settings to strip the 'BEGIN PRIVATE KEY' and 'END PRIVATE KEY' from a private key string in Okta Workflows.
A text interface displaying a 'Compose' element with a private key format, including 'BEGIN PRIVATE KEY' and 'END PRIVATE KEY' headers.

First we strip the header and footer from the private key, and then we add it back in. We weren’t able to get Apple to spit out a proper assertion without doing this step.

Flow setup in Okta Workflows for generating JWT header elements including date and unique ID.

Singing a JWT requires a few things, the current date, the algorithm, the key id, the type, a unique id called jwid.

JWT Sign card interface in Okta Workflows with fields for private key, audience, issuer, expiration, JWT ID, timestamp options, and assertion header.

Now we can use the JWT Sign card.

Screenshot of a text manipulation interface showing fields for URL components and parameters for an API request in Okta Workflows.

EDIT: While Apple’s docs specify that one should put the assertion in the url, best practice and the Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants wants that data sent in the body. I have no tested this connector with the assertion in the body, but please do and report back.

We are then ready to generate the header and ship that data off to Apple.

Interface showing settings for a raw HTTP request in Okta Workflows, including fields for URL, method, headers, query, and body.

Then we can parse the output and use it elsewhere.

Interface showing 'Get Multiple' function with fields for 'access_token', 'token_type', 'expires_in', and 'scope' in Okta Workflows.

Next we can build a flow called Custom API action, which will allow us to call any API endpoint using the bearer token information before.

An illustration of a flow setup in Okta Workflows showing the components 'Connector Action', 'Call Flow', and 'Return Outputs' with various input fields and settings.

The final flow is called “_authPing” which checks to see if it can communicate with the new service and shows a green dot if it can.

A visual representation of an Okta Workflows setup showing the connector authentication process, including steps for getting a bearer token and returning the status of the connection.
User interface for Connector Authping showing authentication parameters including client_id, key_id, and private_key.
Screenshot of Okta Workflows displaying the 'Call Flow' card for 'Get Bearer Token' with input fields for 'Connection' and 'expires_in', and an 'Assign' card indicating successful connection.

Let’s see it in action.

In this example, we first called Get Bearer Token, which will get the assertion and then the bearer token, it will then provide that token as an output. We can then use that in a card called Custom API Action, which will provide the Endpoint and the bearer token as provided earlier. 

Leave a Reply