Git Product home page Git Product logo

python-sample-console-app's Introduction

Python console application for Microsoft Graph

language:Python license:MIT

This sample uses Microsoft Graph to read your user profile, download your profile photo, upload the photo to OneDrive, create a sharing link, and send an email on your behalf (to yourself by default).

Authentication is handled via device flow authentication, the recommended approach for console applications. If you're looking for examples of how to work with Microsoft Graph from Python web applications, see Python authentication samples for Microsoft Graph. For a web app sample that does the same things as this console app sample, see Sending mail via Microsoft Graph from Python.

Installation

Verify that you have the following prerequisites in place before installing the sample:

  • Install Python from https://www.python.org/. You'll need Python 3.6 or later, primarily because of the use of f-strings &mdash change those to format strings if you need to use an earlier Python 3.x version. If your code base is running under Python 2.7, you may find it helpful to use the 3to2 tools to port the code to Python 2.7.
  • The sample can be run on any operating system that supports Python 3.x, including recent versions of Windows, Linux, and Mac OS. In some cases, you may need to use a different command to launch Python — for example, some Linux distros reserve the command python for Python 2.7, so you need to use python3 to launch an installed Python 3.x version.
  • This sample requires an Office 365 for business account.
  • To register your application in the Azure Portal, you will need an Azure account associated with your Office 365 account. No charges will be incurred for registering your application in the Azure Portal, but you must have an account. If you don't have one, you can sign up for an Azure Free Account.

Follow these steps to install the sample code on your computer:

  1. Clone the repo with this command:

    • git clone https://github.com/microsoftgraph/python-sample-console-app.git
  2. Create and activate a virtual environment (optional). If you're new to Python virtual environments, Miniconda is a great place to start.

  3. In the root folder of your cloned repo, install the dependencies for the sample as listed in the requirements.txt file with this command: pip install -r requirements.txt.

Application Registration

To run the sample, you will need to register an application and add the registered application's ID to the configuration information in the config.py file. Follow these steps to register and configure your application:

  1. Navigate to the Azure portal > App registrations to register your app. Sign in using a work or school account, or a personal Microsoft account.

  2. Select New registration.

  3. When the Register an application page appears, set the values as follows:

    1. Set Name to PythonConsoleApp.
    2. Set Supported account types to Accounts in any organizational directory and personal Microsoft accounts.
    3. Leave Redirect URI empty.
    4. Choose Register.
  4. On the PythonConsoleApp overview page, copy and save the value for the Application (client) ID. You'll need it later.

  5. Select API permissions.

    1. Choose the Add a permission button and then make sure that the Microsoft APIs tab is selected.
    2. In the Commonly used Microsoft APIs section, select Microsoft Graph, and then select Delegated permissions.
    3. Use the Select permissions search box to search for the Files.ReadWrite and Mail.Send permissions.
    4. Select the checkbox for each permission as it appears.

      NOTE: Permissions will not remain visible in the list as you select each one.

  6. Go to the Authentication page.

    1. Check the box next to https://login.microsoftonline.com/common/oauth2/nativeclient.
    2. Find the setting labeled Default client type and set it to Yes.
    3. Select Save at the top of the page.

After registering your application, modify the config.py file in the root folder of your cloned repo, and follow the instructions to enter your Client ID (the Application ID value you copied in Step 3 earlier). Save the change, and you're ready to run the sample.

Running the sample

Follow these steps to run the sample app:

  1. At the command prompt, run the command python sample.py. You'll see a message telling you to open a page in your browser and enter a code. launch the sample

  2. After entering the code at https://aka.ms/devicelogin, you'll be prompted to select an identity or enter an email address to identify yourself. The identity you use must be in the same organization/tenant where the application was registered. Sign in, and then you'll be asked to consent to the application's delegated permissions as shown below. Choose Accept. consenting to permissions

  3. After consenting to permissions, you'll see a message saying "You have signed in to the console-app-sample application on your device. You may now close this window." Close the browser and return to the console. You are now authenticated, and the app has a token that can be used for Microsoft Graph requests. The app will request your user profile and display your name and email address, then prompt you for a destination email address. You may enter one or more email recipients (delimited with ;), or press Enter to send the email to yourself. entering recipients

  4. After entering email recipients, you'll see console output showing the Graph endpoints and responses for the remaining steps in the sample app: getting your profile photo, uploading it to OneDrive, creating a sharing link, and sending the email. sending the mail

