JonathanHolvey / sharepy

Simple SharePoint authentication for Python
GNU General Public License v3.0
175 stars 52 forks source link

Support for custom extSTS.srf-url #9

Closed Gitii closed 3 years ago

Gitii commented 6 years ago

Hi,

the german office 365 has a differenct endpoint: The extSTS.srf must be downloaded from https://login.microsoftonline.de/extSTS.srf instead of https://login.microsoftonline.com/extSTS.srf

I would like to override (e.g. in connect()) the standard url to support this use case instead of monkey patching the source.

Thanks

JonathanHolvey commented 6 years ago

Thanks for that, I didn't know.

How about I add a parameter for TLD, which could be set to "de" in your case. This will prevent you having to remember and type the whole URL when using SharePy from the interactive shell.

Gitii commented 6 years ago

This would be great. Thanks for your reply and effort!

JonathanHolvey commented 6 years ago

Try branch auth-domain and see how you get on. I can't test it as I don't currently have access to a SharePoint site. auth_tld is optional and defaults to "com".

Usage will be sharepy.connect("example.sharepoint.com", auth_tld="de").

Gitii commented 6 years ago

The new parameter is not passed to the constructor. Beside that: It works!

JonathanHolvey commented 6 years ago

Great, thanks. I've fixed that up now. Once I've got a test site sorted out I'll push out a new release.

JonathanHolvey commented 6 years ago

I'm working on adding a new authentication method to SharePy, and part of this is auto-detecting the authentication URL. I think this might be a more elegant solution to your issue.

Please try out the auth-classes branch and let me know if it works for you.

The usage will be back to sharepy.connect("example.sharepoint.com")

Gitii commented 6 years ago

I checked the branch but sadly, it does not work as expected: https://login.microsoftonline.com/GetUserRealm.srf?login={}&xml=1 only returns <RealmInfo Success="true"><State>4</State><UserState>1</UserState><Login>[removed mail adress]</Login><NameSpaceType>Unknown</NameSpaceType></RealmInfo> If I change the tld to "de", the response is much more detailed and also contains the fields you are looking for. That is a chicken-and-egg problem.

Thanks for your effort!

JonathanHolvey commented 6 years ago

That's a shame.

Given that there are only four different login domains (Production, Germany, China and US Government) I might just try each one in turn when using sharepy.connect(). You will still be able to supply a custom domain by supplying an auth object to sharepy.SharePointSession:

auth = sharepy.auth.SharePointOnline(username="user@example.com",
                                     auth_domain="login.microsoftonline.de")
s = sharepy.SharePointSession("example.sharepoint.com", auth=auth)

Let me know if you have any ideas.

https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/extending-sharepoint-online-for-germany-china-usgovernment-environments

Gitii commented 6 years ago

You could:

I do not like the idea that sharepy 'randomly' tries all possible auth domains. The user should know, which one is the right one.

JonathanHolvey commented 6 years ago

My thinking was that the connect function should provide a path of least resistance to get connected. I imagine most users won't even know there are multiple environments with different login domains. I certainly didn't.

I understand your concern over trying randomly until it works, but there are only four options. Also, I wouldn't expect the username TLD to match the login TLD, especially for the China and US Government environments.

Do you think it would be better to raise exceptions rather than printing status messages? I've certainly never been completely satisfied with the current method of feedback, but it is useful when using SharePy interactively.

Gitii commented 6 years ago

You have created a fantastic package which is simple and does it job. But to be honest, my first impression was an 'has no attribute'-error. The authorization failed and some "random" instructions crashed the whole process. We have to blame microsoft for the design of this auth process. But sharepy lacks proper error handling, too.

Nevertheless, I am very pleased with your library (I could connect to sharepoint in less than 5 minutes) and your effort to fix and improve it. You designed sharepy with certain goals in mind. I think some aspects can be tweaked to make sharepy even better:

Regarding the auth domain: I expect users of this library to know what "kind" of sharepoint they are connecting to. This applies vice versa: I expect sharepy to connect to the appropriate endpoint (which is login.microsoftonline.de in my case) and not to login.chinacloudapi.cn. Even scarier: These requests include the mail adress and password. I know that login.microsoftonline.de is trustworthy because it is designed to be and we are paying good money for it. The others? I do not know. The easiest way is to use the same approach which Microsoft implemented:

public enum AzureEnvironment
{
    Production=0,
    PPE=1,
    China=2,
    Germany=3,
    USGovernment=4
}
...
ClientContext cc = new AuthenticationManager().GetAzureADAppOnlyAuthenticatedContext(..., 
            .., "....", ..., ...., AzureEnvironment.Germany);
JonathanHolvey commented 6 years ago

Thanks for this feedback! It's really useful to hear what people who use SharePy think of it, and how it could be improved. I'll try to integrate your suggestions as I make changes moving toward a version 2 release sometime soon. They make a lot of sense to me.

When you talk about version handling for the cookie, do you mean the Microsoft authentication cookie, or the serialised SharePointSession file that's produced by the save()method? I don't think the cookie should be affected by the version of SharePy, but the sp-session.pkl file definitely will be.

You're certainly right about the perceived trust issue with submitting the username to a random list of servers (the password wouldn't be sent, but that's not necessarily obvious to the user). Maybe users can provide a full login domain if they know it, or use a shortcut such as Germany, which can be used look up the correct value from a dictionary.

Cheers, Jon

Gitii commented 6 years ago

I am looking forward to your next version :+1: And I mean the serialized pickle file, sorry for the confusion.