I am trying to access TFS REST API in Python 2 but getting 401 Authorization Error. I am able to access API url from web-browser using same credentials. Also same credentials is working with .Net code. Tried with urllib2 library as guided in this solution. Any suggestion to access TFS api in Python2?
tfs.py
import requests
from requests.auth import HTTPDigestAuth
username = '<UserName>'
password = '<Password>'
tfsApi = 'https://{myserver}/tfs/collectionName/_apis/projects?api-version=2.0'
tfsResponse = requests.get(tfsApi, auth=(username, password))
if(tfsResponse.ok):
tfsResponse = tfsResponse.json()
print(tfsResponse)
else:
tfsResponse.raise_for_status()
Error:
Traceback (most recent call last):
File "D:\Scripts\tfs.py", line 13, in <module>
tfsResponse.raise_for_status()
File "C:\Python27\lib\site-packages\requests\models.py", line 862, in raise_fo
r_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://{myserver}/tfs/collectionName/_apis/projects?api-version=2.0
.Net Working code:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", AppConfig.TFS_API_USER, AppConfig.TFS_API_PASS))));
TFS uses NTLM authentication protocol , Hence I have to update my code with HTTP NTLM authentication using the requests library.
Working code:
import requests
from requests_ntlm import HttpNtlmAuth
username = '<DOMAIN>\\<UserName>'
password = '<Password>'
tfsApi = 'https://{myserver}/tfs/collectionName/_apis/projects?api-version=2.0'
tfsResponse = requests.get(tfsApi,auth=HttpNtlmAuth(username,password))
if(tfsResponse.ok):
tfsResponse = tfsResponse.json()
print(tfsResponse)
else:
tfsResponse.raise_for_status()
It seems you want to get a list of team projects with REST API. The API should look like:
-
http://tfsserver:8080/tfs/CollectionName/_apis/projects?api-version=1.0
Make sure you have enabled Basic Auth for your TFS:
check your IIS to see whether the Basic authentication service role
is installed.
go to IIS Manager, select Team Foundation Server -- Authentication
and disable everything other than Basic Authentication. Then do the
same for the tfs node under Team Foundation Server.
restart your IIS.
Related
Setup:
Users are created on On-Prem AD and synced to Azure AD via Azure AD Connect
I have a single-tenant app set up on Azure AD
I created a user (On-Prem, synced to AAD) that can authenticate without MFA (we need to use username-password authentication due to an internal limitation).
Here is the non-interactive authentication code:
import msal
# create a public client app
authority_url = f"https://login.microsoftonline.com/{TENANT_ID}"
msal_app = msal.PublicClientApplication(client_id=CLIENT_ID, authority=authority_url)
# acquire token
token = msal_app.acquire_token_by_username_password(username=USERNAME, password=PASSWORD, scopes=SCOPES)
I'm getting the following error:
Traceback (most recent call last):
File "/./scripts/aad.py", line 8, in <module>
token = msal_app.acquire_token_by_username_password(
File "/usr/local/lib/python3.10/site-packages/msal/application.py", line 1420, in acquire_token_by_username_password
response = _clean_up(self._acquire_token_by_username_password_federated(
File "/usr/local/lib/python3.10/site-packages/msal/application.py", line 1447, in _acquire_token_by_username_password_federated
wstrust_result = wst_send_request(
File "/usr/local/lib/python3.10/site-packages/msal/wstrust_request.py", line 60, in send_request
return parse_response(resp.text)
File "/usr/local/lib/python3.10/site-packages/msal/wstrust_response.py", line 49, in parse_response
raise RuntimeError("WsTrust server returned error in RSTR: %s" % (error or body))
RuntimeError: WsTrust server returned error in RSTR: {'reason': 'MSIS7068: Access denied.', 'code': 'a:FailedAuthentication'}
Searching through Google I found that this can be caused by MFA, but the user is excluded from MFA. I've also verified that there are no Conditional Access policies in place to block the user accessing the app.
Using Interactive auth works as expected. Any ideas on how to get non-interactive auth to work or what might be the issue here?
First, no guesswork! You would need to login to Azure AD with elevated privilege (Security Reader at the least if not Global Administrator).
Go to Enterprise Applications and locate your application by client id.
One you are at the application, go to Sign-in tab/pane.
Review the sign-in activities. You should see the reason authentication failed in overview tab. Look at the Conditional Access tab and you will know if there is any policy that blocked the sign-in.
Take action based on what you identified in sign-in activity.
Okay, I am going to make an educated guess! When you login as non-interactive, you have two authentication choices - ROPC and Client Credential- both requires client_secret to be passed in the request but you have not! Since you are using username and password, it implies that msal is using ROPC and you must include client secret.
Following the directions in the google docs for using firebase for auth in GAE, I am sending an authorization token from Android to my backend python server. Reading that token using the following code:
import google.auth.transport.requests
import google.oauth2.id_token
HTTP_REQUEST = google.auth.transport.requests.Request()
id_token = headers['authorization'].split(' ').pop()
user_info = google.oauth2.id_token.verify_firebase_token(
id_token, HTTP_REQUEST)
results in the following stack trace:
File "/Users/alex/projects/don/don_server/mobile/main.py", line 61, in get_video
user_id = get_user_id(self.request_state.headers)
File "/Users/alex/projects/don/don_server/mobile/main.py", line 37, in get_user_id
id_token, HTTP_REQUEST)
File "/Users/alex/projects/don/don_server/mobile/lib/google/oauth2/id_token.py", line 115, in verify_firebase_token
id_token, request, audience=audience, certs_url=_GOOGLE_APIS_CERTS_URL)
File "/Users/alex/projects/don/don_server/mobile/lib/google/oauth2/id_token.py", line 76, in verify_token
certs = _fetch_certs(request, certs_url)
File "/Users/alex/projects/don/don_server/mobile/lib/google/oauth2/id_token.py", line 50, in _fetch_certs
response = request(certs_url, method='GET')
File "/Users/alex/projects/don/don_server/mobile/lib/google/auth/transport/requests.py", line 111, in __call__
raise exceptions.TransportError(exc)
TransportError: ('Connection aborted.', error(13, 'Permission denied'))
I've double checked my firebase project settings and localhost is listed as an authorized domain in the authentication sign-in section (I'm running this on the GAE local dev server).
As far as I can recall this was working a couple weeks ago. Any ideas?
UPDATE:
I implemented the same authentication using a service account as recommended in the firebase docs but am getting the same error message:
from firebase_admin import auth, credentials
import firebase_admin
fpath = os.path.join(os.path.dirname(__file__), 'shared', 'firebase-admin-private-key.json')
cred = credentials.Certificate(fpath)
firebase_admin.initialize_app(cred)
Then to process an incoming token
id_token = headers['authorization'].split(' ').pop()
user_info = auth.verify_id_token(id_token)
At some point I upgraded my requests library. Because requests doesn't play well with GAE, the calls to the firebase server failed. By downgrading to version 2.3.0 this now works.
pip install -t lib requests==2.3.0
Alternatively monkeypatching requests as suggested in this answer works as well!
import requests_toolbelt.adapters.appengine
requests_toolbelt.adapters.appengine.monkeypatch()
I'm trying to read this Soap API 'https://www.shab.ch/soapserver' using Python's Zeep.
from requests import Session
from requests.auth import HTTPBasicAuth
from zeep import Client
from zeep.transports import Transport
session = Session()
session.auth = HTTPBasicAuth('MYUSERNAME', 'MYPASSWORD')
client = Client('https://www.shab.ch/shabforms/acmsservice?wsdl',
transport=Transport(session=session))
But get the following error message:
HTTPError: 403 Client Error: Forbidden for url:
https://www.shab.ch/shabforms/acmsservice?wsdl
Can anybody see what I am doing wrongly here?
It doesn't seem that Python is your problem. Instead you have a rights issue for the WSDL file. A quick Googling turned up:
https://www.shab.ch/soapserver
https://www.shab.ch/shabforms/soapserver?wsdl
You don't have permission to go to that part of the Shab.ch server. You need a username and password. Contact: info#sogc.ch
I'm trying to connect to my Google Cloud Endpoints API that is running as an Appengine app:
#endpoints.api(name='helloworldendpoints', allowed_client_ids=["1234", "12345"], version='v1', auth_level=endpoints.AUTH_LEVEL.REQUIRED)
class HelloWorldApi(remote.Service):
...
The API request is as follows:
scopes = ["https://www.googleapis.com/auth/userinfo.email"]
credentials = ServiceAccountCredentials.from_json_keyfile_name("CloudEndpointsClient.json", scopes)
from httplib2 import Http
http_auth = credentials.authorize(Http())
from apiclient.discovery import build
api_root = 'https://myapp.appspot.com/_ah/api'
api = 'helloworldendpoints'
version = 'v1'
discovery_url = '%s/discovery/v1/apis/%s/%s/rest' % (api_root, api, version)
service = build(api, version, discoveryServiceUrl=discovery_url)
response = service.myFunction(myparameter = "123456").execute(http=http_auth)#
print response
The requests work well if I remove authentication requirements.
I know that authentication works since the error changes if after authenticating.
The error message I'm getting is:
googleapiclient.errors.HttpError: https://my-app.appspot.com/_ah/api/helloworldendpoints/v1/obtainScoreFromEmail?myparameter=1234&alt=json returned "Access Not Configured. has not been used in project 123456789 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/helloworldendpoints/overview?project=123456789 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.">
I cannot enable the API in my Google Cloud Project, since the API does not exist.
What I found to work is a hack around. I used a user authentication (instead of server) on the same project for the same API which worked (https://cloud.google.com/endpoints/docs/frameworks/python/access_from_python).
After I switched back to my initial server auth. method it started working.
I am trying to authorize my app using google plus. However, everything I've tried always gives me a 404 when I use the people service and attempt to get 'me', except when I log in with the user who created the Google+ API app. It doesn't make any sense to my why that would be the case.
from httplib2 import Http
from apiclient.discovery import build
credential = gp_client.step2_exchange(request.REQUEST)
http = Http()
http = credential.authorize(http)
service = build("plus", "v1", http=http)
o = service.people().get(userId='me').execute()
The same is also true when I use the Google+ explorer:
http://code.google.com/apis/explorer/#_s=plus&_v=v1&_m=people.get&fields=emails
If I switch to private with the user who created the API, then I can fetch 'me', but if I authorize another user, then I can't fetch 'me'.
Any ideas what is happening?
Finally figured out what this was. Google lets you authorize any google account for an app. However, if the authorizing user hasn't upgraded to Google+, when the app makes its first Google+ API request, the request will 404. This is mind boggling, because when I setup the OAuth2WebServerFlow I specified "plus.me" as the scope... IMHO Google should tell the user to upgrade to Google+ when they try to authorize this OAuth request.
gp_client = OAuth2WebServerFlow(
settings.GOOGLE_PLUS_CONSUMER_ID,
settings.GOOGLE_PLUS_CONSUMER_SECRET,
scope='https://www.googleapis.com/auth/plus.me',
)