Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connecting to SharePoint site other than the root with certificate fails #541

Closed
denicomp opened this issue Jul 25, 2022 · 4 comments
Closed
Labels

Comments

@denicomp
Copy link

I am trying to use certificate authentication.

If I connect to the root of my SharePoint, it works. But if I try to connect to any specific site, it gets an error. But both work through PowerShell.

Example - this is PowerShell using the cert in a .pfx file, connecting to the root (https://mytenant.sharepoint.com)

Connect-PnPOnline -Url https://mytenant.sharepoint.com -Tenant mytenant.onmicrosoft.com -ClientId 5fa2148c-d484-444a-bcf1-db632a0fed71 -CertificatePath 'PowershellPnp.pfx' -CertificatePassword $(ConvertTo-Securestring -string "MyCertPassword" -AsPlainText -Force)

Now I change it to connect to https://mytenant.sharepoint.com/sites/MySite

Connect-PnPOnline -Url https://mytenant.sharepoint.com/sites/MySite -Tenant mytenant.onmicrosoft.com -ClientId 5fa2148c-d484-444a-bcf1-db632a0fed71 -CertificatePath 'PowershellPnp.pfx' -CertificatePassword $(ConvertTo-Securestring -string "MyCertPassword" -AsPlainText -Force)

Still works.

Now I try to do the same thing through Python. First the root https://mytenant.sharepoint.com

        site_url = "https://mytenant.sharepoint.com"
	cert_settings = {
		'client_id': '5fa2148c-d484-444a-bcf1-db632a0fed71',
		'thumbprint': "D1656C4AAC5CFBB971477230A5FBACCD356829D3",
		'cert_path': 'PowershellPnP.pem'
	}
	ctx = ClientContext(site_url).with_client_certificate('mytenant.onmicrosoft.com',**cert_settings)

This connects without error.

However, if I change the site to https://mytenant.sharepoint.com/MySite:

        site_url = "**https://mytenant.sharepoint.com/sites/MySite**"
	cert_settings = {
		'client_id': '5fa2148c-d484-444a-bcf1-db632a0fed71',
		'thumbprint': "D1656C4AAC5CFBB971477230A5FBACCD356829D3",
		'cert_path': 'PowershellPnP.pem'
	}
	ctx = ClientContext(site_url).with_client_certificate('mytenant.onmicrosoft.com',**cert_settings)

I get this error:

ValueError: {'error': 'invalid_resource', 'error_description': 'AADSTS500011: The resource principal named https://mytenant.sharepoint.com/sites/MySite was not found in the tenant named mytenant. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant

I might consider what that error says, but I can connect to that site using the certificate method through PowerShell. So there should be no problem or other requirements to connect to it through Python, no?

@vgrem vgrem added the bug label Jul 26, 2022
@denicomp
Copy link
Author

The problem is in the __init__ for the ClientContext class.

It needs to pass only the first part of the base_url (the "root") to AuthenticationContext. It is passing the entire url that it is passed.

So, for example, if I pass https://mytenant.sharepoint.com/sites/MySite, it passes that to AuthenticationContext and that fails. It needs to pass only https://mytenant.sharepoint.com.

I fixed this by modifying client_context.py:

  • add at the top

from urllib.parse import urlparse

  • in __init__ replace this code:
        if auth_context is None:
            self._auth_context = AuthenticationContext(authority_url=base_url)
        else:
            self._auth_context = auth_context

with this code:

        if auth_context is None:
            parsed_uri = urlparse(base_url)
            tenant_url = '{uri.scheme}://{uri.netloc}'.format(uri=parsed_uri)
            self._auth_context = AuthenticationContext(authority_url=tenant_url)
        else:
            self._auth_context = auth_context

@vgrem
Copy link
Owner

vgrem commented Jul 27, 2022

Greetings,

thank you for catching this bug!
Indeed in version 2.3.13, when non root site is provided the authentication flow fails with the error:

'AADSTS500011: The resource principal named https://{tenant}.sharepoint.com/sites/{site) was not found in the tenant named {tenant}

since scopes parameter is not properly determined. The fix will be included in the next release: 2.3.14

Meanwhile you could consider the following workaround: explicitly specify scopes parameter, for example:

cert_settings = {
    'client_id': '--your app client id goes here--',
    'thumbprint': "--thumbprint of certificate goes here--",
    'cert_path': '--path to a PEM encoded certificate private key--',
    'scopes': ['https://{tenant}.sharepoint.com/.default']
}

ctx = ClientContext(test_team_site_url).with_client_certificate(''{tenant}.onmicrosoft.com'', **cert_settings)
current_web = ctx.web.get().execute_query()
print("{0}".format(current_web.url))

vgrem added a commit that referenced this issue Jul 27, 2022
@vgrem
Copy link
Owner

vgrem commented Sep 7, 2022

A new version has been released: 2.3.14 which contains a fix for this issue.

@vgrem vgrem closed this as completed Sep 7, 2022
@JusticeGitHub
Copy link

@denicomp Could you tell me how can you generate the PowershellPnP.pem file?

I tried to use the .cer file by: openssl x509 -in cert.cer -out cert.pem

The cer comes from .\Create-SelfSignedCertificate.ps1 in https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread

Then I got error "Could not deserialize key data. The data may be in an incorrect format or it may be encrypted with an unsupported algorithm".

Could you tell me if there is any difference between yours and mine?
Thank you very much!

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

No branches or pull requests

3 participants