Skip to content

Client Examples

Client examples cover scenarios in which a program wishes to use the planet auth utilities as a client, obtaining credentials from authentication services so that they may be used to make authenticated requests to other network services.

OAuth Client Authentication

A custom auth client profile may be used to configure the AuthClient to use an arbitrary OAuth2 auth service to obtain access tokens for use with application APIs. See Configuration and Profiles for more information on client types and profiles.

  1. Create a ~/.planet/<profile_name>/auth_client.json or ~/.planet/<profile_name>/auth_client.sops.json file. For example, to create a custom profile named "my-custom-profile", create the following:
    ~/.planet/my-custom-profile/auth_client.json
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    {
        "client_type": "oidc_auth_code",
        "auth_server": "https://login.planet.com/",
        "client_id": "your_client_id",
        "redirect_uri": "client_redirect_url_for_network_hosted_handler__if_needed",
        "local_redirect_uri": "client_redirect_url_for_localhost_handler__if_needed",
        "authorization_callback_acknowledgement": "optional__custom_authorization_callback_acknowledgement",
        "authorization_callback_acknowledgement_file": "optional__custom_authorization_callback_acknowledgement_from_a_file",
        "scopes": [
            "planet",
            "offline_access",
            "openid",
            "profile"
        ]
    }
    
  2. Initialize the client library with the specified profile. Note: if the environment variable PL_AUTH_PROFILE is set, it will be detected automatically by planet_auth_utils.PlanetAuthFactory, and it will not be necessary to explicitly pass in the profile name:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    import planet_auth_utils
    
    
    def main():
        auth_ctx = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context(auth_profile_opt="my-custom-profile")
        print(f"Auth context initialized from on disk profile {auth_ctx.profile_name()}")
    
    
    if __name__ == "__main__":
        main()
    
    An alternative to creating a file on disk is to initialize_from_profile a client purely in memory. For some runtime environments where local storage may not be available or trusted, this may be more appropriate:
     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 planet_auth_utils
    
    
    def main():
        # The required fields will vary by client type.
        # See documentation regarding auth client configuration.
        auth_client_config = {
            "client_type": "oidc_auth_code",
            "auth_server": "https://login.example.com/",
            "client_id": "your_client_id",
            "local_redirect_uri": "http://localhost:8080",
            "audiences": ["https://api.planet.com/"],
            "scopes": ["offline_access", "openid", "profile", "planet"],
        }
        auth_ctx = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context_from_custom_config(
            client_config=auth_client_config,
            profile_name="_my_profile_name_",
            save_token_file=False,
            save_profile_config=False,
        )
        print(
            f"Auth context initialized from in memory profile. Auth client class is {auth_ctx.auth_client().__class__.__name__}."
        )
    
    
    if __name__ == "__main__":
        main()
    
  3. Perform initial login to obtain and save long term credentials, if required by the configured profile. An initial login is usually required for auth clients that act on behalf of a user and need to perform an interactive login. Clients configured for service operation may frequently skip this step:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import logging
    import planet_auth_utils
    
    
    def main():
        logging.basicConfig(level=logging.DEBUG)
        auth_ctx = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context(auth_profile_opt="my-custom-profile")
    
        if not auth_ctx.request_authenticator_is_ready():
            # Returned credential is also saved to disk in the profile directory.
            credential = auth_ctx.login(allow_open_browser=True, allow_tty_prompt=True)
            print(f"New credential saved to file {format(credential.path())}")
        else:
            print(f"{auth_ctx.profile_name()} has already been initialized.")
    
    
    if __name__ == "__main__":
        main()
    
  4. Make authenticated requests:
    • Option 1 - Using requests:
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      import logging
      import requests
      import planet_auth_utils
      
      
      def main():
          logging.basicConfig(level=logging.DEBUG)
          auth_ctx = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context(auth_profile_opt="my-custom-profile")
          auth_ctx.ensure_request_authenticator_is_ready(allow_open_browser=True, allow_tty_prompt=True)
          result = requests.get(
              url="https://api.planet.com/basemaps/v1/mosaics",
              auth=auth_ctx.request_authenticator(),
              headers={"X-Planet-App": "requests-example"},
          )
          print(result.status_code)
          print(result.json())
      
      
      if __name__ == "__main__":
          main()
      
    • Option 2 - Using httpx:
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      import logging
      import httpx
      import planet_auth_utils
      
      
      def main():
          logging.basicConfig(level=logging.DEBUG)
          auth_ctx = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context(auth_profile_opt="my-custom-profile")
          auth_ctx.ensure_request_authenticator_is_ready(allow_open_browser=True, allow_tty_prompt=True)
          result = httpx.get(
              url="https://api.planet.com/basemaps/v1/mosaics",
              auth=auth_ctx.request_authenticator(),
              headers={"X-Planet-App": "httpx-example"},
          )
          print(result.status_code)
          print(result.json())
      
      
      if __name__ == "__main__":
          main()
      

