Utilisez Invoke-WebRequest avec un nom d'utilisateur et un mot de passe pour l'authentification de base sur l'API GitHub

127

Avec cURL, nous pouvons passer un nom d'utilisateur avec une requête Web HTTP comme suit:

$ curl -u <your_username> https://api.github.com/user

L' -uindicateur accepte un nom d'utilisateur pour l'authentification, puis cURL demandera le mot de passe. L'exemple cURL concerne l' authentification de base avec l'API GitHub .

Comment transmettre de la même manière un nom d'utilisateur et un mot de passe avec Invoke-WebRequest? L'objectif ultime est d'utiliser PowerShell avec l'authentification de base dans l'API GitHub.

Shaun Luttin
la source
$ pair doit être $pair = "$($user):$($pass)"Vérifiez la réponse approuvée. J'utilisais ce qui précède et cela m'a donné trop de douleur
Bhavjot
Aucune des solutions suggérant l' -Credentialapproche ne fonctionne car l'en-tête d'authentification correct n'est pas généré lorsque la demande est effectuée.
StingyJack
@Shaun Luttin - Ceci est un site de questions ..... et de réponses, pas un site de questions-réponses. Cet utilisateur préférerait voir une question et des réponses succinctes comme possibles autres que ce qui a fonctionné pour votre situation particulière, mais ne pas avoir à la lire deux fois (une fois dans la Question éditée, venez maintenant QuestionAnswer, puis à nouveau dans les réponses). Si la préoccupation était la réponse qui vous a aidé ne serait pas la plus proche de la question, StackExchange a des fonctionnalités pour amener la meilleure réponse acceptée aussi près que possible de la question déjà.
user66001
1
@ user66001 Merci pour vos commentaires. J'ai déplacé ma réponse en question vers sa propre réponse pour référence ultérieure. Je pense que c'est une amélioration.
Shaun Luttin
@ShaunLuttin - Excellente idée! :)
user66001

Réponses:

147

J'assume ici l'authentification de base.

$cred = Get-Credential
Invoke-WebRequest -Uri 'https://whatever' -Credential $cred

Vous pouvez obtenir vos informations d'identification par d'autres moyens ( Import-Clixml, etc.), mais il doit s'agir d'un [PSCredential]objet.

Modifier en fonction des commentaires:

GitHub rompt la RFC comme ils l'expliquent dans le lien que vous avez fourni :

L'API prend en charge l'authentification de base telle que définie dans la RFC2617 avec quelques légères différences. La principale différence est que la RFC exige que les demandes non authentifiées reçoivent une réponse avec 401 réponses non autorisées. Dans de nombreux endroits, cela révélerait l'existence de données utilisateur. Au lieu de cela, l'API GitHub répond avec 404 Not Found. Cela peut entraîner des problèmes pour les bibliothèques HTTP qui supposent une réponse 401 Unauthorized. La solution consiste à créer manuellement l'en-tête d'autorisation.

À Invoke-WebRequestma connaissance, Powershell attend une réponse 401 avant d'envoyer les informations d'identification, et comme GitHub n'en fournit jamais une, vos informations d'identification ne seront jamais envoyées.

Construire manuellement les en-têtes

Au lieu de cela, vous devrez créer vous-même les en-têtes d'authentification de base.

L'authentification de base prend une chaîne composée du nom d'utilisateur et du mot de passe séparés par deux user:pass- points , puis envoie le résultat encodé en Base64.

Un code comme celui-ci devrait fonctionner:

$user = 'user'
$pass = 'pass'

$pair = "$($user):$($pass)"

$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))

$basicAuthValue = "Basic $encodedCreds"

$Headers = @{
    Authorization = $basicAuthValue
}

Invoke-WebRequest -Uri 'https://whatever' -Headers $Headers

Vous pouvez combiner une partie de la concaténation de chaînes, mais je voulais la casser pour la rendre plus claire.

briantiste
la source
1
Comme je l'ai dit, cela fonctionne pour l'authentification de base, mais je ne sais pas quel type d'authentification utilise l'API GitHub. Vous pouvez publier des détails sur ce qui est attendu et cela pourrait nous aider à résoudre le problème.
briantist
1
Ah, il semble que GitHub (de leur propre aveu) ne respecte pas la RFC, mais Powershell l'est. J'ai modifié la réponse avec plus d'informations et une solution de contournement.
briantist
1
Ouais, si vous allez faire beaucoup de ces types d'appels, je vous recommande d'envelopper cela dans une fonction. Comme je l'ai dit, j'ai vraiment éclaté toutes les pièces pour plus de clarté, mais vous pouvez tout faire sur une seule ligne (ce serait juste en désordre).
briantist
1
@Aref, vous devriez publier une nouvelle question avec le code que vous utilisez. Si vous le faites et faites-le moi savoir, je vais jeter un coup d'œil.
briantist
1
Vous devrez également créer manuellement les en-têtes si vous essayez de vous authentifier par rapport à l'API REST Visual Studio Team Services
Brent Robinson
44

