Skip to content
This repository has been archived by the owner on May 15, 2023. It is now read-only.

Connecting to Office365 SPSite with WindowsLogin/Single SignOn #32

Closed
dgutman opened this issue Nov 29, 2018 · 18 comments
Closed

Connecting to Office365 SPSite with WindowsLogin/Single SignOn #32

dgutman opened this issue Nov 29, 2018 · 18 comments

Comments

@dgutman
Copy link

dgutman commented Nov 29, 2018

I see there is support for Office365 based sharepoint sites-- my site just migrated to this recently... I had previously used SharePlum to authenticate using the below module to pass my windows credentials to the sharepoint site... The current Office365 class requires User/Pass, before I try and hack away at this, I was wondering if anyone has run into this scenario? I think I'd need to modify the Class to make username/password optional and if they are None, try and use the module... but it's a bit confusing as it seems I have to connect to a Microsoft Login server, grab a token, and then use that token for the rest of my "basic" Shareplum requests.... However the Office365 module seems to be posting an XML DOC, which I would also have to figure out how to modify to somehow inject whatever "stuff" that , so I have a feeling it's not going to be particularly simple..

https://github.com/brandond/requests-negotiate-sspi/blob/master/README.md

@fatfingers23
Copy link

Hey dgutman,
I'm the guy who wrote the Office365 part of this. If i understand your question right i think you're asking if a user domain account that is tied to the same Office365 account can be used to authenticate? If that's the case then yes. So if your Office365 users are synced with your activate directory it will work fine(That was my use case). The whole it sending xml to Microsoft was only way i could figure out at the time to get any kind of Authentication to SharePoint online sites as that user. It hits Microsoft servers to Authenticate the Microsoft/Office365 account returns a token that you then hit your Online SharePoint site to use to create a cookie and then that cookie is what finally authenticates you to the SharePoint site. This is the article i used to create this implementation. I hope this helps! If you have any questions let me know. It has been a few months since i've looked at any of this but i will gladly help out if i can.

@dgutman
Copy link
Author

dgutman commented Nov 29, 2018 via email

@fatfingers23
Copy link

Ahh! That makes sense. I did a bit of research on this, i am no longer in a System Admin role with access to admin on a already running Sharepoint site. So i wasn't able to test all of them. Here's a few different solutions you can try. I do not think this is something i personally have time to fully implement into Shareplum at this time though. But! I did find a few things for you to try.

If it is just short term data move or something similar, something to be done in a couple of hours you can still use Shareplum. Will just have to go to your sharepoint site in the browser of your choice and manually grab the cookies. Then add them in share plum example below in Python 3 using http.cookiejar

from shareplum import Site
import http.cookiejar

rtFa = http.cookiejar.Cookie(version=0, name='rtFa', value='rtFaValue', port=None, port_specified=False, domain='abc.sharepoint.com', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False)
FedAuth = http.cookiejar.Cookie(version=0, name='FedAuth', value='FedAuthValue', port=None, port_specified=False, domain='abc.sharepoint.com', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False)
cj = http.cookiejar.LWPCookieJar()
cj.set_cookie(rtFa)
cj.set_cookie(FedAuth)
site = Site('https://abc.sharepoint.com/list/',  authcookie=cj)

Set rtFa value to the rtFa cookie value from the browser and change abc.sharepoint.com to your company share point, do the same with FedAuth. And this should work for about 4 hours i think, give or take. Tedious but will get it done if it is just a server move or something similar. May even set a python script to harvest your local browser cookies and use them, or could set a script to open a browser to that site refresh the cookies of your browser of choice and use them. It's a hack for sure and not a pretty one, but it would work haha.

If not and you have admin access or an admin can give access for you. You can create a authorize app in azure active directory that (more info). I would follow the directions from Vadim Gremyachev in this Stack OverFlow Question it seems like his Python Library can handle that. Example in that library.
Looks promising and way i would go, could not test do not have admin access to a sharepoint site at this time.

Other ones i found made my head spin and i gave up on them, honestly i had looked at doing 0auth first instead of username and password authentication but i settled on it cause it was an easier implementation and for most part did not need any other set up. For most part looks like there may be a way to use the authorize app in azure active directory to get a token from Office 365 api then use that, but i myself have not figured that one out.

Going add a list of different things that may help you if the above do no. Good luck and i hope this helped some!
https://stackoverflow.com/questions/45244998/azure-ad-authentication-python-web-api
https://github.com/AzureAD/azure-activedirectory-library-for-python
https://azure.microsoft.com/en-us/resources/samples/data-lake-analytics-python-auth-options/
https://docs.microsoft.com/en-us/onedrive/developer/rest-api/getting-started/aad-oauth?view=odsp-graph-online

