skip to Main Content

I’m writing a powershell script to rotate my PAT in my devbox. Here’s what I’ve done:

PS> .Rotate-Pat.ps1

Here’s the code in Check-PatValidity.ps1:

$env:PAT | az devops login --organization "https://dev.azure.com/$organization"

    $body = @{
        displayName = $organization
        scope = "vso.build vso.code_full vso.tokens vso.profile"
        validTo = (Get-Date).AddDays(7).ToString("yyyy-MM-ddTHH:mm:ssZ")
        allOrgs = $false
    } | ConvertTo-Json

    $response = Invoke-RestMethod -Uri "https://vssps.dev.azure.com/$organization/_apis/tokens/pats?api-version=7.1-preview.1" -Headers $headers -Method Post -Body $body -ContentType "application/json"
    
    $prettyJson = $response | ConvertTo-Json -Depth 2
    $prettyJson | Out-file $env:USERPROFILEDownloadspatgenoutput.json -Encoding UTF8

    if ($response) {
        $newPat = $response.patToken.token
        Write-Output "New PAT: $newPat"
    }

Here’s what I see as output (which is exactly the same as patgenoutput.json):
enter image description here

Looks like the html of Azure DevOps Login screen.

Questions:

  1. Am I on the right track? If not, please point me in the right direction.
  2. How to make the Azure DevOps login as an interactive session and get the access token to generate the PAT?

2

