API Authentication
App Store for Intune uses JWT bearer tokens issued by your Entra ID tenant. Every API request
carries Authorization: Bearer <token>, and the API validates the issuer, the tenant and the audience
before it looks at anything else.
There are two supported ways to authenticate, and neither uses a client secret or a certificate.
| Interactive | Unattended | |
|---|---|---|
| Who is calling | A signed-in person | A workload identity you control |
| Token | Delegated, scope access_as_user | Application, with an App Store role |
| Registration | The App Store app registration | A separate, credentialless workload API registration |
| Reaches | Everything that person can do in the portal | Seven read endpoints |
| Can approve or reject | Yes | No, ever |
Unattended access is off until your administrator sets it up. If nobody supplied a workload API audience at deployment, this deployment accepts no application token at all.
If you have used an earlier version of this page, the client-credentials flow with a secret it described is gone and is not coming back. What replaced it is described under Unattended: a managed identity.
Prerequisites
Section titled “Prerequisites”- The Application (client) ID of the App Store app registration. Your administrator created it during installation. It is the same registration the portal signs users in against, and it is the only identifier you need.
- A user account that can do what you intend to automate. The API grants that account exactly what it already has, so a script that approves requests must run as somebody entitled to approve them.
You do not need the tenant ID for most libraries, and you do not need an Application ID URI
separate from the client ID: the scope is api://<client-id>/access_as_user.
The app registration needs a desktop platform
Section titled “The app registration needs a desktop platform”Both flows below sign in as a person from a console, which Entra ID treats as a public client. The App Store app registration is created during installation with a Single-page application platform, because that is what the portal’s browser sign-in uses. That platform does not cover a console, so the first token request fails until an administrator adds one more platform.
This is a one-time change, and it does not affect how people sign in to the portal.
- Go to Microsoft Entra admin center > App registrations and select the App Store app registration.
- Select Authentication, then + Add Redirect URI.
- In Select a platform to add redirect URI, select Mobile and desktop applications.
- Tick the suggested
https://login.microsoftonline.com/common/oauth2/nativeclient, and addhttp://localhostin the free-text box. - Select Configure.
For the device code flow, also open the Settings tab and set Allow public client flows to Yes.
Getting a token
Section titled “Getting a token”Any standard Entra client library will do it. What matters is that the token is delegated and names this API’s scope.
Interactive, for a person running a script
Section titled “Interactive, for a person running a script”$clientId = '<the App Store app registration client ID>'$tenantId = '<your tenant ID>'
# Any MSAL-based library works. This example uses the Microsoft Graph PowerShell SDK's# authentication, which is MSAL underneath.Connect-MgGraph -ClientId $clientId -TenantId $tenantId ` -Scopes "api://$clientId/access_as_user"Device code, for a console with no browser
Section titled “Device code, for a console with no browser”Useful on a jump box or over SSH. The same scope applies; the library prints a code to enter on another device.
Calling the API
Section titled “Calling the API”$appStoreHost = 'https://<your-app-store-host>'$headers = @{ Authorization = "Bearer $accessToken" }
$apps = Invoke-RestMethod -Uri "$appStoreHost/api/apps" -Headers $headers$apps | Select-Object id, name, publisher, version | Format-TableThat is the round trip. The supported endpoints are listed in the API reference.
What the API checks
Section titled “What the API checks”- The token is valid: issued by your tenant, for this API’s audience.
- The token is delegated and names
access_as_user. A token with no delegated scope is refused before any endpoint runs. - The person is authorized for what they are asking, from their Entra group membership.
Authentication on its own grants nothing. A valid token belonging to somebody with no role reaches the catalog and their own requests, and nothing else.
Unattended: a managed identity
Section titled “Unattended: a managed identity”For a scheduled job there is no person to sign in, and a job that signs in as a named employee is not unattended automation with extra steps: it breaks when they leave and it inherits everything else they can do.
Instead, the workload authenticates as itself, using an identity Azure manages for it. The first-class case is an Azure Automation Account’s system-assigned managed identity, and the full walkthrough is Call the API from Azure Automation.
There is no secret and no certificate in this path. Azure issues short-lived tokens directly to your workload identity. PowerStacks never receives, stores, rotates or manages a credential for it, and there is nothing for you to put in a vault.
The separate workload registration
Section titled “The separate workload registration”Unattended callers authenticate against a second app registration, distinct from the one people sign in with. It exists only to name an audience and to hold App Store’s application roles, and it carries no client secret, no certificate, no Microsoft Graph permissions and no Intune permissions.
Keeping it separate is the point. The sign-in registration stays exactly what it has always been, so “the registration our staff authenticate against holds no credentials and no application roles” stays a sentence your security reviewer can confirm on one screen. A mistaken role assignment on a registration that exists only to hold roles cannot touch the identity people sign in with.
What a workload token has to prove
Section titled “What a workload token has to prove”Four things, together. Missing any one of them is 403:
- This deployment has unattended access enabled.
- The token was issued for the workload audience, not the sign-in registration’s.
- The token came from your tenant.
- The token carries an App Store application role the API recognises, and the one that endpoint requires.
A token that merely has a roles claim is refused. Entra puts whatever roles your tenant granted
into a token, including roles belonging to entirely unrelated applications, so “has roles” and “is
allowed here” are different questions. An unassigned managed identity gets 403: authenticating
proves who is calling and grants nothing.
What a managed identity can and cannot do
Section titled “What a managed identity can and cannot do”It can read: the catalog, packaging job status, update deployments, and which apps have an update waiting. That is seven endpoints, listed in the API reference.
It cannot change anything at all, and specifically it cannot approve or reject a request. An approval is a named person’s decision, recorded against them. A managed identity has no name in that sense, so the product refuses rather than recording a decision it cannot attribute. That refusal happens before any approval rule is consulted.
Application roles
Section titled “Application roles”| Role | Permits | Never permits |
|---|---|---|
AppStore.Automation.Read | The seven supported reads | Any mutation, any approval decision, anything scoped to a person, anything administrative |
One role, because the automation this was built for is a read: find out what is true, and act on it outside App Store. A role that could change something would be broader than any demonstrated need, and breadth in an unattended credential is expensive to withdraw later.
It does not impersonate anyone
Section titled “It does not impersonate anyone”Application authentication is not delegated access. The workload acts as itself, not on behalf of a person, and the audit trail records it as an application with its service principal’s identity. It is never given a manufactured user identity.
Nor does it borrow App Store’s own privileges. The Intune and Graph work App Store performs is done by the App Service’s system-assigned managed identity, and your caller’s token is never forwarded downstream to Graph or Intune.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause | Fix |
|---|---|---|
401 Unauthorized immediately | The token was not included, or the header is malformed | Confirm the header is Authorization: Bearer <token> with a single space |
401 Unauthorized with a token included | The token’s audience does not match the API | Confirm the scope is api://<client-id>/access_as_user using the App Store registration’s client ID, and that the token came from the right tenant |
403 Forbidden on every endpoint | The token carries no delegated scope. This is what an app-only or client-credentials token looks like to the API | Use a delegated token. App-only authentication is not supported; see above |
403 Forbidden on some endpoints | The signed-in person is not authorized for that operation | The API grants exactly what that person has in the portal. Check their group membership |
429 Too Many Requests | The rate limit kicked in. Limits are per signed-in identity, not per IP address | Back off for the Retry-After interval and retry; if the general limit is wrong for your use case, raise the RateLimiting__RequestsPerMinute app setting (default 300) |
AADSTS500011 from the token request | The scope names a resource Entra cannot find | Confirm the client ID, and that the registration exposes the access_as_user scope |
What’s next
Section titled “What’s next”- API reference: the supported endpoints.
- PowerShell examples: runnable scripts.