@dgutman
Copy link
Author

dgutman commented Nov 30, 2018

So one of the snags is that my site uses SmartCard based authentication, adding another level of "fun". As an initial hack, I authenticated through chrome and grabbed the rtFA and FedAuth cookies...

myCookies = { "rtFA" : SomeLongCookie", "FedAuth": myOtherLongCookie"}

If i just hardcode my cookies and set self._session.cookes=myCookies I am able to get it to query my main site, using the credentials chrome authenticated through the Microsoft single sign on service.

As a starting point, how could I use authcookie=myCookes so I could use the current API more closely (instead of hacking the code as per below).

I tried just pushing authcookie={rtfa:"key1","FedAuth":"key2"}

    self._session.cookes = myCookies
    # if authcookie is not None:
    #     self._session.cookies = authcookie
    # else:
    #     self._session.auth = auth

If instead, I try this:

site =shareplum.Site("https://blah.sharepoint.com/",authcookie=myCookies, verify_ssl=False)
I get an error that "Dict" has no method to extract_cookies; it looks like requests can accept a dictionary for cookies in its pure state,but since there's a number of additional wrappers/methods between my initiating the Class and actually making the requests, I am guessing something in the middle of this process is expecting a "CookieJar" or something similar instead of a dict...

Tried to pass a DICT to the authcookie

