My actual question is block-quoted below, but read on for context.

When you use AppRegNew.aspx to setup app credentials for provider-hosted apps the secret expires (by default) after 1 year. This means the app will stop working.

I've setup a fairly robust way to deal with this, by using a local store of app credential information and then having my apps pull the credentials from that store as needed, rather than "hard coding" the AppIds and Secrets into something like a web.config or app.config. It requests the credentials by app name from the store, and those credentials are automatically managed by a separate Windows service when expiration dates come up.

The issue I'm having is in determining when the new/updated secrets take effect. According to Microsoft it takes at least 24 hours. Changing it ahead of time and supporting "SecondarySecret" values within the TokenHelper implementation seems like the only solution here, which is what I've done. This still requires me to either leave the secondary secret active indefinitely, or just assume it's working after, say, 48 hours... or 1 week... or whatever, and then remove it automatically. Manually testing dozens of apps to ensure secret changes are working properly is a huge waste of time, especially given that it comes up every 3 years (max).

How are other people dealing with this secret expiration problem? It feels like a pretty poorly designed mechanism that is fundamental to how it actually works.

I suppose alternatively you could just create a new app every time the secret expires, and link that up with the provider-hosted solution. Maybe that's the better approach?

Is there something I'm missing here?

2 Answers 2


Though this question is quite old now, thought to share the below article following which we can have client secret expiration set to never.

Take below steps:

  1. Register the App in Azure Active Directory and set the client secret expiration set to never.
  2. Use the client id of the app and add the app to the site by going to sitecollection/_layouts/15/appinv.aspx. Provide the required permission xml.
  3. Add the app and use the app client Id and secret in your code.

Detailed article: https://spblog.net/post/2018/08/24/SharePoint-lifehacks-create-SharePoint-app-registration-with-client-secret-which-never-expires

About permission XML: https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/add-in-permissions-in-sharepoint

I tried this and it worked for me.

Hope this helps! Thank you!

  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review Feb 12, 2020 at 9:02
  • Agreed. Updated the answer. Feb 12, 2020 at 11:30

You can use my script to register app for 5 years (or more) just change New-MsolServicePrincipal command parameters.

 #Import-Module MSOnline

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") | Out-Null [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")| Out-Null

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

function Install-SPOnlineApp { Param($appTitle,$appUrl,$clientID,$clientSecret,$appFileLocation)

[Uri]$appUri = $appUrl $appDomain = $appUri.Host Write-Output "Installing app $appTitle on url $appUrl " #APP reg new online # required Windows Azure Active Directory Module for Windows PowerShell https://go.microsoft.com/fwlink/p/?linkid=236297 $servicePrincipalName = @("$clientID/$appDomain") $existing = Get-MsolServicePrincipal | where AppPrincipalId -EQ $clientId if($existing -eq $null) { New-MsolServicePrincipal -ServicePrincipalNames $servicePrincipalName -AppPrincipalId $clientID -DisplayName $appTitle -Type Symmetric -Usage Verify -StartDate $(Get-Date).AddDays(-1) -EndDate $(Get-Date).AddYears(5) -Addresses (New-MsolServicePrincipalAddresses -Address $appUrl) Start-Sleep -Seconds 5 New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Sign -Value $clientSecret New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Verify -Value $clientSecret New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Password -Usage Verify -Value $clientSecret } $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) $pass = $AdminPassword | ConvertTo-SecureString -AsPlainText -Force $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($AdminUser , $pass) $ctx.Credentials = $credentials $sideLoadingEnabled = [Microsoft.SharePoint.Client.appcatalog]::IsAppSideloadingEnabled($ctx); $ctx.ExecuteQuery() if($sideLoadingEnabled.value -eq $false) { Write-Host "Enabling sideloading ..." $sideLoadingGuid = new-object System.Guid "AE3A1339-61F5-4f8f-81A7-ABD2DA956A7D" $ctx.Site.Features.Add($sideLoadingGuid, $false, [Microsoft.SharePoint.Client.FeatureDefinitionScope]::None) | Out-Null $ctx.ExecuteQuery() Write-Host "Sideloading enabled" } else { Write-Output "Sideloading was enabled" } $ctx.Web.LoadAndInstallApp([System.IO.File]::OpenRead($appFileLocation)) $ctx.ExecuteQuery() Write-Output "App installed in web $siteUrl" }

  • I thought 3 years was the maximum? Did they increase it to 5 at some point?
    – Chad
    Aug 12, 2017 at 14:41
  • I didn't find any limitation to 3 years .. One year is default value. Aug 12, 2017 at 14:44
  • My link above (according to Microsoft) it clearly says 3 years is the max. Maybe this is just incorrect documentation, wouldn't surprise me. Either way, this doesn't really solve anything other than pushing the problem further into the future, but I appreciate your response.
    – Chad
    Aug 12, 2017 at 14:49
  • There is only a sample how to create a client secret that is valid for three years. But no limitations ... Aug 12, 2017 at 14:52
  • It says "Tip By default, the add-in secret lasts one year. You can set this to a shorter or longer (up to 3 years maximum)"
    – Chad
    Aug 12, 2017 at 14:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.