I have been trying to do basic authentication with the GitHub Api with PowerShell. The following do not work:
> $cred = get-credential
# type username and password at prompt
> invoke-webrequest -uri https://api.github.com/user -credential $cred
Invoke-WebRequest : {
"message":"Requires authentication",
"documentation_url":"https://developer.github.com/v3"
}
How do we do basic authentication using PowerShell with the GitHub Api?
Basic auth basically expects that you send the credentials in an Authorization header in the following form:
'Basic [base64("username:password")]'
In PowerShell that would translate to something like:
function Get-BasicAuthCreds {
param([string]$Username,[string]$Password)
$AuthString = "{0}:{1}" -f $Username,$Password
$AuthBytes = [System.Text.Encoding]::Ascii.GetBytes($AuthString)
return [Convert]::ToBase64String($AuthBytes)
}
And now you can do:
$BasicCreds = Get-BasicAuthCreds -Username "Shaun" -Password "s3cr3t"
Invoke-WebRequest -Uri $GitHubUri -Headers #{"Authorization"="Basic $BasicCreds"}
Related
Currently we use an approach to reach DevOps and trigger "release pipelines" from a specific VM1 by utilizing user's DevOps PAT. We run PowerShell commands below at VM1:
$userPatToken = "xxxdfdgklfdgofkglfg4565gfhgfhgfh4gf54h54545fhfghfdffg"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "", $userPatToken)))
$url = "https://vsrm.dev.azure.com/MyOrg/MyProject/_apis/release/releases?definitionId=7&$top=100&api-version=6.0"
Invoke-RestMethod -Method Get -Uri $url -ContentType "application/json" -Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo) }
The user is AAD one, is there a way to use it's let say AAD credentials and authenticate to DevOps and do the same?
Or may there is a way to use VMs system managed (or any user managed) identity to authenticate into DevOps and trigger release pipelines? We do not want to be dependent of the user's PAT.
It should be written in PowerShell.
If you don't want to use the PAT, you can install Az powershell module, login with a user account which has the permission in your devops org via Connect-AzAccount.
Then, you can get the token via below command. Please note don't change the 499b84ac-1321-427f-aa17-267ca6975798 in the script, it is the well-known resource id of the DevOps REST API.
$token = (Get-AzAccessToken -ResourceUrl "499b84ac-1321-427f-aa17-267ca6975798").Token
Then, you can pass the token to your powershell script. You can find more details/sample script here.
Edit:
Add username&Password automation script sample:
Install-Module -Name Az -Confirm:$False -Force -AllowClobber
Import-Module Az
$username = "useremail"
$password = "password"
$SecurePassword = ConvertTo-SecureString "$password" -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential($username, $SecurePassword)
Connect-AzAccount -Credential $credentials -TenantId yourTenantID
$token = (Get-AzAccessToken -ResourceUrl "499b84ac-1321-427f-aa17-267ca6975798").Token
$URL = 'https://dev.azure.com/{orgname}/{Projectname}/_apis/pipelines/{pipelineID}/runs?api-version=6.0-preview.1'
$header = #{
'Authorization' = 'Bearer ' + $token
'Content-Type' = 'application/json'
}
$body = #"
{
"resources": {
"repositories": {
"self": {
"refName": "refs/heads/master"
}
}
}
}
"#
Invoke-RestMethod -Method Post -Uri $URL -Headers $header -Body $body
I'm writing a PowerShell script to query an application API (Qualys), and the first step is to authenticate. I can only do it unsecurely:
[string]$username = "username"
[string]$password = "superpassword"
$hdrs= #{"X-Requested-With"="Powershell"}
$base = "https://application-base-url/api/2.0/fo"
$body= "action=login&username=$username&password=$password"
Invoke-RestMethod -SessionVariable sess -Headers $hdrs -URI "$base/session/" -Method POST -Body $body
It works, but as you can see, the username & password are stored in the file. I would like Powershell to prompt me the username and password, and use it to authenticate while securely manage them.
I tried to use Get-Credential but I couldn't make it work. Could anyone help?
Apparently you need to put the plain-text password in the body.
To retrieve that from a credential object you get from using Get-Credential, use:
$cred = Get-Credential
$username = $cred.UserName
$password = $cred.GetNetworkCredential().Password # --> the password as plain-text
When I try to connect to tfs the function Get-Data failed with 401 error although the function Get-DataWithCred succeed with the same argument.
And don't understand the difference with this two ?
function Get-Data([string]$username, [string]$password, [string]$url)
{
# Step 1. Create a username:password pair
$credPair = "$($username):$($password)"
# Step 2. Encode the pair to Base64 string
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))
# Step 3. Form the header and add the Authorization attribute to it
$headers = #{ Authorization = "Basic $encodedCredentials" }
# Step 4. Make the GET request
$responseData = Invoke-WebRequest -Uri $url -Method Get -Headers $headers
return $responseData
}
function Get-DataWithCred([string]$username, [string]$password, [string]$url)
{
$p = ConvertTo-SecureString -String $password -AsPlainText -Force
$Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $p
$responseData = Invoke-WebRequest -Uri $url -Method Get -Credential $Cred
return $responseData
}
The purpose is too connect through tfs with python script who failed the same way that the function Get-Data when I use the requests library.
>>> r = requests.get('https://tfs-url.com', auth=('user', 'pass'))
>>> r.status_code
401
Looks like there is a problem with $encodedCredentials.
Take a look at Choosing the right authentication mechanism
For my script who connect to TFS i use the following code :
$strUser = 'domain\userID'
$password = "YOURPASSWORD"
$strPass = ConvertTo-SecureString -String $password -AsPlainText -Force
$cred= New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($strUser, $strPass)
And than connect to the TFS as you did :
$responseData = Invoke-WebRequest -Uri $url -Method Get -Credential $cred
Or, If you would like to connect to the TFS with the user who runs the script you can use
-UseDefaultCredentials
code snippet :
$responseData = Invoke-WebRequest -Uri $url -Method Get -UseDefaultCredentials
You need to use a microsoft way to pass your credential : the ntlm protocol.
This protocol are not supported by default by requests but a library requests_ntlm extend requests by adding support to ntlm.
A simple example:
import os
import requests
from requests_ntlm import HttpNtlmAuth
def main():
user = "user"
password = "password"
session = requests.Session()
session.auth = HttpNtlmAuth(user, password)
url = "https://tfs-url.com"
response = session.get(url)
print(response)
if __name__ == "__main__":
main()
I'm creating an Azure AD application using AzureAD module to call Microsoft Graph API. I can successfully generate the access token. But, when I try to call the API I have an error "message": "Invalid scope claims/roles.".
When I click on "Grant Permissions" button in my created application in Azure Portal and retry the call to API, the call is working.
I don't find anywhere how to do this "Grant Permissions" actions with Powershell. Is there a way to do that ?
Thanks
Damien
There is an easy way to do this (as admin), it requires you have the AzureAD and AzureRM modules installed for Powershell and is not supported by Microsoft.
Original post / reference to my blog is here: http://www.lieben.nu/liebensraum/2018/04/how-to-grant-oauth2-permissions-to-an-azure-ad-application-using-powershell-unattended-silently/
The specific code sample that should help you accomplish this:
Function Grant-OAuth2PermissionsToApp{
Param(
[Parameter(Mandatory=$true)]$Username, #global administrator username
[Parameter(Mandatory=$true)]$Password, #global administrator password
[Parameter(Mandatory=$true)]$azureAppId #application ID of the azure application you wish to admin-consent to
)
$secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($Username, $secpasswd)
$res = login-azurermaccount -Credential $mycreds
$context = Get-AzureRmContext
$tenantId = $context.Tenant.Id
$refreshToken = #($context.TokenCache.ReadItems() | where {$_.tenantId -eq $tenantId -and $_.ExpiresOn -gt (Get-Date)})[0].RefreshToken
$body = "grant_type=refresh_token&refresh_token=$($refreshToken)&resource=74658136-14ec-4630-ad9b-26e160ff0fc6"
$apiToken = Invoke-RestMethod "https://login.windows.net/$tenantId/oauth2/token" -Method POST -Body $body -ContentType 'application/x-www-form-urlencoded'
$header = #{
'Authorization' = 'Bearer ' + $apiToken.access_token
'X-Requested-With'= 'XMLHttpRequest'
'x-ms-client-request-id'= [guid]::NewGuid()
'x-ms-correlation-id' = [guid]::NewGuid()}
$url = "https://main.iam.ad.ext.azure.com/api/RegisteredApplications/$azureAppId/Consent?onBehalfOfAll=true"
Invoke-RestMethod -Uri $url -Headers $header -Method POST -ErrorAction Stop
}
I came across the same error 'Refresh token is malformed'. When reading out the refreshtoken the token was twice in the string. Resolved it by adding the line
$refreshtoken = $refreshtoken.Split("`n")[0]
If I am not wrong, then it is using "Admin Consent". In that case, you should be using &prompt=admin_consent in the auth request directly.
If your application requests an app-only permission and a user tries to sign in to the application, an error message is displayed saying the user isn’t able to consent.
Whether or not a permission requires admin consent is determined by the developer that published the resource, and can be found in the documentation for the resource.
Link: Multi-tenant App pattern
List of Available permissions for the Azure AD Graph API and Microsoft Graph API are
Graph API Permission Scopes
Consent Framework
Hope it helps.
This answer builds on top of Jos's answer.
Active Directory Authentication library doesn't make the refresh tokens publicly available anymore. More information can be found in github/azure-powershell/7525.
The modified snippet below worked for me
Connect-AzAccount
$context = Get-AzContext
$tenantId = $context.Tenant.TenantId
Connect-AzureAD -TenantId $tenantId -AccountId $context.Account.Id
$appId = 'Your Application ID'
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $tenantId, $null, "Never", $null, "74658136-14ec-4630-ad9b-26e160ff0fc6")
$headers = #{
'Authorization' = 'Bearer ' + $token.AccessToken
'X-Requested-With'= 'XMLHttpRequest'
'x-ms-client-request-id'= [guid]::NewGuid()
'x-ms-correlation-id' = [guid]::NewGuid()}
$url = "https://main.iam.ad.ext.azure.com/api/RegisteredApplications/$appId/Consent?onBehalfOfAll=true"
Invoke-RestMethod -Uri $url -Headers $headers -Method POST -ErrorAction Stop
This question already has answers here:
PowerShell's Invoke-RestMethod equivalent of curl -u (Basic Authentication)
(9 answers)
Closed 6 years ago.
I'm trying to access a web api for Sonarqube on our local server. The examples in the Sonarqube documentation are all curl-based and I'm trying to translate them to PowerShell, either Invoke-WebRequest or Invoke-RestMethod. I'm having issues with credentials. I keep getting a 401 Not Authorized error. I've reviewed every post I can find on doing this and I don't see a comprehensive complete answer on how to do this.
Here's what I'm running now:
$user='myUserid'
$password='myPassword'
$secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($user, $secpasswd)
$uri="http://myServer.ad1.prod:9000/api/properties"
Invoke-RestMethod -Uri $uri -Credential $cred -Method Get
And the response is:
Invoke-RestMethod : {"err_code":401,"err_msg":"Unauthorized"}
I've run the curl command as defined in the original product documentation and it works. Same userid, same password, same URI, same method.
Can anyone advise?
My curl command is:
curl -u myID:myPassword X GET http://myServer.ad.prod:9000/api/properties
I think you need to pass in a credential like this:
$username = "user"
$password = "password"
$authInfo = ("{0}:{1}" -f $username,$password)
$authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
$authInfo = [System.Convert]::ToBase64String($authInfo)
$headers = #{Authorization=("Basic {0}" -f $authInfo)}
Invoke-RestMethod -Method Head -Uri "https://pathtowhatever" -ContentType 'text/json' -Headers $headers