C:\Users\VHAATGGutmaD\AppData\Local\Continuum\Anaconda2\lib\site-packages\requests\sessions.pyc in post(self, url, data, json, **kwargs)
579 """
580
--> 581 return self.request('POST', url, data=data, json=json, **kwargs)
582
583 def put(self, url, data=None, **kwargs):

C:\Users\VHAATGGutmaD\AppData\Local\Continuum\Anaconda2\lib\site-packages\requests\sessions.pyc in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
531 }
532 send_kwargs.update(settings)
--> 533 resp = self.send(prep, **send_kwargs)
534
535 return resp

C:\Users\VHAATGGutmaD\AppData\Local\Continuum\Anaconda2\lib\site-packages\requests\sessions.pyc in send(self, request, **kwargs)
660 extract_cookies_to_jar(self.cookies, resp.request, resp.raw)
661
--> 662 extract_cookies_to_jar(self.cookies, request, r.raw)
663
664 # Redirect resolving generator.

C:\Users\VHAATGGutmaD\AppData\Local\Continuum\Anaconda2\lib\site-packages\requests\cookies.pyc in extract_cookies_to_jar(jar, request, response)
130 # pull out the HTTPMessage with the headers and put it in the mock:
131 res = MockResponse(response._original_response.msg)
--> 132 jar.extract_cookies(res, req)
133
134

AttributeError: 'dict' object has no attribute 'extract_cookies'

@fatfingers23
Copy link

fatfingers23 commented Nov 30, 2018

Yep! I had tried doing a dict as well didn't like that. It is expecting a "CookieJar". If you plug your rtFA and FedAuth values into where it says "rtFaValue" ,"FedAUthValue", and site where it says domain into my code example above using Http.cookiejar Python3 or Cookielib Python 2 into a cookie jar then past it as the authcookie parameter it should work perfectly for you, did for me last night when i tested it. Now for how long it'll keep you authenticated i do not know. Also if you wanted to get real crafty. Let's say you use Google Chrome, you can search the cookie sqlite db for the cookie values to automate it. But it needs to be put into a CookieJar for SharePlum authCookie to accept it.

@dgutman
Copy link
Author

dgutman commented Nov 30, 2018 via email

@fatfingers23
Copy link

Glad i was able to help out! Hope it all works out for you and good luck!

@matt-sharp
Copy link

Not sure if this is a related issue but I'm also trying to connect to a corporate Sharepoint site hosted on Office365 but I get the following error:

SSLError: HTTPSConnectionPool(host='login.microsoftonline.com', port=443): Max retries exceeded with url: /extSTS.srf (Caused by SSLError(SSLError("bad handshake: SysCallError(104, 'ECONNRESET')",),))

@fatfingers23
Copy link

@nekro9t2 Looks to be an error when making the call to Microsoft's servers.
Way Office 365 support works is it makes a call to the Microsoft url with your credentials and SharePoint site and retrieves a token that then is used to authenticate to SharePoint.

I found this and it may help. Looks like it may an issue with your version of request or it's dependencies?

If you like you can post your code with user credenitals and site bleeped out and i can see if i can spot anything.

@matt-sharp
Copy link

Here's the code I'm using:

from shareplum import Site
from shareplum import Office365

authcookie = Office365('https://.sharepoint.com', username='', password='').GetCookies()
site = Site('https://.sharepoint.com/', authcookie=authcookie, verify_ssl=True)

@fatfingers23
Copy link

I don't see anything unusual in what you have. It should work. May try from a different internet connection or i would try this? It looks to be one of SharePlums dependencies not SharePlum itself is causing the issue.

@adithya72
Copy link

Here's the code I'm using:

from shareplum import Site
from shareplum import Office365

authcookie = Office365('https://.sharepoint.com', username='', password='').GetCookies()
site = Site('https://.sharepoint.com/', authcookie=authcookie, verify_ssl=True)

were you able to get this working ? i am having a similar issue. i tired checking PyopenSSL with not much of a luck. If possible can you post the version of the same which is working for you ?

@fatfingers23
Copy link

It’s probably a special character in your password causing the issue. Can try this branch and it should have the patch in it or give you a better error. #52

@wgong
Copy link

wgong commented Feb 9, 2020

@fatfingers23 Thanks for your workaround by getting cookie from browser manually which worked for me. In my case, "expires" value is 5 days (not 4 hrs), so it gives enough time to do something.

Being behind firewall, I also set proxy before calling shareplum:
proxy_str = f"http://{username}:{password}@{proxy_domain}"
os.environ['http_proxy'] = proxy_str
os.environ['HTTP_PROXY'] = proxy_str
os.environ['https_proxy'] = proxy_str
os.environ['HTTPS_PROXY'] = proxy_str

@jimmyknowles
Copy link

jimmyknowles commented May 22, 2020

Regarding the cookiejar approach, why don't you just use browser_cookie3 to grab your rtFa and FedAuth from your browser where you've recently authenticated w/ SharePoint server?

I couldn't get SharePlum to work, but this approach worked for me to build headers and just use the REST API.

I grab the cookies from my browser, build a header dictionary with those two token strings, then just use a regular requests.get call.

@fatfingers23
Copy link

Your way would work perfectly for someone who is using this library on their computer and use Sharepoint regularly. I'm glad you were able to find a solution that worked out for you. The reason I did it this was is cause there two reasons I choose this. The tokens have a 4 or 6 hour lifetime. After that you have to get a new one. Would not be an issue on computer you interact with Sharepoint daily. The second reason is if someone used this library on a server, an example would be with django. You're not going have a web browser on that server you're using to connect to Sharepoint.

A side note Shareplum only uses SOAP endpoints to be able to support 2010 Sharepoint and newer versions. There are lots of new nicer ways to connect to Sharepoint now via the Rest api. Auth tokens would really be the best implementation here so the library never has to see your username and password. This may also be why it does not work for you, the admin may have Soap endpoints turned off.

If you did wanted to post your exception you had with Shareplum I don't mind one bit looking at it and seeing If I have a solution. That is if you wanted to use the library. I wrote this feature a long time ago (in dev time) when I first started my journey writing code. This was actually my first ever merged PR. It's not the prettiest and I'm sure there are some bugs.

@jimmyknowles
Copy link

Thanks for the explanation Bailey. This was mainly for @dgutman since it seemed easier than manually pulling rtFa and FedAUth from your browser cookies. I wasn't trying to suggest that this would be a viable long term solution, but just a way to make a workaround even easier.

My org also uses SSO and I couldn't get any authentication method to work. requests-negotiate-sspi works on our on-premises instance of SP, but it wouldn't work on our O365 MS-hosted instance. I'll take some time next week to rerun the lines that was causing errors w/ SharePlum and post. I'd like to use SharePlum, but due to authentication issues, REST API might be an easier route.

Thanks again.

@fatfingers23
Copy link

No need for the exception then! I think I know a solution. Just wanted to make sure you were able to access it and did not need any help.

I have not worked/read through this library in a while. I believe they have added the Rest API. With that the office 365 authentication can be beefed up to modern standards and better adaption to SSO for office 365 use. I do not believe I will implementing that to this library, unless it was a sought out feature and a lot of people needed it. Too many irons and too many fires.

But I will live some reference articles on it if anyone did see this and wanted to make a pr. I do believe for Auth tokens to work you need to register the application via Active Directory.
Sharepoint Rest Via Microsoft graph
https://docs.microsoft.com/en-us/graph/api/resources/sharepoint?view=graph-rest-1.0
Authentication With Auth Tokens

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants