public/Disconnect-MsalEssentials.ps1
|
<#
.SYNOPSIS Clears the connection stored by Connect-MsalEssentials. .DESCRIPTION Removes the accounts and tokens from the MSAL client's in-memory token cache, then removes the stored connection from module scope. After this, Get-MsalEssentialsToken fails with MsalEssentials.NotConnected until Connect-MsalEssentials is run again. If there is no connection, nothing happens and no error is raised. What this command cannot clear: - Variables in your own session that hold the token. Connect- MsalEssentials -PassThru and Get-MsalEssentialsToken return the access token, so anything you assigned it to still contains it: for example $connection, or a request hashtable such as $request.Headers.Authorization built from $connection.CreateAuthorizationHeader(). Remove them yourself, for example: Remove-Variable -Name connection, request or set them to $null. Closing the PowerShell session removes everything. .NET strings can't be securely wiped, so dropping the references is the most that can be done. - The browser session. Entra ID keeps sign-in cookies in the browser, so the next Connect-MsalEssentials may sign in without a prompt. Sign out in the browser (https://login.microsoftonline.com/logout.srf) if you need to prevent that. - A token that was already issued. It stays valid until it expires (about an hour by default) and can't be revoked from the client. An administrator can invalidate refresh tokens, for example with Revoke-MgUserSignInSession. When a connection was cleared, a hint about the token variables is shown. Use -InformationAction SilentlyContinue to hide it. .EXAMPLE Disconnect-MsalEssentials Clears the connection and shows the hint about token variables. .EXAMPLE $connection = Get-MsalEssentialsToken # ... use $connection.CreateAuthorizationHeader() ... Disconnect-MsalEssentials Remove-Variable -Name connection Clears the connection, then removes the variable that held the token. .EXAMPLE Disconnect-MsalEssentials -InformationAction SilentlyContinue Clears the connection without showing the hint. #> function Disconnect-MsalEssentials { [CmdletBinding()] [OutputType([void])] param () $session = Get-Variable -Name 'MsalEssentialsSession' -Scope 'Script' -ValueOnly -ErrorAction 'SilentlyContinue' if (-not $session) { Write-Verbose -Message 'Not connected, nothing to disconnect.' return } # Remove the accounts (and with them the cached tokens) from the MSAL # client. The client is dropped below anyway; this clears the cache now # instead of waiting for garbage collection. A failure here must not # stop the session from being cleared. if ($session.PublicClientApplication) { try { $accounts = $session.PublicClientApplication.GetAccountsAsync().GetAwaiter().GetResult() foreach ($account in $accounts) { # Discard the VoidTaskResult that RemoveAsync returns, so it isn't written to the pipeline. $null = $session.PublicClientApplication.RemoveAsync($account).GetAwaiter().GetResult() } } catch { $innermostException = $_.Exception while ($innermostException.InnerException) { $innermostException = $innermostException.InnerException } Write-Warning -Message ('Could not clear the MSAL token cache: {0}' -f $innermostException.Message) } } Remove-Variable -Name 'MsalEssentialsSession' -Scope 'Script' -ErrorAction 'SilentlyContinue' Write-Verbose -Message 'Connection cleared.' # Show the hint by default, but let the caller hide it with # -InformationAction (which sets $InformationPreference in this scope). if (-not $PSBoundParameters.ContainsKey('InformationAction')) { $InformationPreference = 'Continue' } Write-Information -MessageData ( 'MSAL.Essentials disconnected. Variables that hold the token (for example the result of Connect-MsalEssentials -PassThru or ' + 'Get-MsalEssentialsToken, or a request header built from it) are not cleared by this command. ' + 'Remove them yourself, for example: Remove-Variable -Name connection' ) } |