Open remjg opened 7 years ago
If you're using OC >= 9.1, login as the user in question then go to the personal page and generate an application token (aka device token). Then use the username as user id and that token as password.
I don't think there is any other way.
The server is running ownCloud 9.0.2 unfortunately, too bad...
Thank you for your prompt answer!
I found that my school uses Central Authentication Service (CAS) as a single sign-on service. Thanks to this very well done article, I managed to log in.
1) First, I have to get the hidden form fields needed to log in (CSRF token).
import requests
import lxml.html
import owncloud
SSO = 'https://ent.clg-marigny.ac-reims.fr:8443/login?service=https%3A%2F%2Fent.clg-marigny.ac-reims.fr%2Fowncloud%2F%3Fapp%3Denvole_cas%26redirect%3D%2Fowncloud%2Findex.php'
s = requests.session()
login = s.get(SSO)
login_html = lxml.html.fromstring(login.text)
hidden_inputs = login_html.xpath(r'//form//input[@type="hidden"]')
form = {x.attrib["name"]: x.attrib["value"] for x in hidden_inputs}
Here is the result:
>>> print(form)
{'lt': 'LT-ent.clg-marigny.ac-reims.fr-761c32d0612e5f23bd95daeb44bf31fc95a6310f147fc84a8cfad650', 'service': 'https://ent.clg-marigny.ac-reims.fr/owncloud/?app=envole_cas&redirect=/owncloud/index.php', 'previous_user': ''}
2) Then, I have to fill out the form with my username and password.
form['username'] = 'MyUsername'
form['password'] = 'MyPassword'
response = s.post(SSO, data=form)
Authentication seems to work since I'm redirected to the correct url:
>>> print(response.url)
https://ent.clg-marigny.ac-reims.fr/owncloud/index.php/apps/files/
3) Now I'm trying to mimic how the Client.login method works while manually overwriting the oc._session
attribute.
oc = owncloud.Client('https://ent.clg-marigny.ac-reims.fr/owncloud/')
oc._session = s
oc._session.verify = oc._verify_certs
oc._session.auth = (MyLogin, MyPassword) # necessary again?
oc._update_capabilities()
But of course, trying any command like oc.mkdir('testdir')
doesn't work (HTTP error: 401
). I'm not surprised since I'm not understanding half of what I'm doing...
Do you have any idea or suggestions regarding what I'm trying to achieve ?
Finally, I managed to get access to my ownCloud storage using pyocclient!
3) Same step as in previous post, I overwrited oc._session
attribute with the one I got in step 1) and I ran the method `_update_capabilities()'.
oc = owncloud.Client('https://ent.clg-marigny.ac-reims.fr/owncloud/')
oc._session = s
oc._update_capabilities()
4) Then, I created a new Session object like in the Client.login()
method but without running `_update_capabilities()'.
oc._session = requests.session()
oc._session.verify = oc._verify_certs
oc._session.auth = ('MyUsername', 'MyPassword')
5) And the following commands now work:
#oc._update_capabilities() won't run here and before
oc.mkdir('testdir')
#oc._update_capabilities() works again here and after
oc.put_file('testdir/file','file')
oc.share_file_with_user('testdir/', 'aLocalUser')
Yesterday, I discovered that I could configure ownCloud sync client without encountering any issue. Hence I thought that overwritingoc_session
wasn't perhaps necessary after "initializing"... As you can see, I still don't understand what I'm doing but I'm lucky enough to have some code that seems to work.
I'll be very happy if you can give me some clue about what happened here !
Maybe should I close the bug since it is not related directly to pyocclient ?
After a bit of polishing, I now use a home made method called Client.login_cas()
in place of Client.login()
to create a session on the server:
import lxml.html
def login_cas(self, user_id, password):
"""Authenticate to ownCloud behind CAS (Central Authentication Service).
This will create a session on the server.
:param user_id: user id
:param password: password
:raises: HTTPResponseError in case an HTTP error status was returned
"""
# Get the hidden form fields needed to log in (CSRF token)
self._session = requests.session()
cas_url = self._session.get(self.url).url # follow redirection
login = self._session.get(cas_url)
login_html = lxml.html.fromstring(login.text)
hidden_inputs = login_html.xpath(r'//form//input[@type="hidden"]')
form = {x.attrib["name"]: x.attrib["value"] for x in hidden_inputs}
# Fill out the form with username and password, then connect
form['username'] = user_id
form['password'] = password
response = self._session.post(cas_url, data=form)
try:
self._update_capabilities()
except HTTPResponseError as e:
self._session.close()
self._session = None
raise e
self._session = requests.session()
self._session.verify = self._verify_certs
self._session.auth = (user_id, password)
I seem to be able to perform the basic operation I need but I won't try the unit tests since this is the server of my school. Maybe this will be useful to someone !
This sounds like a great achievement, however it doesn't feel right to have to hack around HTML pages to make it work. Ideally a proper API endpoint should be added in the server to allow such authentication in a clean way.
(...) it doesn't feel right to have to hack around HTML pages to make it work.
I agree with you.
Ideally a proper API endpoint should be added in the server to allow such authentication in a clean way.
Didn't know what an API endpoint
was before reading your comment (and it is still the case I think). After a quick research, I found a page that seems to describe what you are talking about. But it is beyond my knowledge and I will stop here.
Anyway, thank you for you work on pyocclient
, it fits my needs!
Hi,
I would like to access to the following ownCloud server: https://ent.clg-marigny.ac-reims.fr/owncloud/
Unfortunately, I'm redirected to the following page for logging in: https://ent.clg-marigny.ac-reims.fr:8443/login?service=https%3A%2F%2Fent.clg-marigny.ac-reims.fr%2Fowncloud%2F%3Fapp%3Denvole_cas%26redirect%3D%2Fowncloud%2Findex.php
Hence, I can't seem to be able to use pyocclient to access this ownCloud server since it uses a single sign-on method for logging in.
Is it possible to use pyocclient with an ownCloud server in case the server uses a different authentication method?