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

Using certificate as client credentials without specifying the certificate path #495

Closed
vietluu-collab opened this issue Apr 1, 2022 · 8 comments

Comments

@vietluu-collab
Copy link

Hello everyone. I am making trying to move my data flow to cloud and I am trying to grant access using the below link.
https://youtu.be/kpDs4Xgb_z8

From 2:02, the speaker in the video said that client secret is not supported for sharepoint api. That means I need to log in using certificate. However, when connecting with certificate, according to what I've read, local path to where to certificate is installed is required. But I want to build a logic app with all components "on the cloud" meaning nothing will be installed.on the local machine. My question is that is there a.way to connect without using the path of certificate. I am thinking of using the pfx value but I donnot know the code. Can you guys show me the code?

@vietluu-collab
Copy link
Author

@vgrem can you please answer this question for me?

@vgrem
Copy link
Owner

vgrem commented Apr 2, 2022

Hey @vietluu-collab,

Regarding

My question is that is there a.way to connect without using the path of certificate. I am thinking of using the pfx value but I donnot know the code. Can you guys show me the code?

at the moment ClientContext.with_client_certificate only accepts cert_path which represents a path to A PEM encoded certificate private key . Although I tend to agree, supporting another options, for instance passing it as a file object, might be beneficial.

Anyway, the following approach (workaround) could be considered atm:

  • convert pfx encoded certificate file to pem, for instance via OpenSSL: openssl pkcs12 -in certificate.pfx -out certificate.pem
  • construct your own acquire token callback for client certificate flow (as demonsterated below)

Here is a minimal example:

from office365.runtime.auth.token_response import TokenResponse
from office365.sharepoint.client_context import ClientContext


cert_pem_content = """-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
"""


def acquire_token():
    cert_settings = {
        'tenant': "consoto.onmicrosoft.com",
        'client_id': '51d03106-4726-442c-86db-70b32fa7547f',
        'thumbprint': "78CA7402E8A2508A9772CB1B2E085945147D8050",
        'resource': 'https://contoso.sharepoint.com',
        'private_key': cert_pem_content
    }

    authority_url = 'https://login.microsoftonline.com/{0}'.format(cert_settings.get('tenant'))
    credentials = {
        "thumbprint": cert_settings.get('thumbprint'),
        "private_key": cert_pem_content
    }
    scopes = ["{url}/.default".format(url=cert_settings.get('resource'))]
    import msal
    app = msal.ConfidentialClientApplication(
        cert_settings.get('client_id'),
        authority=authority_url,
        client_credential=credentials,
    )
    result = app.acquire_token_for_client(scopes)
    return TokenResponse.from_json(result)


site_url = "https://consotoso.sharepoint.com/sites/team"
ctx = ClientContext(site_url).with_access_token(acquire_token)
current_web = ctx.web.get().execute_query()
print("{0}".format(current_web.url))

@vietluu-collab
Copy link
Author

@vgrem thank you very much. I will try.this

@yipsmith
Copy link

@vietluu-collab Did you ever get this working? I need to do something similar.

my certificate also has a passphrase. Any ideas how to incorporate that as well? @vgrem

@ShaulAb
Copy link

ShaulAb commented Jul 7, 2022

@bep-droid this solution worked for me.
You can add passphrase to the credentials dictionary, for example:

 credentials = {
      "thumbprint": cert_settings.get('thumbprint'),
      "private_key": cert_pem_content,
      "passphrase": "mypassphrase",
  }

Thanks @vgrem for your example, much appreciated.

@niltecedu
Copy link

@vgrem any plans to implement this into main branch?

@vgrem
Copy link
Owner

vgrem commented Feb 22, 2023

Hey @niltecedu,

since 2.3.15 version version it is supported to pass private_key as a string:

cert_path = 'selfsigncert.pem'
with open(cert_path, 'r') as f:
      private_key = open(cert_path).read()

cert_credentials = {
     'tenant': test_tenant,
     'client_id': '--client id--',
     'thumbprint': '--thumbprint--',
     'private_key': private_key
}
ctx = ClientContext(test_team_site_url)

Similar thread #568

@niltecedu
Copy link

niltecedu commented Feb 22, 2023 via email

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

No branches or pull requests

5 participants