Performing a Device Login

The procedure for performing initial user login on a UI limited device is slightly different. Rather than simply calling login(), it is necessary to initiate the process with a call to device_login_initiate(), display the returned information to the user so that the user may authorize the client asynchronously, and complete the process by calling device_login_complete(). This procedure only applies to clients that are permitted to use the Device Authorization OAuth flow.

 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
import logging
import pyqrcode  # type: ignore
import planet_auth_utils


def prompt_user(init_login_info):
    print("Please activate your device.")
    print(
        "Visit the activation site:\n"
        f"\n\t{init_login_info.get("verification_uri")}\n"
        "\nand enter the activation code:\n"
        f"\n\t{init_login_info.get("user_code")}\n"
    )

    # "verification_url_complete" is optional under the RFC.
    # This may not always be available to display.
    if init_login_info.get("verification_uri_complete"):
        qr_code = pyqrcode.create(content=init_login_info.get("verification_uri_complete"), error="L")
    else:
        qr_code = pyqrcode.create(content=init_login_info.get("verification_uri"), error="L")

    print(f"You may scan this QR code to continue with your mobile device:\n\n{qr_code.terminal()}\n")


def main():
    logging.basicConfig(level=logging.DEBUG)

    myapp_auth_client_config = {
        "client_type": "oidc_device_code",
        "auth_server": "https://login.example.com/",
        "client_id": "__client_id__",
        "scopes": ["planet", "offline_access", "openid", "profile"],
    }
    auth_ctx = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context_from_custom_config(
        client_config=myapp_auth_client_config,
        profile_name="_my_profile_name_",
        # This example directs the library to save the client configration to
        # a new profile, so that the application may bootstrap the auth session
        # from saved state.
        save_token_file=True,
        save_profile_config=True,
    )
    if not auth_ctx.request_authenticator_is_ready():
        login_init_info = auth_ctx.device_login_initiate()
        prompt_user(login_init_info)
        # credential will also be saved the file configured above, and
        # the request authenticator will be updated with the credential.
        credential = auth_ctx.device_login_complete(login_init_info)
        print(f"Credential saved to file {credential.path()}")


if __name__ == "__main__":
    main()

Planet Legacy Authentication

The proprietary Planet legacy authentication protocol is targeted for future deprecation. It should not be used for any new development.

Initial Login

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import planet_auth
import planet_auth_config  # type: ignore


def main():
    _legacy_client_config = {
        **planet_auth_config.Staging.LEGACY_AUTH_AUTHORITY,
        "client_type": "planet_legacy",
    }
    # Be careful where you save the token file
    auth_ctx = planet_auth.Auth.initialize_from_config_dict(
        client_config=_legacy_client_config, token_file="/saved_token.json"
    )
    auth_ctx.login(allow_tty_prompt=True)


if __name__ == "__main__":
    main()

Authenticated requests Call

 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
import requests

import planet_auth
import planet_auth_config  # type: ignore


def main():
    _legacy_client_config = {
        **planet_auth_config.Staging.LEGACY_AUTH_AUTHORITY,
        "client_type": "planet_legacy",
    }

    auth_ctx = planet_auth.Auth.initialize_from_config_dict(
        client_config=_legacy_client_config, token_file="/saved_token.json"
    )
    # The presumption in this example is that the login has already been performed and the token saved.
    # See the login example for that process.

    result = requests.get(url="https://api.planet.com/basemaps/v1/mosaics", auth=auth_ctx.request_authenticator())
    print(result.status_code)
    print(result.json())


if __name__ == "__main__":
    main()