Answers


  1. According to your description, you are trying to use the Pats – Create REST API to create a new PAT token with the old PAT token. However, it is not allowed to create a new token with an old PAT token.

    You can check this document Manage personal access tokens (PATs) using REST API and the following Frequently asked questions (FAQs).

    Q: Why do I need to authenticate with a Microsoft Entra token? Why is a PAT not enough?

    A: With this PAT Lifecycle Management API, we opened the ability to create new PATs and revoke existing PATs. In the wrong hands, malicious actors could use this API to create multiple entry points into your organization’s Azure DevOps resources. By enforcing Microsoft Entra authentication, we hope to have this powerful API be more secure against this unauthorized usage.

    Q: How can I regenerate/rotate PATs through the API? I saw that option in the UI, but I don’t see a similar method in the API.

    A: Great question! The ‘Regenerate’ functionality available in the UI actually accomplishes a few actions, which are fully replicable through the API.
    To rotate your PAT, do the following steps:

    • Understand the metadata of the PAT using a GET call,
    • Create a new PAT with the old PAT’s metadata using a POST call,
    • Revoke the old PAT using a DELETE call

    Here are the steps to create an Azure AD application and create the PAT.

    1. Register a new application under Microsoft Entra ID -> App Registrations in the Azure portal if you don’t have one.

      App Registration

    2. Select your application and navigate to API Permissions and select Azure DevOps -> check user_impersonation -> select Add permissions.

      API Permissions

      Azure DevOps

    3. Add https://jwt.ms as Redirect URI.

      Redirect URI

    4. Create a Client secret in the Certificates & secrets

      Client secret

    5. Paste and access the following link in your browser to make authorization request to get the authorization code in the resulting URL:

    https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/authorize
    ?client_id=<appID>
    &response_type=code
    &redirect_uri=https://jwt.ms
    &response_mode=query
    &scope= 499b84ac-1321-427f-aa17-267ca6975798/.default
    &state=12345
    

    Result:
    code

    1. Then you can generate the access token using authorization code in the following PowerShell script:
    $tenantId = ''     
    $clientId = ''   # check Application (client) ID and tenant Id from the app overview page
    $clientSecret = ''  # the clientSecret from the step  4
    $redirectUri="https://jwt.ms"
    
    $organization = ""
    
    $code=""   # the code from the step 5
    
    $tokenUrl = "https://login.microsoftonline.com/$tenantID/oauth2/v2.0/token"
    
    $body = @{
        grant_type    = "authorization_code"
        client_id     = $clientId
        client_secret = $clientSecret
        scope         = "499b84ac-1321-427f-aa17-267ca6975798/.default"
        redirect_uri  = $redirectUri
        code          = $code
    }
    
    $headers = @{
        "Content-Type" = "application/x-www-form-urlencoded"
    }
    
    # Make the POST request to get the access_token
    $response = Invoke-RestMethod -Method Post -Uri $tokenUrl -Headers $headers -Body $body
    echo $response.access_token
    
    # Create a PAT with the token
    $body = @{
            displayName = $organization
            scope = "vso.build vso.code_full vso.tokens vso.profile"
            validTo = (Get-Date).AddDays(7).ToString("yyyy-MM-ddTHH:mm:ssZ")
            allOrgs = $false
        } | ConvertTo-Json
    $accessHeader = @{
        'Authorization' = 'Bearer ' + $response.access_token
    }
    
    $PATresponse = Invoke-RestMethod -Uri "https://vssps.dev.azure.com/$organization/_apis/tokens/pats?api-version=7.1-preview.1" -Headers $accessHeader -Method Post -Body $body -ContentType "application/json"
    
    
    if ($PATresponse) {
       $newPat = $PATresponse.patToken.token
       Write-Output "New PAT: $newPat"
    }
    
    

    Please note that the authorization codes are short lived, typically expiring after about 10 minutes. So, if you want to get a new token, you can get a refresh_token first instead of getting an authorization code manually again. You can refer this question to get the refresh_token. For more details, please refer Microsoft identity platform and OAuth 2.0 authorization code flow

    By the way, in your script, you are using the az devops login command and then use the Invoke-RestMethod call. However, the Invoke-RestMethod call won’t automatically inherit the login status from the az devops login command. The az devops login command is used to authenticate the Azure DevOps CLI, but it doesn’t directly affect the PowerShell session or the Invoke-RestMethod call. So, your Invoke-RestMethod call met the azure devops login page as you didn’t login.

    Login or Signup to reply.
  2. Alternatively, make use of below modified script that asks user to login interactively and generates bearer token to call Azure DevOps API for PAT creation:

    $organization = "demodevOps25"
    
    Write-Output "Logging into Azure..."
    $loginOutput = az login --tenant "xxxxxxxxx.onmicrosoft.com" --only-show-errors
    
    try {
        $token = az account get-access-token --resource "499b84ac-1321-427f-aa17-267ca6975798" | ConvertFrom-Json
    } catch {
        Write-Error "Failed to retrieve access token. Please check your Azure login status."
        exit
    }
    
    $headers = @{
        Authorization = "Bearer $($token.accessToken)"
        'Content-Type' = 'application/json'
    }
    
    $body = @(
        @{
            displayName = $organization
            scope = "vso.build vso.code_full vso.tokens vso.profile"
            validTo = (Get-Date).AddDays(7).ToString("yyyy-MM-ddTHH:mm:ssZ")
            allOrgs = $false
        }
    ) | ConvertTo-Json
    
    $response = Invoke-RestMethod -Uri "https://vssps.dev.azure.com/$organization/_apis/tokens/pats?api-version=7.1-preview.1" `
                                  -Headers $headers `
                                  -Method Post `
                                  -Body $body `
                                  -ContentType "application/json"
    
    if ($response -and $response.patToken) {
        $newPat = $response.patToken.token
        Write-Output "New PAT generated: $newPat"
        $outputPath = Join-Path $env:USERPROFILE "Downloadspatgenoutput.json"
        $response | ConvertTo-Json -Depth 3 | Out-File $outputPath -Encoding UTF8
        Write-Output "PAT details saved to: $outputPath"
    } else {
        Write-Error "Failed to generate PAT. Check the request body and API version."
    }
    

    enter image description here

    Output:

    enter image description here

    To confirm that, I checked the saved file where new PAT details displayed successfully as below:

    enter image description here

    Azure DevOps Portal:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search