Skip to content

Application Managed Sessions - OAuth2

If an application cannot or should not use a login session initiated by the planet auth CLI command, the application will be responsible for managing the process on its own, persisting session state as needed.

Application managed sessions may be used with all authentication protocols. Application developers may control whether sessions are visible to the CLI. This is managed with the save_state_to_storage parameter on the planet.Auth constructor methods illustrated below.

The process varies depending on the authentication protocol used. Depending on the use case, applications may need to support multiple authentication methods, just as the planet CLI command supports interacting with Planet APIs using either a user or a service user account.

OAuth2 Session for Users

User session initialization inherently involves using a web browser to complete user authentication. This architecture allows for greater security by keeping the user's password from being directly exposed to the application code. This also allows for flexibility in user federation and multifactor authentication procedures without the complexity of these needing to be exposed to the application developer who is focused on geospatial operations using the Planet platform, and not the nuances of user authentication and authorization.

OAuth2 User Client Registration

Developers of applications must register client applications with Planet, and will be issued a Client ID as part of that process. Developers should register a client for each distinct application so that end-users may discretely manage applications permitted to access Planet APIs on their behalf.

See OAuth2 Client Registration for more information.

With a Local Web Browser

In environments where a local browser is available, the Planet SDK library can manage the process of launching the browser locally, transferring control to the Planet authorization services for session initialization, and accepting a network callback from the local browser to regain control once the authorization process is complete. At a network protocol level, this establishes the user login session using the OAuth2 authorization code flow.

To use this method using the SDK, the following requirements must be met:

  • The application must be able to launch a local web browser.
  • The web browser must be able to connect to Planet services.
  • The application must be able to listen on a network port that is accessible to the browser.

Examples - OAuth2 Authorization Code Flow

In Memory Session State

When an application cannot safely store user session state, it may operate purely in memory. When this method is used, the user will be prompted to complete the login process each time the application is run.

Login as a user using a local browser with in memory only state persistance
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import json
import planet


def example_main():
    # Create an auth context with a client ID that
    # is unique to this application.
    plsdk_auth = planet.Auth.from_oauth_user_auth_code(
        client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
        requested_scopes=[
            # Request access to Planet APIs
            planet.PlanetOAuthScopes.PLANET,
            # Request a refresh token so repeated browser logins are not required
            planet.PlanetOAuthScopes.OFFLINE_ACCESS,
        ],
        callback_url="http://localhost:8080",
        save_state_to_storage=False,
    )

    # An application with no persistent storage must
    # initialize a login every time.  This is not smooth user experience.
    plsdk_auth.user_login(allow_open_browser=True)

    # Create a Planet SDK object that uses the loaded auth session.
    sess = planet.Session(plsdk_auth)
    pl = planet.Planet(sess)

    # Use the SDK to call Planet APIs.
    # Refreshing access tokens will be managed automatically by the SDK.
    for item in pl.data.list_searches():
        print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
    example_main()
Session State Shared with CLI

Applications may save their session state in a way that is shared with the CLI. With saved state, the user will only be prompted to complete the login process once.

Login as a user using a local browser with sessions persisted on disk and shared with the CLI
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import json
import planet


def example_main():
    # Create an auth context with a client ID that
    # is unique to this application.
    plsdk_auth = planet.Auth.from_oauth_user_auth_code(
        client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
        requested_scopes=[
            # Request access to Planet APIs
            planet.PlanetOAuthScopes.PLANET,
            # Request a refresh token so repeated browser logins are not required
            planet.PlanetOAuthScopes.OFFLINE_ACCESS,
        ],
        callback_url="http://localhost:8080",
        profile_name="my-name-for-example-user-session-with-local-browser",
        save_state_to_storage=True,
    )

    # In contrast to in-memory applications that must initialize a login every
    # time, an app with persistent storage can skip user prompts when they
    # are not needed.
    # This helper will prompt the user only when it is necessary.
    plsdk_auth.ensure_initialized(allow_open_browser=True,
                                  allow_tty_prompt=True)

    # Create a Planet SDK object that uses the loaded auth session.
    sess = planet.Session(plsdk_auth)
    pl = planet.Planet(sess)

    # Use the SDK to call Planet APIs.
    # Refreshing access tokens will be managed automatically by the SDK.
    for item in pl.data.list_searches():
        print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
    example_main()

Session State Saved to Application Storage

Applications may save their session state to application provided storage. With saved state, the user should only be prompted to complete the login process once. Using application provided storage will result in the session state not being shared with the CLI.

