I have installed couchDB v 0.10.0, and am attempting to talk to it via python from Couch class downloaded from couchDB wiki. Problem is:
Create database 'mydb': {'error': 'unauthorized', 'reason': 'You are not a server admin.'}
I hand edited the local.ini file to include my standard osx login and password. I now have full access via futon but no joy WRT python. Is this an http header issue?
At a a loss - thanks!
To concour David's reply, (i.e. "This is how I do it using module CouchDB 0.8 in python 2.6 with couchdb 1.0.2")
couch = couchdb.Server(couch_server)
couch.resource.credentials = (USERNAME, PASSWORD)
You can also do:
db = couchdb.Database("http://your.url/yourdb")
db.resource.http.add_credentials(username, password)
after which all your requests should work.
The Couch class in the example does not pass any authentication information to the database, so it is not a miracle that it does not allow privileged operations. So your only options are:
disable authentication completely (as you mentioned)
pass the user name and password as part of the URI
pass the user name and password as an Authorization HTTP request header
If you want to pass a user name and a password, then you will need to change the Couch class. Sending an Authorization HTTP request header is easier, since the Couch class uses the httplib.HTTPConnection class. You can add such a header next to the Accept one this way:
headers = {
"Accept": "application/json",
"Authorization": "Basic " + 'username:password'.encode('base64')[:-1]}
Same for the other HTTP request methods.
The documentation on the basic authentication is here:
http://books.couchdb.org/relax/reference/security
Just pass it as part of the URI...python-couchdb will parse the user/pass out and use them:
http://user:pass#localhost:5984
Above are all nice; but I've found that for oauth validation methods versus basic auth, this works really well:
from couchdb import Server, Session
auth = Session()
auth.name = USERNAME
auth.password = PASSWORD
s = Server('http://localhost:5984/', session=auth)
db = s['dbname']
Note: This will not work with basic authentication; in such a case, fviktor has what I consider to be the best answer. You might also look into the security reference material he linked to if you're interested in persistent auth sessions.
There are several patches for python-couchdb that enable authentication. The code probably will be included in Version 0.7 but until then you can usr teh fork at http://github.com/mdornseif/couchdb-python - it allows you to use http://user:pass#127.0.0.1:5984/ type URLs.
http://blogs.23.nu/c0re/2009/12/running-a-couchdb-cluster-on-amazon-ec2/ (at the bottom) shows how to use CouchDB passwords.
Related
I have an XML/WCF API I need to implement something against. The API client library is only provided as c# in Windows and our company does not do either c# or Windows. I am now experimenting with Python and zeep. The api is Symmetry access control system API if anyone is interested.
I can connect to the server and read the wsdl structure. This works:
URL='https://localhost/smsXMLWebService/SMSXMLWebService.svc?singleWsdl'
URL2='https://localhost/smsXMLWebService/smsXMLWebService.svc'
session = Session()
session.verify = False
transport = Transport(session=session)
self.client = zeep.Client(URL, transport=transport)
self.service = self.client.create_service('{http://tempuri.org/}WSHttpBinding_ISMSXMLWebService', URL2)
Now everything from that point forward will require login to the platform. In the example c# code this is done as follows:
G4TAPI = new SMSXMLWebServiceClient();
G4TAPI.ClientCredentials.UserName.UserName = txtUserName.Text
G4TAPI.ClientCredentials.UserName.Password = txtPassword.Text.ToLower();
G4TAPI.G4TLogin();
My self.service has now G4TLogin() call and it seems to attempt to connect when I wireshark the traffic. But how do I set the username and password as they are not given as parameters to G4TLogin() method?
This does not work:
self.service.ClientCredentials.UserName.UserName = "api"
This is very much out of my comfort zone and I may be using incorrect terminology here. Any ideas?
The error message is
AttributeError: Service has no operation 'ClientCredentials'
When using Zeep make sure to study the namespaces in WSDL URL, using
python -mzeep "YourWsdlUrlGoesHere"
Get the parameters and make a Python dictionary from them (in my case facing C#, including username and password in the dictionary) note that one might need to make nested dictionary like in my case.
from requests import Session
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
from zeep import Client
from zeep.transports import Transport
request = { "Credential":{"Username": "yourusername",
"Password": "yourpassword"},
"RN": "150147119"
}
session = Session()
client = Client('http://your url and wsdl../Invoice.svc?Wsdl',transport=Transport(session=session))
r = client.service.NameOfYourService(request)
print(r)
Do not pass user and password in Zeep formal format. Passing the dictionary worked for me.
In my case the WSDL suggested user and password be in credential and a string be passed in RN and finally all be passed in a one variable.
I'm trying to get this example to work from https://github.com/ozgur/python-linkedin. I'm using his example. When I run this code. I don't get the RETURN_URL and authorization_code talked about in the example. I'm not sure why, I think it is because I'm not setting up the HTTP API example correctly. I can't find http_api.py, and when I visit http://localhost:8080, I get a "this site can't be reached".
from linkedin import linkedin
API_KEY = 'wFNJekVpDCJtRPFX812pQsJee-gt0zO4X5XmG6wcfSOSlLocxodAXNMbl0_hw3Vl'
API_SECRET = 'daJDa6_8UcnGMw1yuq9TjoO_PMKukXMo8vEMo7Qv5J-G3SPgrAV0FqFCd0TNjQyG'
RETURN_URL = 'http://localhost:8000'
authentication = linkedin.LinkedInAuthentication(API_KEY, API_SECRET, RETURN_URL, linkedin.PERMISSIONS.enums.values())
# Optionally one can send custom "state" value that will be returned from OAuth server
# It can be used to track your user state or something else (it's up to you)
# Be aware that this value is sent to OAuth server AS IS - make sure to encode or hash it
#authorization.state = 'your_encoded_message'
print authentication.authorization_url # open this url on your browser
application = linkedin.LinkedInApplication(authentication)
http_api.py is one of the examples provided in the package. This is an HTTP server that will handle the response from LinkedIn's OAuth end point, so you'll need to boot it up for the example to work.
As stated in the guide, you'll need to execute that example file to get the server working. Note you'll also need to supply the following environment variables: LINKEDIN_API_KEY and LINKEDIN_API_SECRET.
You can run the example file by downloading the repo and calling LINKEDIN_API_KEY=yourkey LINKEDIN_API_SECRET=yoursecret python examples/http_api.py. Note you'll need Python 3.4 for it to work.
I created 2 applications in my Azure directory, 1 for my API Server and one for my API client. I am using the Python ADAL Library and can successfully obtain a token using the following code:
tenant_id = "abc123-abc123-abc123"
context = adal.AuthenticationContext('https://login.microsoftonline.com/' + tenant_id)
token = context.acquire_token_with_username_password(
'https://myapiserver.azurewebsites.net/',
'myuser',
'mypassword',
'my_apiclient_client_id'
)
I then try to send a request to my API app using the following method but keep getting 'unauthorized':
at = token['accessToken']
id_token = "Bearer {0}".format(at)
response = requests.get('https://myapiserver.azurewebsites.net/', headers={"Authorization": id_token})
I am able to successfully login using myuser/mypass from the loginurl. I have also given the client app access to the server app in Azure AD.
Although the question was posted a long time ago, I'll try to provide an answer. I stumbled across the question because we had the exact same problem here. We could successfully obtain a token with the adal library but then we were not able to access the resource I obtained the token for.
To make things worse, we sat up a simple console app in .Net, used the exact same parameters, and it was working. We could also copy the token obtained through the .Net app and use it in our Python request and it worked (this one is kind of obvious, but made us confident that the problem was not related to how I assemble the request).
The source of the problem was in the end in the oauth2_client of the adal python package. When I compared the actual HTTP requests sent by the .Net and the python app, a subtle difference was that the python app sent a POST request explicitly asking for api-version=1.0.
POST https://login.microsoftonline.com/common//oauth2/token?api-version=1.0
Once I changed the following line in oauth2_client.py in the adal library, I could access my resource.
Changed
return urlparse('{}?{}'.format(self._token_endpoint, urlencode(parameters)))
in the method _create_token_url, to
return urlparse(self._token_endpoint)
We are working on a pull request to patch the library in github.
For the current release of Azure Python SDK, it support authentication with a service principal. It does not support authentication using an ADAL library yet. Maybe it will in future releases.
See https://azure-sdk-for-python.readthedocs.io/en/latest/resourcemanagement.html#authentication for details.
See also Azure Active Directory Authentication Libraries for the platforms ADAL is available on.
#Derek,
Could you set your Issue URL on Azure Portal? If I set the wrong Issue URL, I could get the same error with you. It seems that your code is right.
Base on my experience, you need add your application into Azure AD and get a client ID.(I am sure you have done this.) And then you can get the tenant ID and input into Issue URL textbox on Azure portal.
NOTE:
On old portal(manage.windowsazure.com),in the bottom command bar, click View Endpoints, and then copy the Federation Metadata Document URL and download that document or navigate to it in a browser.
Within the root EntityDescriptor element, there should be an entityID attribute of the form https://sts.windows.net/ followed by a GUID specific to your tenant (called a "tenant ID"). Copy this value - it will serve as your Issuer URL. You will configure your application to use this later.
My demo is as following:
import adal
import requests
TenantURL='https://login.microsoftonline.com/*******'
context = adal.AuthenticationContext(TenantURL)
RESOURCE = 'http://wi****.azurewebsites.net'
ClientID='****'
ClientSect='7****'
token_response = context.acquire_token_with_client_credentials(
RESOURCE,
ClientID,
ClientSect
)
access_token = token_response.get('accessToken')
print(access_token)
id_token = "Bearer {0}".format(access_token)
response = requests.get(RESOURCE, headers={"Authorization": id_token})
print(response)
Please try to modified it. Any updates, please let me know.
I am trying to implement token based authentication for my Flask REST API. I am using Stormpath as my third-party authentication service.
I looked into flask-stormpath built on top of flask-login. Looks like it uses password based authentication as they are trying to maintain session on the server. Also, the documentation doesn't provide me enough information.
Do we have a flask integration for stormpath token based authentication ?
If yes, can someone point me to a sample code.
I have already gone through the stormpath/flask-stormpath-sample on github, which again maintains sessions in server.
References:
https://stormpath.com,
https://github.com/stormpath/stormpath-flask
So here is the way I am currently using until rdegges shall build this feature into flask-stormpath.
You will need stormpath python sdk latest version and wraps from func tools.
from stormpath.api_auth import (PasswordGrantAuthenticator, RefreshGrantAuthenticator, JwtAuthenticator)
from functools import wraps
You can create your application as such.
stormpathClient = Client(id=KEYS['STORMPATH_ID'], secret=KEYS['STORMPATH_SECRET'])
stormpathApp = stormpathClient.applications.search('your-application')[0]
This decorator shall help you with securing endpoints.
def tokenRequired(func):
"""
Decorator to apply on all routes which require tokens.
"""
#wraps(func)
def wrappingFunc():
#check the auth header of the request for a bearer token.
authHeader = request.headers.get('Authentication')
#make sure that the string is a bearer type.
if len(authHeader)<8 or (not authHeader[:7] == 'Bearer ') or (
not authHeader):
return Response("401 Unauthorized",401)
authToken = authHeader[7:]
try:
authenticator = JwtAuthenticator(stormpathApp)
authResult = authenticator.authenticate(authToken)
request.vUser = authResult.account
except:
return Response("403 Forbidden",403)
return func()
return wrappingFunc
#Use this decorator like below.
#flaskApp.route('/secure-route',methods=['GET','POST'])
#tokenRequired
def secureEndpoint():
# return JSON based response
return Response("This is secure Mr." + request.vUser.given_name ,200)
Let me know in the comments if someone wishes to know the token issuing and refreshing end points as well.
I'm the author of the Flask-Stormpath library. The answer is no. I'm actually working on a new release of the library (coming out in a month or so) that will provide this functionality by default, but right now it only supports session based authentication.
Is there a Salesforce endpoint to logout a session (not involving oauth?).
For example, I have a python script that logged in via the REST API using the username, password, security token method (I am using simple_salesforce for this).
simple_salesforce does not provide an inbuilt way to logout. Instead, according to the developer, logging out should be our responsibility:
https://github.com/heroku/simple-salesforce/issues/35
In the url above, it recommends we hit the salesforce revoke endpoint as described here:
https://help.salesforce.com/HTViewHelpDoc?id=remoteaccess_revoke_token.htm&language=en_US
However, as I mentioned before, I used the username, password, security token method to login, not the oauth.
Assuming, I cannot use the oauth way to login, what url/endpoint do I need to hit to logout the session?
Thanks!
Answering my own question. Perhaps this may be helpful to anyone else.
When using the username, password, security-token method instead of oauth to login, you still use the oauth revoke endpoint to logout. As shown in Salesforce documentation (https://help.salesforce.com/apex/HTViewHelpDoc?id=remoteaccess_revoke_token.htm&language=en), the revoke endpoint has the following url: https://login.salesforce.com/services/oauth2/revoke?token=currenttokenID
The token we will hit the endpoint with is actually our session_id. So, in simple_salesforce, once we have created the sf object as follows
sf = Salesforce(username='myemail#example.com', password='password', security_token='token')
we get the session id by sf.session_id.
Now to hit the endpoint we can use requests (which is already there in the sf object)
payload = { "token": sf.session_id }
url = 'https://test.salesforce.com/services/oauth2/revoke'
r = sf.request.get(url, params=payload)
if r.status_code == 200:
#successfully logged out, good to go!
else:
#uh-oh, something went wrong. check it out
Hope this helps!