Check your email, and you'll see the email that has been sent. It includes your profile photo as an attachment, as well as a view-only sharing link to the copy of your profile photo that was uploaded to the root folder of your OneDrive account.

receiving the mail

Device Flow authentication

Microsoft Graph uses Azure Active Directory (Azure AD) for authentication, and Azure AD supports a variety of OAuth 2.0 authentication flows. The recommended authorization flow for Python console apps is device flow, and this sample uses Microsoft ADAL for Python to implement device flow as shown in the diagram below.

device flow

The device_flow_session() function of helpers.py handles the authentication details. As you can see in sample.py, we try to create a session and then if successfully created we use that session to send mail:

GRAPH_SESSION = device_flow_session(config.CLIENT_ID)
if GRAPH_SESSION:
    sendmail_sample(GRAPH_SESSION)

The first step in device_flow_session() is to call ADAL's acquire_user_code() method to get a user code. This code is displayed on the console, and that code must be entered on the authorization URL page before it expires. While waiting for this to happen, the app calls ADAL's acquire_token_with_device_code() method, which begins polling to check whether the code has been entered. When the code is entered and the user consents to the requested permissions, an access token is returned. The app then creates a Requests session and stores the access token in the session's Authorization header, where it will be sent with calls to Microsoft Graph via the session's HTTP verb methods such as get() or post().

This sample doesn't use a refresh token, but it's easy to obtain a refresh token if you'd like to provide your users with a "remember me" experience that doesn't require logging in every time they run your app. To get a refresh token, register the application with offline_access permission, and then you'll receive a refresh token which you can use with ADAL's acquire_token_with_refresh_token method to refresh a Graph access token.

Helper functions

Several helper functions in helpers.py provide simple wrappers for common Graph operations, and provide examples of how to make authenticated Graph requests via the methods of the session object. These helper functions can be used with any auth library — the only requirement is that the session object has a valid Graph access token stored in its Authorization header.

A note on HTTP headers

In this sample, the session object sends the required Authorization header (which contains the access token) as well as optional headers to identify the libraries used. These headers are set during the authentication process. In addition, you may want to create other headers for certain Graph calls. You can do this by passing a headers dictionary to the Graph call, and this dictionary will be merged with the default headers on the session object. You can see an example of this technique in parameter for any of the send_mail helper function, which adds a Content-Type header as shown here.

api_endpoint(url)

Converts a relative path such as /me/photo/$value to a full URI based on the current RESOURCE and API_VERSION settings in config.py.

device_flow_session(client_id, auto=False)

Obtains an access token from Azure AD (via device flow) and create a Requests session instance ready to make authenticated calls to Microsoft Graph. The only required argument is the client_id of the registered application.

The optional auto argument can be set to True to automatically launch the authorization URL in your default browser and copy the user code to the clipboard. This can save time during repetitive dev/test activities.

profile_photo(session, *, user_id='me', save_as=None)

Gets a profile photo, and optionally saves a local copy. Returns a tuple of the raw photo data, HTTP status code, content type, and saved filename.

send_mail(session, *, subject, recipients, body='', content_type='HTML', attachments=None)

Sends email from current user. Returns the Requests response object for the POST.

sharing_link(session, *, item_id, link_type='view')

Creates a sharing link for an item in OneDrive.

upload_file(session, *, filename, folder=None)

Uploads a file to OneDrive for Business.

Contributing

These samples are open source, released under the MIT License. Issues (including feature requests and/or questions about this sample) and pull requests are welcome. If there's another Python sample you'd like to see for Microsoft Graph, we're interested in that feedback as well — please log an issue and let us know!

