Ever been greeted with a (401) Unauthorized when calling a SharePoint-APIs? I have and its not always clear why this happens. Especially when the application in question worked yesterday. This can happen if you have registered a client secret using the /_layouts/15/appregnew.aspx page which means that by default the registered client secret is only valid for a year.

Exception: Microsoft.IdentityModel.SecurityTokenService.RequestFailedException: Token request failed. ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized. 

[11/28/2017 19:00:23 > d4ecbf: INFO]    at System.Net.HttpWebRequest.GetResponse() 

[11/28/2017 19:00:23 > d4ecbf: INFO]    at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2WebRequest.GetResponse() 

[11/28/2017 19:00:23 > d4ecbf: INFO]    at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue(String securityTokenServiceUrl, OAuth2AccessTokenRequest oauth2Request) 

[11/28/2017 19:00:23 > d4ecbf: INFO]    --- End of inner exception stack trace --- 

[11/28/2017 19:00:23 > d4ecbf: INFO]    at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue(String securityTokenServiceUrl, OAuth2AccessTokenRequest oauth2Request) 

[11/28/2017 19:00:23 > d4ecbf: INFO]    at

There is an easy way to determine if it has expired.

Read more about the script here: https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/replace-an-expiring-client-secret-in-a-sharepoint-add-in

First make sure you have the PowerShell Module installed https://www.powershellgallery.com/packages/MSOnline/1.1.183.57

Run the following:

Connect-MsolService

$clientId = "CLIENT_ID"

$keys = Get-MsolServicePrincipalCredential -AppPrincipalId $clientId -ReturnKeyValues $true 
$key1 = $keys[0] 
Write-Host  $key1.KeyId " ExpiryDate " $key1.EndDate 
$key2 = $keys[1] 
Write-Host  $key2.KeyId " ExpiryDate " $key2.EndDate
$key3 = $keys[2] 
Write-Host  $key3.KeyId " ExpiryDate " $key3.EndDate 

This will print out the keys and their end dates. Usually this is where you have determined that they have expired. What to do now? Do I need to change ClientId and add a new secret? No! You can generate a new secret and update your code to use that one. No need to register a new application.

$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(1) #Add how many years you want to have it valid. Be careful though! Dont forget about how long it is valid.
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

Take note of the new client secret and update your code to use the new one.

Note! There are other ways authenticate against SharePoint Online today. Maybe its time to update your way?

https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly

https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread