Wednesday, 21 February 2018

Replace an expiring client secret in a SharePoint Provider Hosted Apps (Add-in) without deploying the Apps again



Client secrets for SharePoint Add-ins that are registered by using the AppRegNew.aspx page expire after one year.you have used this Client ID and Secret ID in the Web Config in the web application part of the provider hosted app (App Web), after one year your Apps is stop working, and you will get the following Error:
System.IdentityModel.Tokens.SecurityTokenException: Invalid JWT token. Could not resolve issuer token.

By default the Secret Key will expire after one year, unfortunately you will not get any alerts before the expiry date, you have to renew the Secret Key at least one day before its expiry, because the new key will take about 12 hours to be generated, following steps will renew the Secret ID

This article explains how to add a new secret for the add-in, as well as how to create a new client secret that is valid for three years.

1.         Use online power shell to create new Client Secret ID
  1.     Microsoft Online Services Sign-In Assistant is installed on the development computer.
  2.      Microsoft Online Services PowerShell Module (32-bit64-bit) is installed on the development computer.
  3.      You are a tenant administrator for the Office 365 tenant (or a farm administrator on the farm) where the app was registered with the AppRegNew.aspx page.
4.      After downloading the powershell open it and connect to SharePoint online using following     CMDLET:

Connect-MsolService

        A popup will ask for Username and Password type your Username as:     UserName@DomainName.com

2.         Find out the expiration dates of the SharePoint Add-ins installed to the Office 365 tenancy 

Generate a report that lists each add-in and the date that its secret expires with the following lines. Note the following about this code:
·         It first filters out Microsoft's own applications, add-ins still under development (and a now-deprecated type of add-in that was called autohosted).
·         From the remainder, it filters out non-SharePoint add-ins and add-ins that use asymmetric keys, such as workflows

·         Get-MsolServicePrincipal -all |Where-Object -FilterScript { ($_.DisplayName -notlike "*Microsoft*") -and ($_.DisplayName -notlike "autohost*") -and  ($_.ServicePrincipalNames -notlike "*localhost*") } | foreach-object{
    $principalId = $_.AppPrincipalId
    $principalName = $_.DisplayName

    Get-MsolServicePrincipalCredential -AppPrincipalId $principalId -ReturnKeyValues $true | Where-Object { ($_.Type -ne "Other") -and ($_.Type -ne "Asymmetric") } |  foreach-object{
        $date = $_.EndDate.ToShortDateString()
        write-output "$($principalName);$($principalId);$($_.KeyId);$($_.type);$($date);$($_.Usage);$($_.Value)"
    }
} > c:\temp\appsec.txt

·         Open the file C:\temp\appsec.txt to see the report. Leave the Windows PowerShell window open for the next procedure, if any of the secrets are near expiration.
3.         Generate New Secret.

1.      Create a client ID variable with the following line, using the client ID of the SharePoint Add-in as the parameter.


PowerShellCopy
            $clientId = 'client id of the add-in'

2.      Generate a new client secret with the following lines:

 
$bytes = New-Object Byte[] 32
$rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$rand.GetBytes($bytes)
$newClientSecret = [System.Convert]::ToBase64String($bytes)
New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Password -Usage Verify -Value $newClientSecret
New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Sign -Value $newClientSecret
New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Verify -Value $newClientSecret
$newClientSecret
Copy the new Secret to use it as mentioned in the next Section
Note:
By default, the add-in secret lasts one year. You can set this to a shorter or longer (up to 3 years maximum) by using the -EndDate parameter on the three calls of the New-MsolServicePrincipalCredential cmdlet. The value of the parameter must be a DateTime object set to no longer than 3 years from DateTime.Now

4.         Update the web Config of the Azure Apps Web with the new Secret

The good news is that it’s not required to deploy the Apps again, you just you need to updated the web config file of the web application part of the provider Hosted App (App Web)
             <add key="ClientId" value="c86eb4d4-0efd-4269-92ba-97fd48689ec5" />
             <add key="ClientSecret" value="New Secret" />
             <add key="SecondaryClientSecret" value="Old Secret" />

We will keep the Old key in App setting (SecondaryClientSecret) because the new key will take about 12 hours to be generated in this case the web application will try to use the new Client Secret key but it will fail then it will use the secondary key, once the new key generated the web application will use it
Note:
You will not be able to use the newly generated client secret until the current client secret expires. Therefore, changing the ClientId key to the new client secret without the SecondaryClientSecret key present will not work. You must follow the procedure in this article and wait for the previous client secret to expire. You can then remove the SecondaryClientSecret if you want to.
If you changed to a new TokenHelper file, rebuild the project.
Republish the web application.

Create a client secret that is valid for three years

For expired client secrets, first you must delete all of the expired secrets for a given clientId. You then create a new one with MSO PowerShell, wait at least 24 hours, and test the app with the new clientId and ClientSecret key.
1.      Connect to MSOnline using the tenant admin user with the following markup using SharePoint Windows PowerShell.
PowerShell


 import-module MSOnline
 $msolcred = get-credential
 connect-msolservice -credential $msolcred
2.      Get ServicePrincipals and keys. Printing $keys returns three records. Replace each KeyId in KeyId1 , KeyId2, and KeyId3. You also see the EndDate of each key. Confirm whether your expired key appers there.


Note
The clientId needs to match your expired clientId. It's recommended to delete all keys, both expired and unexpired, for this clientId.
PowerShell


 $clientId = "27c5b286-62a6-45c7-beda-abbaea6eecf2"
 $keys = Get-MsolServicePrincipalCredential -AppPrincipalId $clientId -ReturnKeyValues $true
 foreach ($Key in $keys){Write-Host $key.KeyId,$key.EndDate }

 Remove-MsolServicePrincipalCredential -KeyIds @("KeyId1"," KeyId2"," KeyId3") -AppPrincipalId $clientId 
3.      Generate a new ClientSecret for this clientID. It uses the same clientId as set in the preceding step. The new ClientSecret is valid for 3 years.
PowerShell


 $bytes = New-Object Byte[] 32
 $rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
 $rand.GetBytes($bytes)
 $rand.Dispose()
 $newClientSecret = [System.Convert]::ToBase64String($bytes)
 $dtStart = [System.DateTime]::Now
 $dtEnd = $dtStart.AddYears(3)
 New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Sign -Value $newClientSecret -StartDate $dtStart  -EndDate $dtEnd
 New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Symmetric -Usage Verify -Value $newClientSecret   -StartDate $dtStart  -EndDate $dtEnd
 New-MsolServicePrincipalCredential -AppPrincipalId $clientId -Type Password -Usage Verify -Value $newClientSecret   -StartDate $dtStart  -EndDate $dtEnd
 $newClientSecret
4.      Copy the output of $newClientSecret.
5.      Replace the Web.config with this ClientId and ClientSecret. You don't need SecondaryClientSecret app settings.
6.      Wait at least 24 hours to propagate ClientSecret to SharePoint Office (SPO).
References:
https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/replace-an-expiring-client-secret-in-a-sharepoint-add-in