Skip to content

Commit 1bc7a6f

Browse files
authored
Auto access token refresh (#278)
1 parent baaad16 commit 1bc7a6f

File tree

7 files changed

+42
-6
lines changed

7 files changed

+42
-6
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
Write-Output "There were $($errors.Count) errors and $($warnings.Count) warnings total."
2828
}
2929
- name: Upload test results
30-
uses: actions/upload-artifact@v2
30+
uses: actions/upload-artifact@v4
3131
with:
3232
name: pssa-results
3333
path: ${{ github.workspace }}/pssa.json

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
*.Pester.Defaults.json
22
*.zip
3+
.DS_Store

RELEASE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
- Fix invalid Id error, [#262](https://github.com/Snow-Shell/servicenow-powershell/issues/262)
1+
- Add support for access token refresh, [#277](https://github.com/Snow-Shell/servicenow-powershell/issues/277)

Readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ $params = @{
4343
New-ServiceNowSession @params
4444
```
4545

46-
Oauth authentication with user credential as well as application/client credential. The application/client credential can be found in the System OAuth->Application Registry section of ServiceNow.
46+
Oauth authentication with user credential as well as application/client credential. The application/client credential can be found in the System OAuth->Application Registry section of ServiceNow. The access token will be refreshed automatically when it expires.
4747
```PowerShell
4848
$params = @{
4949
Url = 'instance.service-now.com'

ServiceNow/Private/Get-ServiceNowAuth.ps1

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,35 @@ function Get-ServiceNowAuth {
3131

3232
if ( $ServiceNowSession.Count -gt 0 ) {
3333
$hashOut.Uri = $ServiceNowSession.BaseUri
34+
35+
# check if we need a new access token
36+
if ( $ServiceNowSession.ExpiresOn -lt (Get-Date) -and $ServiceNowSession.RefreshToken -and $ServiceNowSession.ClientCredential ) {
37+
# we've expired and have a refresh token
38+
$refreshParams = @{
39+
Uri = 'https://{0}/oauth_token.do' -f $ServiceNowSession.Domain
40+
Method = 'POST'
41+
ContentType = 'application/x-www-form-urlencoded'
42+
Body = @{
43+
grant_type = 'refresh_token'
44+
client_id = $ServiceNowSession.ClientCredential.UserName
45+
client_secret = $ServiceNowSession.ClientCredential.GetNetworkCredential().password
46+
refresh_token = $ServiceNowSession.RefreshToken.GetNetworkCredential().password
47+
}
48+
}
49+
50+
$response = Invoke-RestMethod @refreshParams
51+
52+
$ServiceNowSession.AccessToken = New-Object System.Management.Automation.PSCredential('AccessToken', ($response.access_token | ConvertTo-SecureString -AsPlainText -Force))
53+
$ServiceNowSession.RefreshToken = New-Object System.Management.Automation.PSCredential('RefreshToken', ($response.refresh_token | ConvertTo-SecureString -AsPlainText -Force))
54+
if ($response.expires_in) {
55+
$ServiceNowSession.ExpiresOn = (Get-Date).AddSeconds($response.expires_in)
56+
Write-Verbose ('Access token has been refreshed and will expire at {0}' -f $ServiceNowSession.ExpiresOn)
57+
}
58+
59+
# ensure script/module scoped variable is updated
60+
$script:ServiceNowSession = $ServiceNowSession
61+
}
62+
3463
if ( $ServiceNowSession.AccessToken ) {
3564
$hashOut.Headers = @{
3665
'Authorization' = 'Bearer {0}' -f $ServiceNowSession.AccessToken.GetNetworkCredential().password

ServiceNow/Public/New-ServiceNowSession.ps1

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ Create a new ServiceNow session
66
Create a new ServiceNow session via credentials, OAuth, or access token.
77
This session will be used by default for all future calls.
88
Optionally, you can specify the api version you'd like to use; the default is the latest.
9+
910
To use OAuth, ensure you've set it up, https://docs.servicenow.com/bundle/quebec-platform-administration/page/administer/security/task/t_SettingUpOAuth.html.
1011
12+
If using OAuth, the client credential will be stored in the script scoped variable ServiceNowSession and the access token will be automatically refreshed.
13+
1114
.PARAMETER Url
1215
Base domain for your ServiceNow instance, eg. tenant.domain.com
1316
@@ -200,8 +203,11 @@ function New-ServiceNowSession {
200203
if ($token.expires_in) {
201204
$expiryTime = (Get-Date).AddSeconds($token.expires_in)
202205
$newSession.Add('ExpiresOn', $expiryTime)
203-
Write-Verbose "Token will expire at $expiryTime"
206+
Write-Verbose "Access token will expire at $expiryTime"
204207
}
208+
# store client credential as it will be needed to refresh the access token
209+
$newSession.Add('ClientCredential', $ClientCredential)
210+
205211
}
206212
else {
207213
# invoke-webrequest didn't throw an error, but we didn't get a token back either

ServiceNow/ServiceNow.psd1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
RootModule = 'ServiceNow.psm1'
1313

1414
# Version number of this module.
15-
ModuleVersion = '4.0.5'
15+
ModuleVersion = '4.1'
1616

1717
# Supported PSEditions
1818
# CompatiblePSEditions = @()
@@ -27,7 +27,7 @@ Author = 'Greg Brownstein, Rick Arroues, Sam Martin'
2727
CompanyName = 'None'
2828

2929
# Copyright statement for this module
30-
Copyright = '(c) 2015-2023 Snow-Shell. All rights reserved.'
30+
Copyright = '(c) 2015-2025 Snow-Shell. All rights reserved.'
3131

3232
# Description of the functionality provided by this module
3333
Description = 'Automate against ServiceNow service and asset management. This module can be used standalone, with Azure Automation, or Docker.'

0 commit comments

Comments
 (0)