Utilisez ceci:

$root = 'REST_SERVICE_URL'
$user = "user"
$pass= "password"
$secpasswd = ConvertTo-SecureString $pass -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($user, $secpasswd)

$result = Invoke-RestMethod $root -Credential $credential
mfralou
la source
Pour une raison quelconque, la réponse sélectionnée n'a pas fonctionné pour moi lors de son utilisation sur TFS vNext, mais celle-ci a fait l'affaire. Merci beaucoup!
Tybs
La réponse sélectionnée ne fonctionnait pas pour exécuter un runbook PowerShell sur Azure pour lancer une tâche déclenchée, mais cette réponse a fonctionné.
Sam
7

J'ai dû faire ceci pour que ça marche:

$pair = "$($user):$($pass)"
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Pair))
$headers = @{ Authorization = "Basic $encodedCredentials" }
Invoke-WebRequest -Uri $url -Method Get -Headers $headers -OutFile Config.html
livy111
la source
6

Invoke-WebRequestsuit la RFC2617 comme @briantist l'a noté, cependant il existe certains systèmes (par exemple JFrog Artifactory) qui permettent une utilisation anonyme si l'en- Authorizationtête est absent, mais qui répondront 401 Forbiddensi l'en-tête contient des informations d'identification invalides.

Cela peut être utilisé pour déclencher la 401 Forbiddenréponse et se mettre -Credentialsau travail.

$login = Get-Credential -Message "Enter Credentials for Artifactory"

                              #Basic foo:bar
$headers = @{ Authorization = "Basic Zm9vOmJhcg==" }  

Invoke-WebRequest -Credential $login -Headers $headers -Uri "..."

Cela enverra l'en-tête invalide la première fois, qui sera remplacé par les informations d'identification valides dans la deuxième demande car il -Credentialsremplace l'en- Authorizationtête.

Testé avec Powershell 5.1

Leonard Brünings
la source
5

Si quelqu'un avait besoin d'une seule doublure:

iwr -Uri 'https://api.github.com/user' -Headers @{ Authorization = "Basic "+ [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("user:pass")) }
karolberezicki
la source
2

une autre façon est d'utiliser certutil.exe, enregistrez votre nom d'utilisateur et votre mot de passe dans un fichier par exemple in.txt comme nom d'utilisateur: mot de passe

certutil -encode in.txt out.txt

Vous devriez maintenant pouvoir utiliser la valeur d'authentification de out.txt

$headers = @{ Authorization = "Basic $((get-content out.txt)[1])" }
Invoke-WebRequest -Uri 'https://whatever' -Headers $Headers
Mayursharma
la source
2

Je sais que c'est un peu en dehors de la demande originale des OP, mais je suis tombé sur cela en cherchant un moyen d'utiliser Invoke-WebRequest contre un site nécessitant une authentification de base.

La différence est que je ne voulais pas enregistrer le mot de passe dans le script. Au lieu de cela, je voulais demander au script runner les informations d'identification du site.

Voici comment je l'ai géré

$creds = Get-Credential

$basicCreds = [pscredential]::new($Creds.UserName,$Creds.Password)

Invoke-WebRequest -Uri $URL -Credential $basicCreds

Le résultat est que le script runner est invité avec une boîte de dialogue de connexion pour l'U / P, puis Invoke-WebRequest est capable d'accéder au site avec ces informations d'identification. Cela fonctionne car $ Creds.Password est déjà une chaîne chiffrée.

J'espère que cela aidera quelqu'un à la recherche d'une solution similaire à la question ci-dessus mais sans enregistrer le nom d'utilisateur ou le PW dans le script

Ernest Correale
la source
0

C'est ce qui a fonctionné pour notre situation particulière.

Les notes proviennent de Wikipedia sur l'authentification de base du côté client . Merci à la réponse de @ briantist pour l'aide!

Combinez le nom d'utilisateur et le mot de passe en une seule chaîne username:password

$user = "shaunluttin"
$pass = "super-strong-alpha-numeric-symbolic-long-password"
$pair = "${user}:${pass}"

Encodez la chaîne dans la variante RFC2045-MIME de Base64, sauf si elle n'est pas limitée à 76 caractères / ligne.

$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)

Créez la valeur Auth comme méthode, un espace, puis la paire encodée Method Base64String

$basicAuthValue = "Basic $base64"

Créer l'en-tête Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

$headers = @{ Authorization = $basicAuthValue }

Appeler la requête Web

Invoke-WebRequest -uri "https://api.github.com/user" -Headers $headers

La version PowerShell de ceci est plus détaillée que la version cURL. Pourquoi donc? @briantist a souligné que GitHub rompt la RFC et que PowerShell s'y tient. Cela signifie-t-il que cURL rompt également avec la norme?

Shaun Luttin
la source