0
votes

I've inherited a PowerShell script which integrates with the VSTS APIs, and authenticates using a PAT (Personal Access Token) which is currently stored in our team's password safe.

However, the origins of the PAT have been lost to the mists of time and I have no idea which member of the team created it in the first place (and they might not even still work here!), or which user's VSTS account it's defined in.

Using just the PAT, are there any "who-am-i"-type endpoints in the VSTS APIs that I could hit that would echo back the username, guid, or other details of the account the PAT is defined in?

There are a couple of reasons I specifically want to find out where the PAT is defined, rather than just issue a new one from another account:

  • so I can get a new one issued in the same account when the current one expires
  • so we can get the owner to revoke the existing one if necessary

Cheers,

M

3

3 Answers

2
votes

Based on Marina's answer, I've written the following PowerShell script to create a new task using the PAT for authentication. You can then check the "fields -> System.CreatedBy" property in the json response to see which account the PAT belongs to.

$ErrorActionPreference = "Stop";
$ProgressPreference = "SilentlyContinue";
Set-StrictMode -Version "Latest";


$vstsAccount     = "myaccount";     # e.g. "myaccount" in "https://myaccount.visualstudio.com"
$vstsProjectName = "myprojectname"; # e.g. "myprojectname" in "https://myaccount.visualstudio.com/myprojectname"
$vstsPat         = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";


function Invoke-VstsWebRequest
{
    param
    (
        [string] $Uri,
        [string] $Pat,
        [string] $Method,
        [string] $Body,
        [string] $ContentType
    )
    write-host "uri = '$Uri'";
    $splat = @{
        "Uri"     = $Uri
        "Headers" = @{
            "Authorization" = "Basic " +
                [System.Convert]::ToBase64String(
                    [System.Text.ASCIIEncoding]::ASCII.GetBytes(
                       [string]::Format("{0}:{1}", "", $Pat)
                    ) 
                )
        }
        "Method" = $Method
        "UseBasicParsing" = $true
    }
    if( -not [string]::IsNullOrEmpty($Body) )
    {
        write-host "body = ";
        write-host $Body;
        $splat.Add("ContentType", $ContentType); 
        $splat.Add("Body", $Body);
    }
    $response = Invoke-WebRequest @splat;
    write-host "response = ";
    write-host ($response.Content | ConvertFrom-Json | ConvertTo-Json);
    return $response.Content;
}


# get existing work items in the specified project
# (not necessary, but useful for testing)
$uri  = "https://$vstsAccount.visualstudio.com/$vstsProjectName/_apis/wit/wiql?%24top=50&api-version=4.1";
$query = @"
SELECT [System.ID],
       [System.Title]
FROM workitems
WHERE [System.TeamProject] = '{0}'
ORDER BY [System.Title]
"@;
$body = ConvertTo-Json ([ordered] @{
    "query" = [string]::Format($query, $vstsProjectName)
});
$type = "application/json";
$json = Invoke-VstsWebRequest -Uri $uri -Pat $vstsPat -Method "Post" -Body $body -ContentType $type;


# create a new "Task" work item in the specified project
# (the response will show the user account associated with the PAT)
$uri  = "https://$vstsAccount.visualstudio.com/$vstsProjectName/_apis/wit/workitems/`$Task?api-version=4.1";
$body = ConvertTo-Json @([ordered] @{
    "op"    = "add"
    "path"  = "/fields/System.Title"
    "value" = "my sample task"
});
$type = "application/json-patch+json";
$json = Invoke-VstsWebRequest -Uri $uri -Pat $vstsPat -Method "Post" -Body $body -ContentType $type;

Output:

...
"System.CreatedBy":"My Username <[email protected]>"
...

P.S. I've posted a UserVoice ticket requesting a "who-am-i" endpoint here: https://visualstudio.uservoice.com/forums/330519-visual-studio-team-services/suggestions/34509568-provide-a-who-am-i-endpoint-in-the-vsts-api-to-i

1
votes

I've seen this used successfully to get the owner of the PAT: https://docs.microsoft.com/en-us/javascript/api/azure-devops-extension-api/connectiondata

e.g. use an API call: https://dev.azure.com/domoreexp/_apis/connectionData?api-version=5.0-preview

You can get the authenticatedUser as well as the authorizedUser (unsure what the difference is tbh)

0
votes

There is no way for VSTS itself to show who create a PAT.

But if you know the value of the PAT, you can find the user who create the PAT by creating a wotk item. Such as you can use the PAT to create a Task wotk item, and then the user who create the Task wotj item is the personal who created the PAT.

Besides, you can feed back this feature by creating an user voice.