This project has adopted the Microsoft Open Source Code of Conduct. For more information, see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

Resources

python-sample-console-app's People

Contributors

jackson-woods avatar jasonjoh avatar nokafor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-sample-console-app's Issues

Requests got 404 error but work in Graph Explorer

Hi ,
I'm trying to modify the code to learn Microsoft Graph API. When I send any requests that target is a file in Document Library in SharePoint, I get the 404 responses with 'message': 'The resource could not be found.'. However, I check the requests in Graph Explorer, and I get 200 responses. I use a business account, and I had set all permissions that need for file accessing.
The requests I used
GET https://graph.microsoft.com/v1.0/sites/xxxx/drives/<drive_id_1>/root:/<existing_path>/
GET https://graph.microsoft.com/v1.0/drives/<drive_id_1>/items/<item_id_1>/

Additionally, I check the following request and get different response from the Graph Explorer
GET https://graph.microsoft.com/v1.0/drives/<drive_id_1>/root/children

  • The response for my code (the value field is empty)
    {'@odata.context': "https://graph.microsoft.com/v1.0/$metadata#drives('<drive_id_1>')/root/children", 'value': []}
  • The response in Graph Explorer (the value field is not empty)
    { "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#drives('<drive_id_1>')/root/children", "value": [ { "createdDateTime": "2018-12-20T18:04:06Z", "eTag": "\"{xxxx},1\"", "id": "xxxx", "lastModifiedDateTime": "2018-12-20T18:04:06Z", "name": "xxxx", "webUrl": "xxxx", "cTag": "\"c:{xxxxx},0\"", "size": 545056, "createdBy": { "user": { "email": "xxxx", "id": "xxxx", "displayName": "xxxx" } }, .... }, .... ] }

Not able to connect after allowing permissions (but have confirmation of permission granted

Traceback (most recent call last):
File "/python-sample-console-app/sample.py", line 81, in
GRAPH_SESSION = device_flow_session(config.CLIENT_ID)
File "/python-sample-console-app/helpers.py", line 54, in device_flow_session
client_id)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/adal/authentication_context.py", line 299, in acquire_token_with_device_code
return self._acquire_token(token_func, user_code_info.get('correlation_id', None))
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/adal/authentication_context.py", line 128, in _acquire_token
return token_func(self)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/adal/authentication_context.py", line 292, in token_func
token = token_request.get_token_with_device_code(user_code_info)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/adal/token_request.py", line 392, in get_token_with_device_code
token = client.get_token_with_polling(oauth_parameters, interval, expires_in)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/adal/oauth2_client.py", line 362, in get_token_with_polling
wire_response)
adal.adal_error.AdalError: Unexpected polling state invalid_client

authenticate without browser

Is it possible to authenticate without using a browser?
I want to be able to parse a onenote file in onedrive without having to authenticate through a browser (like in oauth2client)

README user must modifiy AUTHORITY_URL

The README is missing the need to change the AUTHORITY_URL,

from:
AUTHORITY_URL = 'https://login.microsoftonline.com/common'

to:
AUTHORITY_URL = 'https://login.microsoftonline.com/contoso.onmicrosoft.com'

as per:
https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki/ADAL-basics

else the example fails with:

AdalError(return_error_string, error_response) adal.adal_error.AdalError: Get Device Code request returned http error: 400 and server response: {"error":"invalid_request","error_description":"AADSTS50059: No tenant-identifying information found in either the request or implied by any provided credentials....

f-strings

Hi,

In Installation it is written "..., but any Python 3.x version should work". Since f-strings is used in sample.py this is not true

bad handshake

Hello,

I followed the tutorial, and registered in the Azure AD as native app, but got the following error when I updated the Client ID. I've searched everywhere within Azure documentations, and googled SSL related issues, but could not get this error to go away. Has there been an update within ADAL that needs further updates?

requests.exceptions.SSLError: HTTPSConnectionPool(host='login.microsoftonline.com', port=443): Max retries exceeded with url: /common/oauth2/devicecode?api-version=1.0 (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",),))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.