Reputation: 113
I'm working on a custom Powershell Cmdlet for accessing a REST webservice.
The webservice requires me to authenticate, and when i do it returns a authenticaton-token that i have to include in every request after that.
The problem I am facing is that I am unable to store the token in a desired manner so i can use it with ease in commands after the authentication.
I would like if it could work in the same way as Connect-MSOLService work.
For those unfamiliar with the Office 365 cmdlets i will give some examples.
Office 365 Cmdlets
$Credentials = Get-Credential
Connect-MSOLService -Credential $Credentials
Get-MSOLUser
In this example the Get-MSOLUser will return every Office 365 user, because the Connect-MSOLService have been called before hand.
My Cmdlet
$Credentials = Get-Credential
$token = Connect-WebService -Credential $Credentials
Get-Server -token $token
Get-Client -token $token
As you can see, I have to return the token and store it in a variable and use it in every call i do after the authentication.
So that leads me to my question, how can i "inject" the token into the Powershell session and use it "under-the-hood" on every command in my cmdlet/module after that?
Thank you for your time.
Upvotes: 2
Views: 1664
Reputation: 1303
If using the PowerShell 5.0 assembly you can inherit from PSCmdlet
and use SessionState
to store variables.
private string const variableName = "MyVar";
private Token token = new Token("your token");
SessionState.PSVariable.Set(new PSVariable(variableName, token, ScopedItemOptions.Private));
You then use GetValue()
to retrieve it.
Token storedToken = (Token)SessionState.PSVariable.GetValue(variableName);
This variable is not available to the PowerShell session but will persist between cmdlet calls. I use it to store an API token on the first query, and to reuse it until it expires or the session is closed.
Upvotes: 1
Reputation: 201622
You have to be careful about storing the token in a process wide variable as it is possible to have multiple PowerShell runspaces running in the same process. However, what you could do is create a static reference to a Dictionary that stashes the token for the runspace in which the cmdlet is running. You can get the runspace ID like so:
Guid runspaceId = Guid.Empty;
using (var ps = PowerShell.Create(RunspaceMode.CurrentRunspace))
{
runspaceId = ps.Runspace.InstanceId;
}
Then create a static class with a static readonly field like so:
public static class TokenUtil {
public static readonly Dictionary<Guid,PSObject> Tokens = new Dictionary<Guid,PSObject>();
}
Check for existing token for this runspace like so:
PSObject token = null;
if (TokenUtil.Tokens.ContainsKey(runspaceId))
{
token = TokenUtil.Tokens[runspaceId];
}
Upvotes: 2
Reputation: 5241
I don't know how Microsoft does it, but I think one way to do it is like this:
function Connect-WebService {
param($credential)
#Do all of the connection here
#Set the global variable so it will be available outside of this function
$script:token = ...
}
function Get-Server {
param(
$token = $script:token # By default use the globally set $token variable
)
}
This way would work if you are doing everything in a PowerShell module.
Upvotes: 0