Skip to content

Get an app only access token

Jeremy edited this page Dec 24, 2020 · 5 revisions

For this sample, we'll need to create a new Azure AD application, create and upload a self-signed certificate, and assign API permissions. These tasks can all be done using either PowerShell (AzureAD module) or the Azure AD Portal. We'll use the latter option.

Step 1 - Create a new App Registration

Login to the Azure AD Portal then navigate to Azure Active Directory > App Registrations. Select New registration, then give the new app a name, and under Supported account types, select Accounts in this organizational directory only (<tenant name> only - Single tenant), then select Register.

Once the app is created, you'll be at the Overview page for it. While there, take note of the app's Application (client) ID, as well as your Directory (tenant) ID; we'll use these later.

Step 2 - Configure API permissions

From the app's resource menu in the Azure AD Portal, select API permissions. Select Add a permission > Microsoft Graph > Application permissions then search for and select AuditLog.Read.All and Directory.Read.All. We'll use these permissions for our sample task - looking up Azure AD Sign-Ins. Once these permissions have been added, you'll also need to grant admin consent using the Grant admin consent <tenant> button.

Step 3 - Create and upload a self-signed certificate

We will now move over into PowerShell to use the MSGraphPSEssentials module to generate a self-signed certificate to upload into our new App Registration in Azure AD.

If not already installed, install the module like this:

Install-Module MSGraphPSEssentials -Scope CurrentUser

Once installed, generate a new certificate and export its public key:

$Cert = New-SelfSignedMSGraphApplicationCertificate -DnsName MyApp.MyTenant.com -FriendlyName 'My App'
Export-Certificate -FilePath $HOME\Desktop\cert.cer -Cert $Cert

Note: The values for -DnsName and -FriendlyName are completely up to you. Anything goes, so whatever makes sense to describe the certificate, or your app.

Now back in the Azure AD Portal, still with the new app selected, navigate to Certificates & secrets, then choose Upload certificate and browse to find/upload your exported certificate file on your Desktop.

At this point, the newly generated certificate resides in Azure AD (only the public key, whereas Export-Certificate did not export the private key) as well as in your CurrentUser certificate store (Cert:\CurrentUser\My). The certificate's properties are also loaded in your $Cert variable, which is convenient for our next steps.

Step 4 - Obtain an app-only access token

We're now ready to request an access token for our new app (the only real 'app' in this case, is just our PowerShell console in reality). We'll first load up a couple of variables to store our app and tenant ID's:

$AppId = '<the Application (client) ID from Step 1>'
$TenantId = '<the Directory (tenant) ID from Step 1>'

Then we'll request our access token:

$TokenObject = New-MSGraphAccessToken -TenantId $TenantId -ApplicationId $AppId -Certificate $Cert

We now have an access token stored in our $TokenObject variable. Feel free to take a look at it, directly (i.e. $TokenObject [enter]) or using ConvertFrom-JWTAccessToken:

ConvertFrom-JWTAccessToken $TokenObject.access_token | Select-Object -ExpandProperty Headers
ConvertFrom-JWTAccessToken $TokenObject.access_token | Select-Object -ExpandProperty Payload

Step 5 - Use the new access token with Microsoft Graph

Now let's test out our new access token by listing Azure AD Sign-Ins using New-MSGraphRequest. We can consult the Microsoft Graph reference page for the list signIns method. I'll leave the reading to you and demonstrate a quick example below, listing all signIns from the last 24 hours:

$24HoursAgo = (Get-Date).ToUniversalTime().AddDays(-1).ToString('yyyy-MM-ddTHH:mm:ssZ')
$SignIns = New-MSGraphRequest -Request "/auditLogs/signIns?&`$filter=createdDateTime gt $($24HoursAgo)" -AccessToken $TokenObject

To review the signIns, we need to look at the returned value property:

# See how many signIns were found:
$SignIns.value.count

# Review the signIns:
$SignIns.value | more

And that concludes this sample.