This Content is from Stack Overflow. Question asked by Ben Baker
I am trying to use OAuth2 to access the Azure DevopsAPI, to query work-items.
But I am unable to get the access tokene.
I am using Python and Flask. My approach is based on these resources:
- Microsoft documentation , there currently Step 3 is relevant
- OAuth Tutorial, which worked fine for Github, but is not working for Azure.
from requests_oauthlib import OAuth2Session from flask import Flask, request, redirect, session, url_for
client_id = "..." client_secret = "..." authorization_base_url = "https://app.vssps.visualstudio.com/oauth2/authorize" token_url = "https://app.vssps.visualstudio.com/oauth2/token" callback_url = "..."
Step 1: User Authorization. (works fine)
@app.route("/") def demo(): azure = OAuth2Session(client_id) authorization_url, state = azure.authorization_url(authorization_base_url) session['oauth_state'] = state authorization_url += "&scope=" + authorized_scopes + "&redirect_uri=" + callback_url print(authorization_url) return redirect(authorization_url)
Step 2: Retrieving an access token (generates an error)
@app.route("/callback", methods=["GET"]) def callback(): fetch_body = "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" "&client_assertion=" + client_secret + "&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" "&assertion=" + request.args["code"] + "&redirect_uri=" + callback_url azure = OAuth2Session(client_id, state=session['oauth_state']) token = azure.fetch_token(token_url=token_url, client_secret=client_secret, body=fetch_body, authorization_response=request.url) azure.request() session['oauth_token'] = token return redirect(url_for('.profile'))
The application-registration and adhoc-SSL-certification are working fine (using it just temporary).
When I use the client_assertion in Postman, I get a correct response from Azure:
But when I execute the code, this error is thrown:
oauthlib.oauth2.rfc6749.errors.MissingTokenError: (missing_token) Missing access token parameter.
Which only lets me know, that no token was received.
There is one issue in the generated request body, where the grant_type is added twice:
The first value is expected by Azure, but the second one is generated automatically by the library.
Now when I specify the grant_type in the fetch_token call, like this:
token = azure.fetch_token(token_url=token_url, client_secret=client_secret, body=fetch_body, grant_type="urn:ietf:params:oauth:grant-type:jwt-bearer", authorization_response=request.url)
I get this error
TypeError: prepare_token_request() got multiple values for argument 'grant_type'
And the actual request to Azure is not even sent.
I see in the web_application.py that is used by oauth2_session.py, that grant_type =’authorization_code’ is set fixed, so I guess this library is generally incompatible with Azure.
Is that the case?
If so, what would be the simplest way to connect to Azure-OAuth with Python (Flask)?
I would be very grateful for any advice and help that point me in the right direction.
I just found the azure.devops library that solves my problem.
- azure-devops-python-api query for work item where field == string
from azure.devops.connection import Connection from azure.devops.v5_1.work_item_tracking import Wiql from msrest.authentication import BasicAuthentication import pprint # Fill in with your personal access token and org URL personal_access_token = '... PAT' organization_url = 'https://dev.azure.com/....' # Create a connection to the org credentials = BasicAuthentication('', personal_access_token) connection = Connection(base_url=organization_url, creds=credentials) # Get a client (the "core" client provides access to projects, teams, etc) core_client = connection.clients.get_core_client() wit_client = connection.clients.get_work_item_tracking_client() query = "SELECT [System.Id], [System.WorkItemType], [System.Title], [System.AssignedTo], [System.State]," \ "[System.Tags] FROM workitems WHERE [System.TeamProject] = 'Test'" wiql = Wiql(query=query) query_results = wit_client.query_by_wiql(wiql).work_items for item in query_results: work_item = wit_client.get_work_item(item.id) pprint.pprint(work_item.fields['System.Title'])
This Question was asked in StackOverflow by Ben Baker and Answered by Ben Baker It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.