Applications needing to use their own storage will do so by providing the Auth layer in the SDK with a custom implementation of the planet_auth.ObjectStorageProvider abstract base class. See examples below for more details.

Login as a user using a local browser with sessions persisted to application provided storage
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
import json
import logging
import os
import pathlib
import stat

import planet

from planet_auth import ObjectStorageProvider, ObjectStorageProvider_KeyType

logging.basicConfig(level=logging.CRITICAL)


class DemoStorageProvider(ObjectStorageProvider):
    """
    Simple demo custom storage provider that uses
    ~/.planet-demo as a storage home for saving object.

    As a practical matter, ObjectStorageProvider_KeyType is defined
    to be pathlib.Path, and we leverage that in this example.
    But, storage providers are not required to use the local file
    system to store objects.
    """

    def __init__(self):
        self._demo_storage_root = pathlib.Path.home() / ".planet-demo"

    def load_obj(self, key: ObjectStorageProvider_KeyType) -> dict:
        demo_obj_filepath = self._demo_obj_filepath(key)
        return self._load_file(file_path=demo_obj_filepath)

    def save_obj(self, key: ObjectStorageProvider_KeyType, data: dict) -> None:
        demo_obj_filepath = self._demo_obj_filepath(key)
        self._save_file(file_path=demo_obj_filepath, data=data)

    def obj_exists(self, key: ObjectStorageProvider_KeyType) -> bool:
        demo_obj_filepath = self._demo_obj_filepath(key)
        return demo_obj_filepath.exists()

    def mtime(self, key: ObjectStorageProvider_KeyType) -> float:
        obj_filepath = self._demo_obj_filepath(key)
        return obj_filepath.stat().st_mtime

    def obj_rename(self,
                   src: ObjectStorageProvider_KeyType,
                   dst: ObjectStorageProvider_KeyType) -> None:
        src_filepath = self._demo_obj_filepath(src)
        dst_filepath = self._demo_obj_filepath(dst)
        src_filepath.rename(dst_filepath)

    def _demo_obj_filepath(self, obj_key):
        if obj_key.is_absolute():
            obj_path = self._demo_storage_root / obj_key.relative_to("/")
        else:
            obj_path = self._demo_storage_root / obj_key
        return obj_path

    @staticmethod
    def _load_file(file_path: pathlib.Path) -> dict:
        logging.debug(msg="Loading JSON data from file {}".format(file_path))
        with open(file_path, mode="r", encoding="UTF-8") as file_r:
            return json.load(file_r)

    @staticmethod
    def _save_file(file_path: pathlib.Path, data: dict):
        file_path.parent.mkdir(parents=True, exist_ok=True)
        logging.debug(msg="Writing JSON data to file {}".format(file_path))
        with open(file_path, mode="w", encoding="UTF-8") as file_w:
            os.chmod(file_path, stat.S_IREAD | stat.S_IWRITE)
            _no_none_data = {
                key: value
                for key, value in data.items() if value is not None
            }
            file_w.write(json.dumps(_no_none_data, indent=2, sort_keys=True))


def example_main():
    # Create an auth context with a client ID that
    # is unique to this application.
    plsdk_auth = planet.Auth.from_oauth_user_auth_code(
        client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
        requested_scopes=[
            # Request access to Planet APIs
            planet.PlanetOAuthScopes.PLANET,
            # Request a refresh token so repeated browser logins are not required
            planet.PlanetOAuthScopes.OFFLINE_ACCESS,
        ],
        callback_url="http://localhost:8080",
        profile_name="my-example-name-auth-code-with-custom-storage",
        save_state_to_storage=True,
        storage_provider=DemoStorageProvider(),
    )

    # In contrast to in-memory applications that must initialize a login every
    # time, an app with persistent storage can skip user prompts when they
    # are not needed.
    # This helper will prompt the user only when it is necessary.
    plsdk_auth.ensure_initialized(allow_open_browser=True,
                                  allow_tty_prompt=True)

    # Create a Planet SDK object that uses the loaded auth session.
    sess = planet.Session(plsdk_auth)
    pl = planet.Planet(sess)

    # Use the SDK to call Planet APIs.
    # Refreshing access tokens will be managed automatically by the SDK.
    for item in pl.data.list_searches():
        print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
    example_main()

Without a Local Web Browser

