I saw this question about Python requests attempting to authenticate to Azure DevOps REST API and receiving HTTP Status 203, Non-Authoritative Information. When viewing the text response, its just the HTML of the login page and not actually logging me in. I used the Authorization: Basic <BASE64 PAT> listed on their REST API page, but it doesn't seem to be working. Here is my code example:
"""Using Python and Requests to interact with Azure DevOps REST API
"""
import base64
import pprint as pp
import requests
with open('ado_pat.txt', 'r') as file:
PERSONAL_AUTHENTICATION_TOKEN = file.read().replace('\n', '')
PAT_BASE_64 = base64.b64encode(
b'{PERSONAL_AUTHENTICATION_TOKEN}').decode('ascii')
COLLECTION = 'collection_name'
ORGANIZATION_URL = f'https://dev.azure.com/{COLLECTION}'
RESOURCE_PATH = '/_apis/projects?api-version=5.1'
HEADERS = {
'Authorization': f'Basic {PAT_BASE_64}',
'Accept': 'application/json'
}
try:
ADO_RESPONSE = requests.get(
ORGANIZATION_URL + RESOURCE_PATH, headers=HEADERS)
pp.pprint(ADO_RESPONSE)
pp.pprint(ADO_RESPONSE.text)
ADO_RESPONSE.raise_for_status()
except requests.exceptions.HTTPError as err:
pp.pprint(err)
This is the response that I get:
<Response [203]>
(''\r\n'
Then it displays the whole login page. I would use the microsoft/azure-devops-python-api but I don't really understand or see the methods I can call nor really understand how that works.
--EDIT WORKING EXAMPLE --
This example works now.
"""Using Python and Requests to interact with Azure DevOps REST API
"""
import base64
import pprint as pp
import requests
with open('ado_pat.txt', 'r') as file:
PERSONAL_AUTHENTICATION_TOKEN = file.read().replace('\n', '')
USERNAME = ""
USER_PASS = USERNAME + ":" + PERSONAL_AUTHENTICATION_TOKEN
B64USERPASS = base64.b64encode(USER_PASS.encode()).decode()
COLLECTION = 'collection_name'
ORGANIZATION_URL = f'https://dev.azure.com/{COLLECTION}'
RESOURCE_PATH = '/_apis/projects?api-version=5.1'
HEADERS = {
'Authorization': 'Basic %s' % B64USERPASS
}
try:
ADO_RESPONSE = requests.get(
ORGANIZATION_URL + RESOURCE_PATH, headers=HEADERS)
pp.pprint(ADO_RESPONSE)
pp.pprint(ADO_RESPONSE.text)
ADO_RESPONSE.raise_for_status()
except requests.exceptions.HTTPError as err:
pp.pprint(err)
-
1Does this answer your question? Using a personal access token for azure devops API repository manipulationShayki Abramczyk– Shayki Abramczyk2019年10月29日 20:38:31 +00:00Commented Oct 29, 2019 at 20:38
-
I'll update my code to the working version. What I really got is that the M$ example didn't actually work, and isn't very good.FilBot3– FilBot32019年10月29日 21:00:46 +00:00Commented Oct 29, 2019 at 21:00
-
Thanks for sharing your solution here, you could Accept it as an Answer , so it could help other community members who get the same issues and we could archive this thread, thanks.meta.stackexchange.com/questions/5234/…Frank Wang-MSFT– Frank Wang-MSFT2019年11月01日 07:37:09 +00:00Commented Nov 1, 2019 at 7:37
-
Accepted. I had looked at it before but I needed to wait longer than other things came up.FilBot3– FilBot32019年11月01日 13:20:07 +00:00Commented Nov 1, 2019 at 13:20
-
Does this answer your question? getting 203 with error when using vsts rest apiMichael Freidgeim– Michael Freidgeim2024年03月12日 18:04:54 +00:00Commented Mar 12, 2024 at 18:04
4 Answers 4
Using a comment's link, I was able to get the code above working. This is the end result working code.
"""Using Python and Requests to interact with Azure DevOps REST API
"""
import base64
import json
import pprint as pp
import requests
with open('ado_pat.txt', 'r') as file:
PERSONAL_AUTHENTICATION_TOKEN = file.read().replace('\n', '')
USERNAME = ""
USER_PASS = USERNAME + ":" + PERSONAL_AUTHENTICATION_TOKEN
B64USERPASS = base64.b64encode(USER_PASS.encode()).decode()
COLLECTION = 'collection_name'
ORGANIZATION_URL = f'https://dev.azure.com/{COLLECTION}'
RESOURCE_PATH = '/_apis/securitynamespaces?api-version=5.1'
HEADERS = {
'Authorization': 'Basic %s' % B64USERPASS
}
try:
ADO_RESPONSE = requests.get(
ORGANIZATION_URL + RESOURCE_PATH, headers=HEADERS)
pp.pprint(ADO_RESPONSE)
pp.pprint(ADO_RESPONSE.text)
ADO_RESPONSE.raise_for_status()
except requests.exceptions.HTTPError as err:
pp.pprint(err)
with open('output.json', 'w') as file:
file.write(json.dumps(ADO_RESPONSE.json(), indent=4))
It seems that the API docs didn't specify how to encode the PAT properly and needed to be reworked.
1 Comment
you can also do this
import requests
from requests.auth import HTTPBasicAuth
requests.post(
url=your_link,
auth=HTTPBasicAuth("", PAT),
headers=headers
)
Comments
In case this helps someone because I have been struggling for hours, I was running the code from GitLab runners and pulling the PAT from the CI/CD variables. It turns out, when variables are set to protected and/or masked, this messes up the encoding and the PAT becomes incorrectly encoded. Disabling the protection and masking fixed it for me.
Comments
Below is the way to do it via Rest Client vscode extension. My mistake for 203 error, was using Bearer authz instead of Basic.
@org = MyCompany
@authz = Basic My_Personal_Access_Token_Base64_with_colon_prefix
GET https://dev.azure.com/{{org}}/_apis/projects
Authorization: {{authz}}
Content-Type: application/json
Bash script inferred from ado website to generate colon-prefix base64 of PAT:
pat=ThePersonalAccessTokenAsFromADO
b64pat=$(printf "%s"":$pat" | base64)
echo $b64pat
Comments
Explore related questions
See similar questions with these tags.