SharePoint – Extending app only secret lifetime

Perhaps you need an app principal to be able to access a particular SharePoint site? You could be using the great SharePoint PnP PowerShell module and you want to connect via an AppId and AppSecret.

You’ve got two choices:

Grant access using Azure AD app-only

Microsoft’s preferred method when using SharePoint Online.

All you have to do is register an Azure AD App Principal and grant the relevant permissions to SharePoint. That can all be done via the Azure AD portal.

The downside of this is that you can’t limit permissions to a particular Site. The principal will have access across the whole of your SharePoint tenancy.

Grant access using SharePoint App-Only principal

This is the older method up setting up app-principals. It allows you to generate a principal with very specific permissions and at different levels:

  • Tenant – permissions across whole SharePoint tenancy
  • Site Collection – permissions at site collection scope
  • Site / Sub Site – permissions at a site level or even sub-level
  • List – permissions at list level for a site/sub-site

As you can see the benefit of this model is that you can assign fine grain permissions that Info-sec will be happier with.

The downside is that by registering the app via the AppRegNew.aspx, the secret will have a default expiry of only 1 year! Furthermore, from the web interface, you have no way of changing this or even being able to see the expiry date. However, you can view the expiry using PowerShell (see the Extend current secret lifetime section).

Note – This method only works for SharePoint Online.

Create new Azure AD app registration

The goods news is that you can create an Azure AD app principal with a secret that has a custom expiry date. You can then assign SharePoint permissions using the standard AppInv.aspx page method.

To create the registration, you can use the Azure AD web portal. However, I find it easier and quicker to use PowerShell.

You’ll need the Azure AD PowerShell V2 module installed (instructions here) and you will need to use an account that has at least the Cloud Application Administrator role assigned.

The following code will:

  1. Connect to Azure AD – replace tenantId with your id.
  2. Create a new Azure AD Application registration – usually found under App registrations
  3. Register a new Azure AD service principal – usually found under Enterprise applications
  4. Create a new secret – with a 49 year expiry from today.
Connect-AzureAD -TenantId <tenantId>
$appName = "<appName>"
$appURI = "https://$appName.<tenantId>"
$appHomePageUrl = "https://localhost"
$appReplyURLs = @($appURI, $appHomePageURL, "https://localhost:1234")

if(!($myApp = Get-AzureADApplication -Filter "DisplayName eq '$($appName)'" -ErrorAction SilentlyContinue))
    $myApp = New-AzureADApplication -DisplayName $appName -IdentifierUris $appURI -Homepage $appHomePageUrl -ReplyUrls $appReplyURLs

$svcprincipal = New-AzureADServicePrincipal -AppId $myApp.AppId

$startDate = Get-Date
$EndDate = $startDate.AddYears(49)
$aadAppKeyPwd = New-AzureADApplicationPasswordCredential -ObjectId $myApp.ObjectId -CustomKeyIdentifier "Default" -StartDate $startDate -EndDate $endDate

You can verify that everything was created successfully by going to:

Azure > Azure Active Directory > App registrations > {appName} > Certificates & Secrets

app registration secrets

You should see a secret named Default with a long expiry date.

The secret is accessible in the $aadAppKeyPwd.Value property. Make sure you save it as it won’t be viewable again. You’ll also want to record the $myApp.AppId value to use later.

Grant SharePoint access

Now that you have a service principal to work with you need to assign the appropriate SharePoint permission. To do that you need go to the relevant AppInv.aspx page. The page location depends on which permission level/scope you want to assign:

  • Tenant level – https://{tenant_name}
  • Site collection level – https://{tenant_name}{site_collection}/_layouts/15/appinv.aspx
  • Site/sub-site/list level – https://{tenant_name}{site_collection}/{site}/_layouts/15/appinv.aspx

Go to the relevant AppInv.aspx page and under AppId enter the value stored in $myApp.AppId and press Lookup. The app registration information should then be returned.

SharePoint app inventory page

In the App’s Permission Request XML textbox you will need to provide the correct XML based on the permission you want to grant. Microsoft have some documentation available here that explains what the available permission scopes are.

For this example, I’m going to grant full control at a site level:

<AppPermissionRequests AllowAppOnlyPolicy="true">  
  <AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web"
   Right="FullControl" />

Note – If you’re not sure of the correct XML then have a look at this cheat sheet.

Press Create to commit your changes. You may be prompted to trust the app, you will need to press Trust It to grant the permissions.

Trust SharePoint app permissions

You now have a app registration that won’t expire for a long long time!

Extend current secret lifetime

If you can’t create a new app registration or need to update an existing app. You can use a bit of PowerShell to generate a new secret with a custom lifetime.

Connect to Azure AD using the Azure AD V2 PowerShell Module:

Connect-AzureAD -TenantId <tenantId>

Find the Service Principal that you need to update:

$apps = Get-AzureADServicePrincipal -All $true | ? DisplayName -like '*{appName}*'

Piping out to a table you can see that the test-sp-generated-app is listed:

This is the one I created via the AppRegNew.aspx page. I’m just going to store that object in the $app variable to make the rest of the commands easier to write.

Next, we’re going to list the existing secrets:

Get-AzureADServicePrincipalPasswordCredential -ObjectId $app.ObjectId

The auto generated key is displayed and you can see that the end date is 1 year from the start date:

However, we can’t set a new EndDate for an existing secret. Therefore, we have to create a new secret:

$startDate = Get-Date
$endDate = $startDate.AddYears(49)
New-AzureADServicePrincipalPasswordCredential -ObjectId $app.ObjectId -CustomKeyIdentifier "Test" -StartDate $startDate -EndDate $endDate

A new secret is created and is stored in the Value property:

If you run the Get-AzureADServicePrincipalPasswordCredential again, you should now see two credentials:

To test if the new secret works you can try connecting to the site via PnP cmdlets:

Connect-PnPOnline -AppId $app.AppId -AppSecret {value} -Url {url of SharePoint site}

You should see all the Lists contained in the site:

Success! You now have a new secret that won’t expire for a long time.

You should update your code to use the new secret and verify everything is working as expected. Lastly, delete the old credential:

Remove-AzureADServicePrincipalPasswordCredential -ObjectId $app.ObjectId -KeyId {old keyId}

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.