In environments where a local web browser is not available, additional steps must be taken by the application author to initialize the user session. For example, a remote shell to a cloud environment is not likely to be able to open a browser on the user's desktop or receive network callbacks from the user's desktop browser. In these cases, a browser is still required. To complete login in such a case, the SDK will generate a URL and a verification code that must be presented to the user. The user must visit the URL out of band to complete the login process while the application polls for the completion of the login process using the SDK. At a network protocol level, this establishes the user login session using the OAuth2 device code flow.

To use this method using the SDK, the following requirements must be met:

  • The application must be able to connect to Planet services.
  • The application must be able to display instructions to the user, directing them to a web location to complete login.

As above, this may be done with state only persisted in memory, with state shared with the CLI, or with state saved to application provided storage.

Examples - OAuth2 Device Code Flow

In Memory Session State
Login as a user using an external browser with in memory only state persistance
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import json
import planet


def initialize_user_session(plsdk_auth):
    # Example of initiating a user session where the app is 100%
    # responsible for the user experience.

    # 1. Initiate the login
    login_initialization_info = plsdk_auth.device_user_login_initiate()

    # 2. Display necessary instructions to the user.
    #
    #    "verification_uri" and "user_code" are required under RFC 8628.
    #    "verification_uri_complete" is optional under the RFC.
    #
    #    If the user is expected to type in the URL, verification_uri will be
    #    shorter.  If the URL may be presented in a clickable means (such as a
    #    link, button, or QR code) the verification_uri_complete may offer a
    #    better user experience.
    verification_uri_complete = login_initialization_info.get(
        "verification_uri_complete")
    verification_uri = login_initialization_info.get("verification_uri")
    user_code = login_initialization_info.get("user_code")

    print("Please activate your client.")
    if verification_uri_complete:
        print(f"Visit the activation site:\n"
              f"\n\t{verification_uri_complete}\n"
              f"\nand confirm the authorization code:\n"
              f"\n\t{user_code}\n")
    else:
        print(f"Visit the activation site:\n"
              f"\n\t{verification_uri}\n"
              f"\nand enter the authorization code:\n"
              f"\n\t{user_code}\n")

    # 3. Return control to the SDK.  This will block until the user
    #    completes login.
    plsdk_auth.device_user_login_complete(login_initialization_info)


def example_main():
    # Create an auth context with a client ID that
    # is unique to this application.
    plsdk_auth = planet.Auth.from_oauth_user_device_code(
        client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
        requested_scopes=[
            # Request access to Planet APIs
            planet.PlanetOAuthScopes.PLANET,
            # Request a refresh token so repeated browser logins are not required
            planet.PlanetOAuthScopes.OFFLINE_ACCESS,
        ],
        save_state_to_storage=False,
    )

    # An application with no persistent storage must initialize a login every
    # time.  This is not smooth user experience.
    initialize_user_session(plsdk_auth)

    # Create a Planet SDK object that uses the loaded auth session.
    sess = planet.Session(plsdk_auth)
    pl = planet.Planet(sess)

    # Use the SDK to call Planet APIs.
    # Refreshing access tokens will be managed automatically by the SDK.
    for item in pl.data.list_searches():
        print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
    example_main()
Session State Shared with CLI
Login as a user using an external browser with sessions persisted on disk and shared with the CLI
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import json
import planet


def initialize_user_session(plsdk_auth):
    # Example of initiating a user session where the app is 100%
    # responsible for the user experience.

    # 1. Initiate the login
    login_initialization_info = plsdk_auth.device_user_login_initiate()

    # 2. Display necessary instructions to the user.
    #
    #    "verification_uri" and "user_code" are required under RFC 8628.
    #    "verification_uri_complete" is optional under the RFC.
    #
    #    If the user is expected to type in the URL, verification_uri will be
    #    shorter.  If the URL may be presented in a clickable means (such as a
    #    link, button, or QR code) the verification_uri_complete may offer a
    #    better user experience.
    verification_uri_complete = login_initialization_info.get(
        "verification_uri_complete")
    verification_uri = login_initialization_info.get("verification_uri")
    user_code = login_initialization_info.get("user_code")

    print("Please activate your client.")
    if verification_uri_complete:
        print(f"Visit the activation site:\n"
              f"\n\t{verification_uri_complete}\n"
              f"\nand confirm the authorization code:\n"
              f"\n\t{user_code}\n")
    else:
        print(f"Visit the activation site:\n"
              f"\n\t{verification_uri}\n"
              f"\nand enter the authorization code:\n"
              f"\n\t{user_code}\n")

    # 3. Return control to the SDK.  This will block until the user
    #    completes login.
    plsdk_auth.device_user_login_complete(login_initialization_info)


