-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathUpdate-GitHubUserAccessToken.ps1
More file actions
119 lines (106 loc) · 5.02 KB
/
Update-GitHubUserAccessToken.ps1
File metadata and controls
119 lines (106 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
function Update-GitHubUserAccessToken {
<#
.SYNOPSIS
Updates the GitHub access token.
.DESCRIPTION
Updates the GitHub access token. If the access token is still valid, it will not be refreshed.
.EXAMPLE
```powershell
Update-GitHubUserAccessToken
```
This will update the GitHub access token for the default context.
.EXAMPLE
```powershell
Update-GitHubUserAccessToken -Context 'github.com/mojombo'
```
This will update the GitHub access token for the context 'github.com/mojombo'.
.NOTES
[Refreshing user access tokens](https://docs.github.com/apps/creating-github-apps/authenticating-with-a-github-app/refreshing-user-access-tokens)
#>
[CmdletBinding(SupportsShouldProcess)]
[OutputType([GitHubContext])]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSAvoidUsingWriteHost', '',
Justification = 'Is the CLI part of the module.'
)]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSAvoidUsingConvertToSecureStringWithPlainText', '',
Justification = 'The tokens are received as clear text. Mitigating exposure by removing variables and performing garbage collection.'
)]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSAvoidLongLines', '',
Justification = 'Reason for suppressing'
)]
param(
# The context to run the command in. Used to get the details for the API call.
# Can be either a string or a GitHubContext object.
[Parameter(Mandatory)]
[object] $Context,
# Return the updated context.
[Parameter()]
[switch] $PassThru,
# Timeout in milliseconds for waiting on mutex. Default is 30 seconds.
[Parameter()]
[int] $TimeoutMs = 30000
)
begin {
$stackPath = Get-PSCallStackPath
Write-Debug "[$stackPath] - Start"
}
process {
if (Test-GitHubAccessTokenRefreshRequired -Context $Context) {
$lockName = "PSModule.GitHub-$($Context.ID)".Replace('/', '-')
$lock = $null
try {
$lock = [System.Threading.Mutex]::new($false, $lockName)
$updateToken = $lock.WaitOne(0)
if ($updateToken) {
try {
$refreshTokenValidity = [datetime]($Context.RefreshTokenExpiresAt) - [datetime]::Now
$refreshTokenIsValid = $refreshTokenValidity.TotalSeconds -gt 0
if ($refreshTokenIsValid) {
Write-Debug '⚠ Access token expired. Refreshing access token...'
$tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $Context.AuthClientID -RefreshToken $Context.RefreshToken -HostName $Context.HostName
} else {
Write-Verbose "Using $($Context.DeviceFlowType) authentication..."
$tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $Context.AuthClientID -HostName $Context.HostName
}
$Context.Token = ConvertTo-SecureString -AsPlainText $tokenResponse.access_token
$Context.TokenExpiresAt = ([DateTime]::Now).AddSeconds($tokenResponse.expires_in)
$Context.TokenType = $tokenResponse.access_token -replace $script:GitHub.TokenPrefixPattern
$Context.RefreshToken = ConvertTo-SecureString -AsPlainText $tokenResponse.refresh_token
$Context.RefreshTokenExpiresAt = ([DateTime]::Now).AddSeconds($tokenResponse.refresh_token_expires_in)
if ($PSCmdlet.ShouldProcess('Access token', 'Update/refresh')) {
Set-Context -Context $Context -Vault $script:GitHub.ContextVault
}
} finally {
$lock.ReleaseMutex()
}
} else {
Write-Verbose "Access token is not valid. Waiting for mutex to be released (timeout: $($TimeoutMs)ms)..."
try {
if ($lock.WaitOne($TimeoutMs)) {
$Context = Resolve-GitHubContext -Context $Context.ID
$lock.ReleaseMutex()
} else {
Write-Warning 'Timeout waiting for token update. Proceeding with current token state.'
}
} catch [System.Threading.AbandonedMutexException] {
Write-Debug 'Mutex was abandoned by another process. Re-checking token state...'
$Context = Resolve-GitHubContext -Context $Context.ID
}
}
} finally {
if ($lock) {
$lock.Dispose()
}
}
}
if ($PassThru) {
return $Context
}
}
end {
Write-Debug "[$stackPath] - End"
}
}