title: Azure credentials have not been set up or have expired, please run Connect-AzAccount
body: <p>Related to the following question (<a href="https://stackoverflow.com/questions/54286763/azure-devops-custom-task-powershell-with-azure-authentification">Azure DevOps - Custom Task - PowerShell with Azure Authentification</a>) I am using now <code>Connect-AzAccount</code> to login by using a Azure DevOps Custom Task.</p>
  
  <p>In the next step I want to run multiple jobs in parallel to first manipulate and then deploy certain Azure resources via templates. Working with AzureRM this worked without problems but after switching to Az I always get the error</p>
  
  <blockquote>
    <p>Your Azure credentials have not been set up or have expired, please
    run Connect-AzAccount to set up your Azure credentials.</p>
  </blockquote>
  
  <p>I already updated the Az modules to the most current version.</p>
  
  <p>Here is how I do it:</p>
  
  <p><strong>Authenticate</strong></p>
  
  <pre><code>try {
      $endpoint = Get-VstsEndpoint -Name $serviceName -Require
      if (!$endpoint) {
          throw "Endpoint not found..."
      }
      $subscriptionId = $endpoint.Data.SubscriptionId
      $tenantId = $endpoint.Auth.Parameters.TenantId
      $servicePrincipalId = $endpoint.Auth.Parameters.servicePrincipalId
      $servicePrincipalKey = $endpoint.Auth.Parameters.servicePrincipalKey
  
      $spnKey = ConvertTo-SecureString $servicePrincipalKey -AsPlainText -Force
      $credentials = New-Object System.Management.Automation.PSCredential($servicePrincipalId,$spnKey)
  
      Connect-AzAccount -ServicePrincipal -TenantId $tenantId -Credential $credentials
      Select-AzSubscription -SubscriptionId $subscriptionId -Tenant $tenantId
  
      $ctx = Get-AzContext
      Write-Host "Connected to subscription '$($ctx.Subscription)' and tenant '$($ctx.Tenant)'..."
  } catch {
      Write-Host "Authentication failed: $($_.Exception.Message)..." 
  }
  </code></pre>
  
  <p><strong>Deploy in parallel</strong></p>
  
  <pre><code>foreach ($armTemplateFile in $armTemplateFiles) {
      $logic = {
          Param(
              [object] 
              [Parameter(Mandatory=$true)]
              $ctx,
  
              [object] 
              [Parameter(Mandatory=$true)]
              $armTemplateFile,
  
              [string] 
              [Parameter(Mandatory=$true)]
              $resourceGroupName
          )
  
          ####################################################################
          # Functions
          function Format-ValidationOutput {
              param ($ValidationOutput, [int] $Depth = 0)
              Set-StrictMode -Off
              return @($ValidationOutput | Where-Object { $_ -ne $null } | ForEach-Object { @('  ' * $Depth + ': ' + $_.Message) + @(Format-ValidationOutput @($_.Details) ($Depth + 1)) })
          }
  
          ####################################################################
          # Logic
  
          # Some template manipulation
  
  
          $paramFileContent | ConvertTo-Json -Depth 100 | Set-Content -Path $paramTemplateFile.FullName
          $templateFileContent | ConvertTo-Json -Depth 100 | Set-Content -Path $armTemplateFile.FullName
  
          ####################################################################
          # Test Deployment
          $ErrorMessages = Format-ValidationOutput (Test-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName `
                                                                                          -TemplateFile $armTemplateFile.FullName `
                                                                                          -TemplateParameterFile $paramTemplateFile.FullName `
                                                                                          -DefaultProfile $ctx)
          if ($ErrorMessages) {
              Write-Host '', 'Validation returned the following errors:', @($ErrorMessages), '', 'Template is invalid.'
          }
          else { # Deploy
  
              New-AzResourceGroupDeployment -Name (($armTemplateFile.Name).Split(".")[0] + ((Get-Date).ToUniversalTime()).ToString('MMddHHmm')) `
                                                  -ResourceGroupName $resourceGroupName `
                                                  -TemplateFile $armTemplateFile.FullName `
                                                  -TemplateParameterFile $paramTemplateFile.FullName `
                                                  -Force `
                                                  -ErrorVariable ErrorMessages `
                                                  -DefaultProfile $ctx
              if ($ErrorMessages) {
                  Write-Host '', 'Template deployment returned the following errors:', @(@($ErrorMessages) | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") })
              }
          }
      }
      Start-Job $logic -ArgumentList (Get-AzContext), $armTemplateFile, $ResourceGroupName
  }
  
  While (Get-Job -State "Running")
  {
      Start-Sleep 10
      Write-Host "Jobs still running..."
  }
  
  Get-Job | Receive-Job
  </code></pre>