def example_main():
    # Create an auth context with a client ID that
    # is unique to this application.
    plsdk_auth = planet.Auth.from_oauth_user_device_code(
        client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
        requested_scopes=[
            # Request access to Planet APIs
            planet.PlanetOAuthScopes.PLANET,
            # Request a refresh token so repeated browser logins are not required
            planet.PlanetOAuthScopes.OFFLINE_ACCESS,
        ],
        profile_name="my-name-example-user-auth-with-external-browser",
        save_state_to_storage=True,
    )

    # In contrast to an in-memory only application that must initialize a login every
    # time, an app with persistent storage can skip this when it is not needed.
    if not plsdk_auth.is_initialized():
        initialize_user_session(plsdk_auth)

    # Create a Planet SDK object that uses the loaded auth session.
    sess = planet.Session(plsdk_auth)
    pl = planet.Planet(sess)

    # Use the SDK to call Planet APIs.
    # Refreshing access tokens will be managed automatically by the SDK.
    for item in pl.data.list_searches():
        print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
    example_main()
Session State Saved to Application Storage
Login as a user using an external browser with sessions persisted to application provided storage
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import json
import logging
import os
import pathlib
import stat

import planet

from planet_auth import ObjectStorageProvider, ObjectStorageProvider_KeyType

logging.basicConfig(level=logging.CRITICAL)


class DemoStorageProvider(ObjectStorageProvider):
    """
    Simple demo custom storage provider that uses
    ~/.planet-demo as a storage home for saving object.

    As a practical matter, ObjectStorageProvider_KeyType is defined
    to be pathlib.Path, and we leverage that in this example.
    But, storage providers are not required to use the local file
    system to store objects.
    """

    def __init__(self):
        self._demo_storage_root = pathlib.Path.home() / ".planet-demo"

    def load_obj(self, key: ObjectStorageProvider_KeyType) -> dict:
        demo_obj_filepath = self._demo_obj_filepath(key)
        return self._load_file(file_path=demo_obj_filepath)

    def save_obj(self, key: ObjectStorageProvider_KeyType, data: dict) -> None:
        demo_obj_filepath = self._demo_obj_filepath(key)
        self._save_file(file_path=demo_obj_filepath, data=data)

    def obj_exists(self, key: ObjectStorageProvider_KeyType) -> bool:
        demo_obj_filepath = self._demo_obj_filepath(key)
        return demo_obj_filepath.exists()

    def mtime(self, key: ObjectStorageProvider_KeyType) -> float:
        obj_filepath = self._demo_obj_filepath(key)
        return obj_filepath.stat().st_mtime

    def obj_rename(self,
                   src: ObjectStorageProvider_KeyType,
                   dst: ObjectStorageProvider_KeyType) -> None:
        src_filepath = self._demo_obj_filepath(src)
        dst_filepath = self._demo_obj_filepath(dst)
        src_filepath.rename(dst_filepath)

    def _demo_obj_filepath(self, obj_key):
        if obj_key.is_absolute():
            obj_path = self._demo_storage_root / obj_key.relative_to("/")
        else:
            obj_path = self._demo_storage_root / obj_key
        return obj_path

    @staticmethod
    def _load_file(file_path: pathlib.Path) -> dict:
        logging.debug(msg="Loading JSON data from file {}".format(file_path))
        with open(file_path, mode="r", encoding="UTF-8") as file_r:
            return json.load(file_r)

    @staticmethod
    def _save_file(file_path: pathlib.Path, data: dict):
        file_path.parent.mkdir(parents=True, exist_ok=True)
        logging.debug(msg="Writing JSON data to file {}".format(file_path))
        with open(file_path, mode="w", encoding="UTF-8") as file_w:
            os.chmod(file_path, stat.S_IREAD | stat.S_IWRITE)
            _no_none_data = {
                key: value
                for key, value in data.items() if value is not None
            }
            file_w.write(json.dumps(_no_none_data, indent=2, sort_keys=True))


def initialize_user_session(plsdk_auth):
    # Example of initiating a user session where the app is 100%
    # responsible for the user experience.

    # 1. Initiate the login
    login_initialization_info = plsdk_auth.device_user_login_initiate()

    # 2. Display necessary instructions to the user.
    #
    #    "verification_uri" and "user_code" are required under RFC 8628.
    #    "verification_uri_complete" is optional under the RFC.
    #
    #    If the user is expected to type in the URL, verification_uri will be
    #    shorter.  If the URL may be presented in a clickable means (such as a
    #    link, button, or QR code) the verification_uri_complete may offer a
    #    better user experience.
    verification_uri_complete = login_initialization_info.get(
        "verification_uri_complete")
    verification_uri = login_initialization_info.get("verification_uri")
    user_code = login_initialization_info.get("user_code")

    print("Please activate your client.")
    if verification_uri_complete:
        print(f"Visit the activation site:\n"
              f"\n\t{verification_uri_complete}\n"
              f"\nand confirm the authorization code:\n"
              f"\n\t{user_code}\n")
    else:
        print(f"Visit the activation site:\n"
              f"\n\t{verification_uri}\n"
              f"\nand enter the authorization code:\n"
              f"\n\t{user_code}\n")

    # 3. Return control to the SDK.  This will block until the user
    #    completes login.
    plsdk_auth.device_user_login_complete(login_initialization_info)


def example_main():
    # Create an auth context with a client ID that
    # is unique to this application.
    plsdk_auth = planet.Auth.from_oauth_user_device_code(
        client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
        requested_scopes=[
            # Request access to Planet APIs
            planet.PlanetOAuthScopes.PLANET,
            # Request a refresh token so repeated browser logins are not required
            planet.PlanetOAuthScopes.OFFLINE_ACCESS,
        ],
        profile_name="my-example-name-device-code-with-custom-storage",
        save_state_to_storage=True,
        storage_provider=DemoStorageProvider(),
    )

    # In contrast to an in-memory only application that must initialize a login every
    # time, an app with persistent storage can skip this when it is not needed.
    if not plsdk_auth.is_initialized():
        initialize_user_session(plsdk_auth)

    # Create a Planet SDK object that uses the loaded auth session.
    sess = planet.Session(plsdk_auth)
    pl = planet.Planet(sess)

    # Use the SDK to call Planet APIs.
    # Refreshing access tokens will be managed automatically by the SDK.
    for item in pl.data.list_searches():
        print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
    example_main()

OAuth2 Session for Service Accounts

Service account session initialization is simpler than user session initialization, and does not require a web browser.

While preserving session state for user sessions was a concern driven in part by a concern for the user experience of using a web browser for initialization, for service accounts it remains a concern to avoid throttling by the authorization service.

If applications are expected to run longer than the life of an access token (a few hours), then in memory operations are acceptable (for example: a long-running data processing job). If application lifespan is short and frequent, then the application should take steps to persist the session state (for example: a command line utility run repeatedly from a shell with a short lifespan).

Like the session state itself, service account initialization parameters are sensitive, and it is the responsibility of the application to store them securely.

At a network protocol level, OAuth2 service account sessions are implemented using the OAuth2 authorization code flow. This carries with it some additional security concerns, discussed in RFC 6819 ยง4.4.4. Because of these considerations, service accounts should only be used for workflows that are independent of a controlling user.

As above, this may be done with state only persisted in memory, with state shared with the CLI, or with state saved to application provided storage.

OAuth2 M2M Client Registration

Service accounts are managed under the OAuth Clients panel on the Planet Insights Account page.

See Sentinel Hub Authentication for further information.

Examples - OAuth2 Client Credentials Flow

In Memory Session State

Access APIs using a service account with in memory only state persistance
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import json
import planet


def example_main():
    # Create an auth context with the client ID and secret of the service account.
    plsdk_auth = planet.Auth.from_oauth_m2m(
        client_id="__MUST_BE_END_USER_SUPPLIED__",
        client_secret="__MUST_BE_END_USER_SUPPLIED__",
        save_state_to_storage=False,
    )

    # Explicit login is not required for M2M client use. The above is sufficient.
    # plsdk_auth.user_login()

    # Create a Planet SDK object that uses the loaded auth session.
    sess = planet.Session(plsdk_auth)
    pl = planet.Planet(sess)

    # Use the SDK to call Planet APIs.
    # Refreshing access tokens will be managed automatically by the SDK.
    for item in pl.data.list_searches():
        print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
    example_main()

Session State Shared with CLI

Access APIs using a service account with sessions persisted on disk and shared with the CLI
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import json
import planet


def example_main():
    # Create an auth context with the client ID and secret of the service account.
    plsdk_auth = planet.Auth.from_oauth_m2m(
        client_id="__MUST_BE_END_USER_SUPPLIED__",
        client_secret="__MUST_BE_END_USER_SUPPLIED__",
        profile_name="my-name-for-example-m2m-auth-profile",
        save_state_to_storage=True,
    )

    # Explicit login is not required for M2M client use. The above is sufficient.
    # plsdk_auth.user_login()

    # Create a Planet SDK object that uses the loaded auth session.
    sess = planet.Session(plsdk_auth)
    pl = planet.Planet(sess)

    # Use the SDK to call Planet APIs.
    # Refreshing access tokens will be managed automatically by the SDK.
    for item in pl.data.list_searches():
        print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
    example_main()

Session State Saved to Application Storage

Access APIs using a service account with sessions persisted to application provided storage
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
import json
import logging
import os
import pathlib
import stat

import planet

from planet_auth import ObjectStorageProvider, ObjectStorageProvider_KeyType

logging.basicConfig(level=logging.CRITICAL)


class DemoStorageProvider(ObjectStorageProvider):
    """
    Simple demo custom storage provider that uses
    ~/.planet-demo as a storage home for saving object.

    As a practical matter, ObjectStorageProvider_KeyType is defined
    to be pathlib.Path, and we leverage that in this example.
    But, storage providers are not required to use the local file
    system to store objects.
    """

    def __init__(self):
        self._demo_storage_root = pathlib.Path.home() / ".planet-demo"

    def load_obj(self, key: ObjectStorageProvider_KeyType) -> dict:
        demo_obj_filepath = self._demo_obj_filepath(key)
        return self._load_file(file_path=demo_obj_filepath)

    def save_obj(self, key: ObjectStorageProvider_KeyType, data: dict) -> None:
        demo_obj_filepath = self._demo_obj_filepath(key)
        self._save_file(file_path=demo_obj_filepath, data=data)

    def obj_exists(self, key: ObjectStorageProvider_KeyType) -> bool:
        demo_obj_filepath = self._demo_obj_filepath(key)
        return demo_obj_filepath.exists()

    def mtime(self, key: ObjectStorageProvider_KeyType) -> float:
        obj_filepath = self._demo_obj_filepath(key)
        return obj_filepath.stat().st_mtime

    def obj_rename(self,
                   src: ObjectStorageProvider_KeyType,
                   dst: ObjectStorageProvider_KeyType) -> None:
        src_filepath = self._demo_obj_filepath(src)
        dst_filepath = self._demo_obj_filepath(dst)
        src_filepath.rename(dst_filepath)

    def _demo_obj_filepath(self, obj_key):
        if obj_key.is_absolute():
            obj_path = self._demo_storage_root / obj_key.relative_to("/")
        else:
            obj_path = self._demo_storage_root / obj_key
        return obj_path

    @staticmethod
    def _load_file(file_path: pathlib.Path) -> dict:
        logging.debug(msg="Loading JSON data from file {}".format(file_path))
        with open(file_path, mode="r", encoding="UTF-8") as file_r:
            return json.load(file_r)

    @staticmethod
    def _save_file(file_path: pathlib.Path, data: dict):
        file_path.parent.mkdir(parents=True, exist_ok=True)
        logging.debug(msg="Writing JSON data to file {}".format(file_path))
        with open(file_path, mode="w", encoding="UTF-8") as file_w:
            os.chmod(file_path, stat.S_IREAD | stat.S_IWRITE)
            _no_none_data = {
                key: value
                for key, value in data.items() if value is not None
            }
            file_w.write(json.dumps(_no_none_data, indent=2, sort_keys=True))


def example_main():
    # Create an auth context with the client ID and secret of the service account.
    plsdk_auth = planet.Auth.from_oauth_m2m(
        client_id="__MUST_BE_END_USER_SUPPLIED__",
        client_secret="__MUST_BE_END_USER_SUPPLIED__",
        profile_name="my-example-name-m2m-with-custom-storage",
        save_state_to_storage=True,
        storage_provider=DemoStorageProvider(),
    )

    # Explicit login is not required for M2M client use. The above sufficient.
    # plsdk_auth.user_login()

    # Create a Planet SDK object that uses the loaded auth session.
    sess = planet.Session(plsdk_auth)
    pl = planet.Planet(sess)

    # Use the SDK to call Planet APIs.
    # Refreshing access tokens will be managed automatically by the SDK.
    for item in pl.data.list_searches():
        print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
    example_main()

Back to top