diff --git a/docs/auth/auth-dev-app-managed-apikey.md b/docs/auth/auth-dev-app-managed-apikey.md new file mode 100644 index 00000000..1b2888c9 --- /dev/null +++ b/docs/auth/auth-dev-app-managed-apikey.md @@ -0,0 +1,39 @@ +# Application Managed Sessions - Planet API Key + +## Planet API Key Sessions +Legacy applications that need to continue to support Planet API keys may do so +until API keys are deprecated. This method should not be adopted for new +development if possible. + +### Examples - Planet API Keys + +#### In Memory Session State +Once provided with an API key, an application may operate with the API key +in memory indefinitely without the need to prompt the user for re-authentication. +```python linenums="1" title="Access APIs using Planet API keys in memory" +{% include 'auth-session-management/app_managed_auth_state__in_memory__api_key.py' %} +``` + +#### Version 2 Compatibility +The SDK continues to support files written by version 2 of the SDK to save +auth state. +```python linenums="1" title="Access APIs using Planet API keys using the on disk file format used by older versions of the SDK" +{% include 'auth-session-management/app_managed_auth_state__on_disk_legacy__api_key.py' %} +``` + +```json linenums="1" title="Legacy API Key file example" +{% include 'auth-session-management/legacy_api_key_file.json' %} +``` + +#### Session State Shared with CLI +```python linenums="1" title="Access APIs using Planet API keys with CLI managed shared state on disk" +{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__api_key.py' %} +``` + +#### Session State Saved to Application Storage + +```python linenums="1" title="Access APIs using Planet API keys with sessions persisted to application provided storage" +{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__api_key.py' %} +``` + +---- diff --git a/docs/auth/auth-dev-app-managed-oauth.md b/docs/auth/auth-dev-app-managed-oauth.md new file mode 100644 index 00000000..f80d5806 --- /dev/null +++ b/docs/auth/auth-dev-app-managed-oauth.md @@ -0,0 +1,174 @@ +# Application Managed Sessions - OAuth2 + +If an application cannot or should not use a login session initiated by the +[`planet auth`](../../cli/cli-reference/#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/cli-reference) 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](http://docs.planet.com/develop/authentication/#interactive-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. + +```python linenums="1" title="Login as a user using a local browser with in memory only state persistance" +{% include 'auth-session-management/app_managed_auth_state__in_memory__oauth_user_authcode__with_browser.py' %} +``` + +##### 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. +```python linenums="1" title="Login as a user using a local browser with sessions persisted on disk and shared with the CLI" +{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_authcode__with_browser.py' %} +``` + +##### 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`](https://planet-auth.readthedocs.io/en/latest/api-planet-auth/#planet_auth.ObjectStorageProvider) +abstract base class. See examples below for more details. + +```python linenums="1" title="Login as a user using a local browser with sessions persisted to application provided storage" +{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__oauth_user_authcode__with_browser.py' %} +``` + +### 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 +```python linenums="1" title="Login as a user using an external browser with in memory only state persistance" +{% include 'auth-session-management/app_managed_auth_state__in_memory__oauth_user_devicecode__external_browser.py' %} +``` + +##### Session State Shared with CLI +```python linenums="1" title="Login as a user using an external browser with sessions persisted on disk and shared with the CLI" +{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_devicecode__external_browser.py' %} +``` + +##### Session State Saved to Application Storage +```python linenums="1" title="Login as a user using an external browser with sessions persisted to application provided storage" +{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__oauth_user_devicecode__external_browser.py' %} +``` + +## 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](https://datatracker.ietf.org/doc/html/rfc6819#section-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](https://insights.planet.com/account/#/) page. + +See [Sentinel Hub Authentication](https://docs.sentinel-hub.com/api/latest/api/overview/authentication/) for further information. + +### Examples - OAuth2 Client Credentials Flow + +#### In Memory Session State +```python linenums="1" title="Access APIs using a service account with in memory only state persistance" +{% include 'auth-session-management/app_managed_auth_state__in_memory__oauth_m2m.py' %} +``` + +#### Session State Shared with CLI +```python linenums="1" title="Access APIs using a service account with sessions persisted on disk and shared with the CLI" +{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_m2m.py' %} +``` + +#### Session State Saved to Application Storage +```python linenums="1" title="Access APIs using a service account with sessions persisted to application provided storage" +{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__oauth_m2m.py' %} +``` + +---- diff --git a/docs/auth/auth-dev-cli-managed.md b/docs/auth/auth-dev-cli-managed.md new file mode 100644 index 00000000..ba7f84a7 --- /dev/null +++ b/docs/auth/auth-dev-cli-managed.md @@ -0,0 +1,110 @@ +# CLI Managed Sessions +For simple programs and scripts, it is easiest for the program to defer +session management to the [`planet auth`](../../cli/cli-reference/#auth) +CLI. This method will store session information in the user's home directory +in the `~/.planet.json` file and `~/.planet/` directory. The Python SDK will +use the information saved in these locations to make API calls. + +When this approach is taken, the authentication session will be shared between +actions taken by the `planet` utility and those taken by programs built +using the SDK. Changes made by one will impact the behavior of the other. + +CLI managed sessions can be used for all authentication protocols supported +by the SDK library. + +**Requirements and Limitations:** + +* The program must have read and write access to the user's home directory. +* This method requires that the end-user has access to and understands + the [`planet`](../../cli/cli-reference) CLI command needed to manage + authentication. +* This approach should not be used on public terminals or in cases where the + user's home directory cannot be kept confidential. + +## Initialize Session - CLI Login +Session login can be performed using the following command. This command can +be used to initialize sessions using any of the supported authentication methods, +and will default to creating an OAuth2 user session. +Refer to the command's `--help` for more information. + + +```shell title="Initialize session using planet CLI." +planet auth login +``` + +A particular configuration may be selected by using the `--auth-profile` option. +`planet-user` is the default, but may be [overridden](../auth-sdk/#configuration) +by the runtime environment. + + +```shell title="Initialize session using planet CLI, forcing the built-in user interactive OAuth2 login flow." +planet auth login --auth-profile planet-user +``` + + +```shell title="Initialize session using planet CLI, forcing the use of the specified service principal." +planet auth login --auth-client-id --auth-client-secret +``` + + +```shell title="Initialize session using planet CLI, forcing the use of a legacy Planet API key." +planet auth login --auth-api-key +``` + +## Using Saved Session +Using a CLI managed session is the default behavior for SDK functions. +Developing an application that uses a CLI managed session requires no additional +action by the developer. When a developer chooses to create an application +that behaves in this way, it will most often be done implicitly by relying +on SDK default behavior, but it may also be done explicitly. + +### CLI Selected Session +The default behavior of the SDK is to defer which session is loaded to CLI. + + +```python linenums="1" title="Implicitly use CLI managed login sessions, deferring session selection to the user and the CLI." +{% include 'auth-session-management/cli_managed_auth_state__implicit.py' %} +``` + +```python linenums="1" title="Explicitly use CLI managed login sessions, deferring session selection to the user and the CLI." +{% include 'auth-session-management/cli_managed_auth_state__explicit.py' %} +``` + +### Application Selected Session +Applications may be developed to always select a specific CLI managed profile. +This may be useful in cases where an application wishes to guide the user +experience towards expecting an auth session that is separate from the default +sessions used by the CLI. + +In cases where the application has access to the +user's home directory and saved sessions, forcing the use of a particular +profile circumvents the user's CLI managed preferences. + + +Note: This first example does not create the session `my-app-profile`. +This must be created either through a separate code path as show in +the [Application Managed Sessions](../auth-dev-app-managed-oauth) guide, +or by using a CLI command to copy an existing profile such as +`planet auth profile copy planet-user my-app-profile`. + +```python linenums="1" title="Use a specific session that is shared with the CLI." +{% include 'auth-session-management/cli_managed_auth_state__specific_auth_profile.py' %} +``` + + +It is also possible to force the use of the SDK's built-in OAuth2 application ID +for interactive user applications. This capability is provided for developer +convenience, primarily for smaller programs and scripts. Larger applications +developed for multiple users should +[register](../auth-dev-app-managed-oauth/#oauth2-user-client-registration) +a unique application ID. + +This second example also initiates a login and does not save session state to storage. +This means this example does not depend on the CLI, and may be considered a simple +example of an [Application Managed Session](../auth-dev-app-managed-oauth). + +```python linenums="1" title="Use the Planet SDK with an OAuth2 user session initialized by the application and utilizing the SDK's built-in OAuth2 application ID." +{% include 'auth-session-management/app_managed_auth_state__using_sdk_app_id.py' %} +``` + +--- diff --git a/docs/auth/auth-overview.md b/docs/auth/auth-overview.md new file mode 100644 index 00000000..c8148e03 --- /dev/null +++ b/docs/auth/auth-overview.md @@ -0,0 +1,126 @@ +# Client Authentication Overview + +## Introduction +All calls to Planet APIs must be authenticated. Only authorized clients may +use Planet Platform APIs. + +For general information on how to authenticate to Planet APIs, please see +the [Authentication](https://docs.planet.com/develop/authentication/) section of Planet's platform documentation. +This documentation focuses on the use of the Planet Python SDK and +[`planet`](../../cli/cli-reference) CLI. + +!!! info + Work to unify authentication practices between `api.planet.com` and `services.sentinel-hub.com` + is ongoing and being rolled out in phases over time. Documentation referring + to work in progress is marked as such 🚧. + + Of particular note is the general shift towards OAuth2 based authentication, + and a corresponding move away from Planet API keys. + +---- + +## Authentication Protocols +At the HTTP protocol level underneath the SDK, there are several distinct +ways a client may authenticate to the Planet APIs, depending on the use case. +See [Authentication Protocols](https://docs.planet.com/develop/authentication/#authentication-protocols) for a +complete discussion of when to choose a particular method. + +* **OAuth2 user access tokens** - API access as the end-user, using OAuth2 + user access tokens. This is the preferred way for user-interactive + applications to authenticate to Planet APIs. A registered client application + and a web browser are required to initialize a session. A web browser is not + required for continued operation. The SDK itself is a registered + client application that may be used for this purpose. + + Examples of applications that fall into this category include + [ArcGIS Pro](https://www.esri.com/en-us/arcgis/products/arcgis-pro/overview), + [QGIS](https://qgis.org/), and the SDK's own [`planet`](../../cli/cli-reference) + CLI program. All Planet first-party web applications also use this method. + +* **OAuth2 M2M access tokens** (🚧 _Work in progress_) - API access as a service user, using OAuth2 + M2M access tokens. This is the new preferred way for automated processes + to authenticate to Planet APIs that must operate without a human user. + No web browser is required, but this method carries some additional + security considerations. + +* **Planet API keys** (⚠️ _Pending future deprecation_) - API access as a Planet end-user using a simple + fixed string bearer key. This is the method that has historically been + documented and recommended for developers using Planet APIs. + +### OAuth2 +OAuth2 authentication requires that the client possess an access token +in order to make API calls. Access tokens are obtained by the client from +the Planet authorization server, which is separate from the API servers, and are +presented by the client to API services to assert the client's right to make +API calls. + +Unlike Planet API keys, access tokens do not last forever for a variety of +reasons and must be regularly refreshed by the client before their expiration. +When using the Planet SDK, many of the details of obtaining and refreshing +OAuth2 access tokens will be taken care of for you. + +OAuth2 defines many different ways to obtain access tokens, and a full discussion +is beyond the scope of this SDK user guide. Please refer to the [Resources](#resources) +below for more information. Planet broadly divides OAuth2 use cases into +user-interactive and machine-to-machine use cases, as described in this guide. + +**SDK Examples:** + +* **OAuth2 user access tokens** + * [Using the CLI (Quick start)](../auth-dev-cli-managed/#planet-auth-login-planet-user) + * [Forcing use of SDK Built-in Application ID in code (Quick start)](../auth-dev-cli-managed/#use-cli-session-force-builtin) + * [Using a custom registered application ID](../auth-dev-app-managed-oauth/#oauth2-session-for-users) +* **OAuth2 M2M access tokens** + * [Using the CLI (Quick start)](../auth-dev-cli-managed/#planet-auth-login-planet-m2m) + * [Using a M2M Access Token in code](../auth-dev-app-managed-oauth/#oauth2-session-for-service-accounts) + +!!! info + OAuth2 user access tokens currently work for all Planet APIs under both + the `api.planet.com` and `services.sentinel-hub.com` domains. + + 🚧 OAuth2 machine-to-machine (M2M) access tokens are currently available for use + with `services.sentinel-hub.com` APIs. Work to support `api.planet.com` is + ongoing. It should also be noted that at this time no API clients for + `services.sentinel-hub.com` APIs have been incorporated into this SDK. + The SDK may still be used to obtain and manage M2M access tokens to + support external applications. + +### Planet API Keys +Planet API keys are simple fixed strings that may be presented by the client +to API services to assert the client's right to access APIs. API keys are +obtained by the user from their [Account](https://www.planet.com/account) page +under the [_My Settings_](https://www.planet.com/account/#/user-settings) tab. + +**SDK Examples:** + +* **Planet API keys** + * [Using the CLI (Quick start)](../auth-dev-cli-managed/#planet-auth-login-planet-apikey) + * [Using a Planet API Key in code](../auth-dev-app-managed-apikey) + + +!!! warning + Planet API keys are being targeted for eventual deprecation in favor + of OAuth2 mechanisms for most use cases. No specific timeframe has been + set for disabling API keys, but new development should use OAuth2 + mechanisms where possible. + + Planet API keys will work for Planet APIs underneath `api.planet.com`, but + will **NOT** work for APIs underneath `services.sentinel-hub.com`. + + There is no plan for API keys to ever be supported by APIs underneath + `services.sentinel-hub.com`. + +---- + +## Resources +More information regarding Authentication to Planet APIs, OAuth2, and JWTs +may be found here: + +* [Planet Authentication](https://docs.planet.com/develop/authentication/) +* [RFC 6749 - The OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749) +* [RFC 8628 - OAuth 2.0 Device Authorization Grant](https://datatracker.ietf.org/doc/html/rfc8628) +* [RFC 7519 - JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519) +* [RFC 9068 - JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens](https://datatracker.ietf.org/doc/html/rfc9068) +* [RFC 6819 - OAuth 2.0 Threat Model and Security Considerations](https://datatracker.ietf.org/doc/html/rfc6819) + +---- diff --git a/docs/auth/auth-sdk.md b/docs/auth/auth-sdk.md new file mode 100644 index 00000000..1831a86f --- /dev/null +++ b/docs/auth/auth-sdk.md @@ -0,0 +1,133 @@ +# Authentication with the SDK + +## Overview +The [`planet.Auth`](../../python/sdk-reference/#planet.auth.Auth) class is the +main class that is responsible for managing how clients built with the SDK +authenticate to the Planet Insights Platform API services. By default, +API clients provided by the SDK will create an `Auth` instance that is connected +to login sessions managed by the [`planet auth`](../../cli/cli-reference/#auth) +CLI utility, with state saved to the `.planet.json` file and `.planet` +directory in the user's home directory. + +When applications require more control over the authentication process, +constructor methods on the [`planet.Auth`](../../python/sdk-reference/#planet.auth.Auth) +class may be used to create instances with specific configurations. +`Auth` instances may then be wrapped in [`planet.Session`](../../python/sdk-reference/#planet.http.Session) +objects so they can be attached to the +[`planet.Planet`](../../python/sdk-reference/#planet.client.Planet) synchronous +client, or various [asynchronous API clients](../../python/async-sdk-guide/) provided by the SDK. + +## Configuration + +When determining how to authenticate requests made against the Planet +APIs, the default behavior of the SDK and the Planet CLI is to load +configuration from a number of sources at runtime: + +- Highest priority is given to arguments passed to the [`Auth`](../../python/sdk-reference/#planet.auth.Auth) + class (when using the SDK) or via the command line (when using the CLI). + When saving preferences using the CLI, configuration is saved to + configuration files (below). +- Next, environment variables are checked. + Of these, `PL_API_KEY` has been used by Planet software for many years, + and is the most likely to be set in a user's environment. + The other environment variables are new to version 3 of the Planet Python SDK. + **Note**: This means that environment variables override configuration + saved by the `planet` CLI program. See [Environment Variables](#environment-variables) + below. +- Then, the configuration file `.planet.json` and files underneath + the `.planet` directory in the user's home directory are consulted. + These configuration files may be managed with the + [`planet auth profile`](../../cli/cli-reference/#profile) CLI command. +- Finally, built-in defaults will be used. + +### Environment Variables +When the SDK is not otherwise explicitly configured by an application, +or behavior is not overridden by command-line arguments, the following +environment variables will be used: + +| Variable | Description | +|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------| +| **`PL_AUTH_PROFILE`** | Specify a custom CLI managed auth client profile by name. This must name a valid CLI managed profile or an error will occur. | +| **`PL_AUTH_CLIENT_ID`** | Specify an OAuth2 M2M client ID. `PL_AUTH_CLIENT_SECRET` must also be specified, or this will be ignored. | +| **`PL_AUTH_CLIENT_SECRET`** | Specify an OAuth2 M2M client secret. `PL_AUTH_CLIENT_ID` must also be specified, or this will be ignored. | +| **`PL_AUTH_API_KEY`** | Specify a legacy Planet API key. | + +When multiple conflicting environment variables are set, `PL_AUTH_PROFILE` is +preferred over `PL_AUTH_CLIENT_ID` and `PL_AUTH_CLIENT_SECRET`, which are +preferred over `PL_AUTH_API_KEY`. + +### Reset User Configuration +The following commands may be used to clear an environment of any +previously configured settings: + +```sh title="Clear saved authentication settings" +unset PL_API_KEY +unset PL_AUTH_PROFILE +unset PL_AUTH_CLIENT_ID +unset PL_AUTH_CLIENT_SECRET +planet auth reset +``` + +## Profiles +Collectively, the configuration of the SDK to use a specific authentication +protocol (see [overview](../auth-overview#authentication-protocols)) and a +working set of session state information is termed a _profile_ by the SDK +and the CLI. Profiles are an abstraction of the SDK and the CLI, and are +not inherent to authentication to the Planet platform generally. + +The [`planet auth profile`](../../cli/cli-reference/#profile) CLI command +is provided to manage persistent profiles and sessions in the user's home +directory. These home directory persisted profiles are shared between the CLI +and applications built using the SDK. + +Applications built using the SDK may be configured to bypass home directory +profile and session storage, if this better suits the needs of the application. +See [Applicaiton Managed Sessions](../auth-dev-app-managed-oauth) for detailed +examples. + +## Sessions + +Before any calls can be made to a Planet API using the SDK, it is +necessary for the user to login and establish an authentication session. +Exactly how this should be done with the SDK depends on the +application's complexity and needs. + +In simple cases, this may be managed external to the application +by using the [`planet auth`](../../cli/cli-reference/#auth) +command-line utility. See [CLI Managed Sessions](../auth-dev-cli-managed) +for examples. + +In more complex cases, an application may need to manage the +stored session itself independent of utilities provided by the CLI. In such +cases, the application will be responsible for instantiating a `planet.Auth` +object, initiating user login, and saving the resulting session information. +Session information may contain sensitive information such as access and +refresh tokens, and must be stored securely by the application. Session +information will also be regularly updated during SDK operations, so the +application must handle callbacks to store updated session information. +See [Application Managed Sessions](../auth-dev-app-managed-oauth) +for examples. + +### Session Persistence + +Once a user login session is established using any method, the state should be +saved to secure persistent storage to allow for continued access to the Planet +platform without the need to perform the login repeatedly. If state cannot +be persisted in the application environment, the application can operate in +in-memory mode, but will be forced to create a new login session every time the +application is run. If the rate of repeated logins is too great, this may +result in throttling by the authorization service. Particular attention should +be paid to this when creating automated processes that utilize service users. + +The SDK provides the option to save session state in the user's +home directory in a way that is compatible with the CLI. +When [CLI Managed Sessions](../auth-dev-cli-managed) are used, no additional +steps should be required of the application developer. + +The SDK also provides a way for the application to provide its own secure +storage. 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`](https://planet-auth.readthedocs.io/en/latest/api-planet-auth/#planet_auth.ObjectStorageProvider) +abstract base class. + +---- diff --git a/docs/get-started/quick-start-guide.md b/docs/get-started/quick-start-guide.md index a6ae82c4..7a04b361 100644 --- a/docs/get-started/quick-start-guide.md +++ b/docs/get-started/quick-start-guide.md @@ -27,9 +27,10 @@ pip install planet ### Authentication -Use the `planet auth` CLI command to establish a user login session that will -be saved to the user's home directory. For other authentication options, see -the [Client Authentication Guide](../python/sdk-client-auth.md). +Use the [`planet auth`](../../cli/cli-reference/#auth) CLI command to establish +a user login session that will be saved to the user's home directory. This +session will be picked up by SDK library functions by default. For other +authentication options, see the [Client Authentication Guide](../auth/auth-overview.md). ```bash planet auth login diff --git a/docs/get-started/upgrading-v3.md b/docs/get-started/upgrading-v3.md index 02151a1c..bc515acf 100644 --- a/docs/get-started/upgrading-v3.md +++ b/docs/get-started/upgrading-v3.md @@ -20,7 +20,7 @@ where the use case allows for it. Users may also continue to initialize SDK and CLI sessions with their username and password, but rather than being processed by the SDK itself a browser must be invoked to complete OAuth2 client session initialization. -This new method is intended to offer a number of long term benefits, including: +This new method is intended to offer a number of long-term benefits, including: * The new method provides the SDK and the CLI with access tokens that may be used with both `api.planet.com` and `services.sentinel-hub.com` endpoints. The method @@ -31,7 +31,7 @@ This new method is intended to offer a number of long term benefits, including: * The new method is compatible with other platform enhancements currently under development by Planet's software engineering team. -For complete details on the new mechanisms, see the [Client Authentication Guide](../python/sdk-client-auth.md). +For complete details on the new mechanisms, see the [Client Authentication Guide](../auth/auth-overview.md). ### CLI Usage The [`planet auth`](../../cli/cli-reference/#auth) command has been substantially @@ -57,7 +57,7 @@ of the SDK, the following changes are the most important to note: ### Session Persistence Both version 2 and version 3 of the SDK use the `~/.planet.json` file in the user's -home directory to store user's API key. If this file is present and was configured +home directory to store the user's API key. If this file is present and was configured by version 2 of the SDK, it should continue to work. While the `~/.planet.json` file continues to be used by version 3, and version 3 @@ -71,7 +71,7 @@ command to reset all saved state should it become corrupted. When this command the old files are moved aside rather than deleted. ### SDK Session Initialization -See the [Client Authentication Guide](../python/sdk-client-auth.md) for a complete +See the [Client Authentication Guide](../auth/auth-overview.md) for a complete discussion of all options now available. Basic SDK use cases should work with no alterations. @@ -88,7 +88,7 @@ Applications may also continue to initialize the SDK with a specific API key as {% include 'auth-session-management/app_managed_auth_state__in_memory__api_key.py' %} ``` -Users developing new applications should consult the [Client Authentication Guide](../python/sdk-client-auth.md) +Users developing new applications should consult the [Client Authentication Guide](../auth/auth-overview.md) for a complete discussion of all OAuth2 based mechanisms. OAuth2 mechanisms should be preferred to the use of Planet API keys. diff --git a/docs/python/async-sdk-guide.md b/docs/python/async-sdk-guide.md index af016248..68dd0014 100644 --- a/docs/python/async-sdk-guide.md +++ b/docs/python/async-sdk-guide.md @@ -6,7 +6,7 @@ This guide is for the Planet Async SDK for Python users who want to use asynchro This guide walks you through the steps: -* **[Authenticate](#authenticate-with-planet-services)**—pass your username and password to Planet services to verify your permissions to data. +* **[Authenticate](#authenticate-with-planet-services)**—authenticate to Planet services to verify your permissions to data. * **[Create a session](#create-a-session)**—set up a context for calling on Planet servers and receiving data back. * **[Create an order](#create-an-order)**—build an orders client, send the request within the session context, and download it when it’s ready. * **[Collect and list data](#collecting-results)**—handle the potentially large number of results from a search for imagery. @@ -22,52 +22,36 @@ pip install planet ## Authenticate with Planet services -An SDK `Session` requires authentication to communicate with Planet services. This -authentication information is retrieved when a `Session` is created. By default, -a `Session` retrieves authorization key from the environment variable `PL_API_KEY` or a secret file, in that order of priority. - -The SDK provides the `auth.Auth` class for managing authentication information. -This module can be used to obtain authentication information from the username -and password with `Auth.from_login()`. Additionally, it can be created with -the API key obtained directly from the Planet account site with `Auth.from_key()`. - -Once you have provided the authentication information (in other words, the username and API key), it can be accessed by way of the `Auth.value`. The most convenient way of managing it for local use is to write it to a secret file using `Auth.write()`. For example, to obtain and store authentication information: - -Once you have provided the authentication information (in other words, the account username and password), it can be accessed by way of `Auth.value`. The most convenient way of managing it for local use is to write it to a secret file using `Auth.write()`. -It can also be accessed, for example, to store in an environment variable, such as -`Auth.value`. - -Here is an example of retrieving and storing authentication information: - -```python -# Get the user account name and password -# from the command line and environment, -# and store credentials in an Auth object -import getpass -from planet import Auth - -user = input("Username: ") -pw = getpass.getpass() -auth = Auth.from_login(user,pw) -auth.store() -``` - -The default authentication behavior of the `Session` can be modified by specifying -`Auth` explicitly using the methods `Auth.from_file()` and `Auth.from_env()`. -While `Auth.from_key()` and `Auth.from_login` can be used, it is recommended -that those functions be used in authentication initialization. Authentication -information should be stored using `Auth.store()`. - -You can customize the manner of retrieval and location to read from when retrieving the authorization information. The file and environment variable read from can be customized in the respective functions. For example, authentication can be read from a custom -environment variable, as in the following code: +An SDK `Session` requires authentication to communicate with Planet services. The +details of authentication are managed with the [`planet.Auth`](../../python/sdk-reference/#planet.auth.Auth) +class, and are configured when a `Session` is created. Default behavior +shares the responsibility of managing authentication sessions with the [`planet auth`](../../cli/cli-reference/#auth) +CLI utility, which stores authentication sessions in the user's home directory. + +The default authentication behavior of the `Session` can be modified by providing an +`Auth` instance when creating the `Session`. There are many different ways to +create an `Auth` instance, depending on the use case. See +[Client Authentication Overview](../../auth/auth-overview/) +and [Authentication with the SDK](../../auth/auth-sdk/) for more details concerning +Planet Insights Platform authentication with the SDK. For general information on +how to authenticate to Planet APIs, please see the +[Authentication](https://docs.planet.com/develop/authentication/) section of Planet's +platform documentation. + +For example, a program may wish create the `Auth` instance prior to setting up +the `Session` to guide the user towards external setup steps: ```python import asyncio -import os +import sys from planet import Auth, Session -auth = Auth.from_env('ALTERNATE_VAR') +auth = Auth.from_user_default_session() async def main(): + if not auth.is_initialized(): + print("Login required. Execute the following command:\n\n\tplanet auth login\n") + sys.exit(99) + async with Session(auth=auth) as sess: # perform operations here pass diff --git a/docs/python/sdk-client-auth.md b/docs/python/sdk-client-auth.md index a0bf32eb..fe22f517 100644 --- a/docs/python/sdk-client-auth.md +++ b/docs/python/sdk-client-auth.md @@ -1,377 +1,15 @@ -# Client Authentication Guide +# Authentication SDK Guide -## Introduction -All calls to Planet APIs must be authenticated. Only authorized clients may -use Planet Platform APIs. +For general information on how to authenticate to Planet APIs, see the +[Authentication](https://docs.planet.com/develop/authentication/) section of Planet's +Insights Platform documentation. -For general information on how to authenticate to Planet APIs, please see -the [Authentication](https://docs.planet.com/develop/authentication) section of Planet's platform documentation. +See [Client Authentication Overview](../../auth/auth-overview) for an overview +of authentication to the Planet Insights Platform that is geared towards SDK +users, and includes a discussion of authentication protocols that are under +construction and available for early access to SDK users. -!!! warning - Some statements in this guide are forward-looking. - - OAuth2 M2M tokens are currently only supported by `services.sentine-hub.com`, - and are not yet supported by `api.planet.com`. This is planned for a future date - to be announced. - - All APIs support interactive user OAuth2 access tokens, but a process for - developers to register and manage clients has not yet been made public. - We have also not yet release a way for end-users of such applications to - manage which applications have been authorized to access the platform on - their behalf. - - If you would like to develop an interactive application that uses - Planet's APIs on behalf of a logged-in user (as the `planet` CLI utility - does), please contact Planet support and work with engineering to - register your application. - ----- -## Authentication Protocols -At the API protocol level underneath the SDK, there are several distinct -ways a client may authenticate to the Planet APIs, depending on the use case: - -* **OAuth2 user access tokens** - API access as the end-user, using OAuth2 -user access tokens. This is the preferred way for user interactive -applications to authenticate to Planet APIs. A web browser is required -to initialize a session, but not required for continued operation. -* **OAuth2 M2M access tokens** - API access as a service user, using OAuth2 -M2M access tokens. This is the preferred way for automated processes -to authenticate to Planet APIs that must operate without a human user. -No web browser is required, but this method carries some additional -security considerations. -* **Planet API keys** - API access as a planet end-user using a simple -fixed string bearer key. This method is being targeted for deprecation. - -### OAuth2 -OAuth2 authentication requires that the client possesses an access token -in order to make API calls. Access tokens are obtained by the client from -the Planet authorization server that is separate from the API servers, and are -presented by the client to API services to prove the client's right to make -API calls. - -Unlike Planet API keys, access tokens do not last forever for a variety of -reasons and must be regularly refreshed by the client before their expiration. -However, clients should not refresh access tokens for every API call; clients -that misbehave in this way will be throttled by the authorization service, -potentially losing access to APIs. - -When using the Planet SDK, the many of the details of obtaining and refreshing -OAuth2 access tokens will be taken care of for you. - -Planet OAuth2 access tokens will work for all Planet APIs underneath -both the `api.planet.com` and `services.sentinel-hub.com` domains. - -Planet Access tokens conform to the JSON Web Token (JWT) specification. -Tokens may be inspected to determine their expiration time, which will be -in the `exp` claim. - -!!! note - Clients should generally treat the access tokens as opaque bearer tokens. - While JWTs are open for inspection, Planet does not guarantee the stability - of undocumented claims. Rely only on those documented here. - -More information regarding OAuth2 and JWTs may be found here: - -* [RFC 6749 - The OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749) -* [RFC 8628 - OAuth 2.0 Device Authorization Grant](https://datatracker.ietf.org/doc/html/rfc8628) -* [RFC 7519 - JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519) -* [RFC 9068 - JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens](https://datatracker.ietf.org/doc/html/rfc9068) - -#### OAuth2 Client Registration -!!! TODO - * link to docs for this process - * discuss registering a interactive client (that will access Planet - as the user) vs registering a M2M client identity (which is really - more like creating a new user) vs registering a confidential client. - discuss native vs web clients. - -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. - -### Planet API Keys -Planet API keys are simple fixed strings that may be presented by the client -to API services that assert the client's right to access APIs. API keys are -obtained by the user from their account page, and provided to the client -so that it may make API calls on the user's behalf. - -Planet API keys are simpler to use than OAuth2, but are considered less secure -in many ways. Because of this, Planet API keys are targeted for eventual -deprecation. Support for this method is maintained for continuity -while OAuth2 based methods are being rolled out across all Planet APIs and -clients. - -Planet API Keys will work for Planet APIs underneath `api.planet.com`, but -will **NOT** work for APIs underneath `services.sentinel-hub.com`. - ----- -## Authentication with the SDK - -Before any calls can be made to a Planet API using the SDK, it is -necessary for the user to login and establish an authentication session. -Exactly how this should be done with the SDK depends on the -application's complexity and needs. - -In simple cases, this may be managed external to the application -by using the [`planet auth`](../../cli/cli-reference/#auth) -command line utility. - -In more complex cases, an application may need to manage the -stored session itself independent of utilities provided by the CLI. In such -cases the application will be responsible for instantiating a `planet.Auth` -object, initiating user login, and saving the session resulting information. -Session information may contain sensitive information such as access and -refresh tokens, and must be stored securely by the application. Session -information will also be regularly updated during SDK operations, so the -application must handle keeping the saved session information up-to-date. - -Regardless of which authentication protocol is used, the SDK encapsulates -the details with -[`planet.Auth`](../sdk-reference/#planet.auth.Auth) and -[`planet.Session`](../sdk-reference/#planet.http.Session). - -#### Session State Storage - -Once a user login session is established using any method, the state should be -saved to secure persistent storage to allow for continued access to the Planet -platform without the need to perform the login repeatedly. If state cannot -be persisted in the application environment, the application can operate in -in-memory mode, and will be forced create a new login session every time the -application is run. In some cases, this may result in throttling by the -authorization service. - -By default, the SDK provides the option to save session state in the user's -home directory in a way that is compatible with the CLI. The SDK also -provides a way for the application to provide its own secure storage. -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. - -### Using `planet auth` CLI Managed Auth Session -For simple programs and scripts, it is easiest for the program to defer -session management to the [`planet auth`](../../cli/cli-reference/#auth) -CLI. This method will store session information in the user's home directory -in the `~/.planet.json` file and `~/.planet/` directory. The python SDK will -use the information saved in these locations to make API calls. - -When this approach is taken, the authentication session will be shared between -actions taken by the `planet` utility, and those taken by the programs built -using the SDK. Changes made by one will impact the behavior of the other. - -**Requirements and Limitations:** - -* The program must have read and write access to the user's home directory. -* This method requires that the end-user has access to and understands - the [`planet`](../../cli/cli-reference) CLI command needed to manage session - authentication. -* This approach should not be used on public terminals or in cases where the - user's home directory cannot be kept confidential. - -#### Initialize Session - Login -Session login can be performed using the following command. This command can -be used to initialize sessions using any of the authentication methods -discussed above, and will default to creating an OAuth2 user session. -Refer to the command's `--help` for more information. -```shell title="Initialize session using planet CLI" -planet auth login -``` - -#### Using Saved Session -Using the CLI managed session is the default behavior for SDK functions. -Developing an application that uses this session requires no additional -action by the developer. When a developer chooses to create an application -that behaves in this way, it will most often be done implicitly by relying -on SDK default behavior, but it may also be done explicitly. - -```python linenums="1" title="Implicitly use CLI managed login sessions" -{% include 'auth-session-management/cli_managed_auth_state__implicit.py' %} -``` - -```python linenums="1" title="Explicitly use CLI managed login sessions" -{% include 'auth-session-management/cli_managed_auth_state__explicit.py' %} -``` - -```python linenums="1" title="Use a specific session that is shared with the CLI" -{% include 'auth-session-management/cli_managed_auth_state__specific_auth_profile.py' %} - -``` - -### Manually Creating a Session Using Library Functions -If an application cannot or should not use a login session initiated by the -[`planet auth`](../../cli/cli-reference/#auth) CLI command, it will be -responsible for managing the process on its own, persisting session state as -needed. - -The process differs slightly for applications accessing Planet services on behalf -of a human user verses accessing Planet services using a service account. Depending -on the use case, applications may need to support one or the other or both (just -as the [`planet`](../../cli/cli-reference) CLI command supports both methods). - -#### 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. - -##### With a Local Web Browser -In environments where a local browser is available, the Planet SDK 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 is establishing 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 browse 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 - Authorization Code Flow -```python linenums="1" title="Login as a user using a local browser with in memory only state persistance" -{% include 'auth-session-management/app_managed_auth_state__in_memory__oauth_user_authcode__with_browser.py' %} -``` - -```python linenums="1" title="Login as a user using a local browser with sessions persisted on disk and shared with the CLI" -{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_authcode__with_browser.py' %} -``` - -```python linenums="1" title="Login as a user using a local browser with sessions persisted to application provided storage" -{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__oauth_user_authcode__with_browser.py' %} -``` - -##### Without a Local Web Browser -In environments where a local web browsers is not available the process above -will not work. 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 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 is establishing 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. - -###### Examples - Device Code Flow -```python linenums="1" title="Login as a user using an external browser with in memory only state persistance" -{% include 'auth-session-management/app_managed_auth_state__in_memory__oauth_user_devicecode__external_browser.py' %} -``` - -```python linenums="1" title="Login as a user using an external browser with sessions persisted on disk and shared with the CLI" -{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_devicecode__external_browser.py' %} -``` - -```python linenums="1" title="Login as a user using an external browser with sessions persisted to application provided storage" -{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__oauth_user_devicecode__external_browser.py' %} -``` - -#### 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 account 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, -than the application should still take steps to persist the session state (for -example: a command line utility run 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 considerations, discussed in -[RFC 6819 §4.4.4](https://datatracker.ietf.org/doc/html/rfc6819#section-4.4.4). -Because of these consideration, service accounts should only be used for -workflows that are independent of a controlling user. - -##### Examples - Client Credentials Flow -```python linenums="1" title="Access APIs using a service account with in memory only state persistance" -{% include 'auth-session-management/app_managed_auth_state__in_memory__oauth_m2m.py' %} -``` - -```python linenums="1" title="Access APIs using a service account with sessions persisted on disk and shared with the CLI" -{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_m2m.py' %} -``` - -```python linenums="1" title="Access APIs using a service account with sessions persisted to application provided storage" -{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__oauth_m2m.py' %} -``` - -#### Planet API Key Sessions -Legacy applications that need to continue to support Planet API keys may do so -until API keys are deprecated. This method should not be adopted for new -development. - -##### Examples - Planet API Keys - -```python linenums="1" title="Access APIs using Planet API keys in memory" -{% include 'auth-session-management/app_managed_auth_state__in_memory__api_key.py' %} -``` - -```python linenums="1" title="Access APIs using Planet API keys using the on disk file format used by older versions of the SDK" -{% include 'auth-session-management/app_managed_auth_state__on_disk_legacy__api_key.py' %} -``` - -```json linenums="1" title="Legacy API Key file" -{% include 'auth-session-management/legacy_api_key_file.json' %} -``` - -```python linenums="1" title="Access APIs using Planet API keys with CLI managed shared state on disk" -{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__api_key.py' %} -``` - -```python linenums="1" title="Access APIs using Planet API keys using legacy on disk persistance" -{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__api_key.py' %} -``` - -## OAuth2 Scopes -OAuth2 uses scopes to allow users to limit how much access clients have to the Planet -service on their behalf. - -* **`planet`** - Use this scope to request access to Planet APIs. -* **`offline_acess`** - Use this scope to request a refresh token. This may - only be requested by clients that access APIs on behalf of a user. M2M - clients may not request this scope. - - -## Environment Variables -When session information is not explicitly configured, the following environment variables -will influence the library behavior when initialized to user default preferences. - -* **`PL_AUTH_PROFILE`** - Specify a custom CLI managed auth client profile by name. -* **`PL_AUTH_CLIENT_ID`** - Specify an OAuth2 M2M client ID. -* **`PL_AUTH_CLIENT_SECRET`** - Specify an OAuth2 M2M client secret. -* **`PL_AUTH_API_KEY`** - Specify a legacy Planet API key. ----- - - -## Web Services -!!! TODO - All of the above really deals with native applications running in an - environment controlled by the end-user. The considerations - are different if the application being developed is a web service where - the end-user is not directly accessing Planet APIs. This involves - "Confidential" OAuth2 client configurations, and needs to be documented - here. +[Authentication with the SDK](../../auth/auth-sdk) provides a primer +on how to use the Planet SDK for Python to authenticate to Planet APIs. ---- diff --git a/docs/python/sdk-guide.md b/docs/python/sdk-guide.md index 413c4d96..fe26f590 100644 --- a/docs/python/sdk-guide.md +++ b/docs/python/sdk-guide.md @@ -38,11 +38,11 @@ planet auth login ``` These examples will assume you have done this, and are using the SDK's default -client authentication mechanisms. If you are not, please see the -[Client Authentication Guide](sdk-client-auth.md) for a complete discussion of +client authentication mechanisms. For more advanced use cases, see the +[Client Authentication Guide](../auth/auth-overview.md) for a complete discussion of all authentication options provided by the SDK. This includes user authentication with a web browser, service account authentication for detached -workloads, and support for legacy authentication mechanisms. +workloads using OAuth2, and support for legacy applications using Planet API keys. ### Search diff --git a/examples/auth-session-management/app_managed_auth_state__in_memory__oauth_user_authcode__with_browser.py b/examples/auth-session-management/app_managed_auth_state__in_memory__oauth_user_authcode__with_browser.py index 312d1136..a7274db9 100644 --- a/examples/auth-session-management/app_managed_auth_state__in_memory__oauth_user_authcode__with_browser.py +++ b/examples/auth-session-management/app_managed_auth_state__in_memory__oauth_user_authcode__with_browser.py @@ -1,9 +1,6 @@ import json -import logging import planet -logging.basicConfig(level=logging.CRITICAL) - def example_main(): # Create an auth context with a client ID that diff --git a/examples/auth-session-management/app_managed_auth_state__in_memory__oauth_user_devicecode__external_browser.py b/examples/auth-session-management/app_managed_auth_state__in_memory__oauth_user_devicecode__external_browser.py index 0f332cfa..087dacab 100644 --- a/examples/auth-session-management/app_managed_auth_state__in_memory__oauth_user_devicecode__external_browser.py +++ b/examples/auth-session-management/app_managed_auth_state__in_memory__oauth_user_devicecode__external_browser.py @@ -1,9 +1,6 @@ import json -import logging import planet -logging.basicConfig(level=logging.CRITICAL) - def initialize_user_session(plsdk_auth): # Example of initiating a user session where the app is 100% diff --git a/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_m2m.py b/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_m2m.py index 23b23b11..7afcf765 100644 --- a/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_m2m.py +++ b/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_m2m.py @@ -1,9 +1,6 @@ import json -import logging import planet -logging.basicConfig(level=logging.CRITICAL) - def example_main(): # Create an auth context with the client ID and secret of the service account. diff --git a/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_authcode__with_browser.py b/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_authcode__with_browser.py index 5be30978..4beeb5a2 100644 --- a/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_authcode__with_browser.py +++ b/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_authcode__with_browser.py @@ -1,9 +1,6 @@ import json -import logging import planet -logging.basicConfig(level=logging.CRITICAL) - def example_main(): # Create an auth context with a client ID that diff --git a/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_devicecode__external_browser.py b/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_devicecode__external_browser.py index d0ca115a..0b74a39d 100644 --- a/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_devicecode__external_browser.py +++ b/examples/auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_devicecode__external_browser.py @@ -1,9 +1,6 @@ import json -import logging import planet -logging.basicConfig(level=logging.CRITICAL) - def initialize_user_session(plsdk_auth): # Example of initiating a user session where the app is 100% diff --git a/examples/auth-session-management/app_managed_auth_state__on_disk_legacy__api_key.py b/examples/auth-session-management/app_managed_auth_state__on_disk_legacy__api_key.py index a1425759..7c076106 100644 --- a/examples/auth-session-management/app_managed_auth_state__on_disk_legacy__api_key.py +++ b/examples/auth-session-management/app_managed_auth_state__on_disk_legacy__api_key.py @@ -1,9 +1,6 @@ import json -import logging import planet -logging.basicConfig(level=logging.CRITICAL) - def example_main(): # Create an auth context with a Planet API key loaded from the diff --git a/examples/auth-session-management/app_managed_auth_state__using_sdk_app_id.py b/examples/auth-session-management/app_managed_auth_state__using_sdk_app_id.py new file mode 100644 index 00000000..afdc8fd9 --- /dev/null +++ b/examples/auth-session-management/app_managed_auth_state__using_sdk_app_id.py @@ -0,0 +1,29 @@ +import json +import planet + + +def example_main(): + # Load the OAuth2 user-interactive client configration that is built-into the SDK. + # This configuration is shared with the `planet` CLI command. + # When save_state_to_storage is true, sessions will be shared with the + # CLI and saved to the user's home directory. When save_state_to_storage + # is false, the state will only be persistent in memory and the + # user will need to login each time the application is run. + plsdk_auth = planet.Auth.from_profile("planet-user", + save_state_to_storage=False) + + if not plsdk_auth.is_initialized(): + plsdk_auth.user_login(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() diff --git a/examples/auth-session-management/cli_managed_auth_state__explicit.py b/examples/auth-session-management/cli_managed_auth_state__explicit.py index 2a8a68f0..2ad7b8c4 100644 --- a/examples/auth-session-management/cli_managed_auth_state__explicit.py +++ b/examples/auth-session-management/cli_managed_auth_state__explicit.py @@ -1,10 +1,7 @@ import json -import logging import planet import sys -logging.basicConfig(level=logging.CRITICAL) - def example_main(): # Explicitly load the user's auth session from disk. The user must have diff --git a/examples/auth-session-management/cli_managed_auth_state__specific_auth_profile.py b/examples/auth-session-management/cli_managed_auth_state__specific_auth_profile.py index f1583ac9..42f33431 100644 --- a/examples/auth-session-management/cli_managed_auth_state__specific_auth_profile.py +++ b/examples/auth-session-management/cli_managed_auth_state__specific_auth_profile.py @@ -1,10 +1,7 @@ import json -import logging import planet import sys -logging.basicConfig(level=logging.CRITICAL) - def example_main(): # Explicitly load the user's auth session from disk for a specific @@ -13,8 +10,7 @@ def example_main(): # must have performed a login() elsewhere prior to this example. # If this has not been done, the API calls will fail. This example # does not initialize a new session. - plsdk_auth = planet.Auth.from_profile( - profile_name="my-cli-managed-profile") + plsdk_auth = planet.Auth.from_profile(profile_name="my-app-profile") # If required, how to login depends on what is configured in the specific # profile. See other examples for login calls. diff --git a/mkdocs.yml b/mkdocs.yml index aec8349d..039dd279 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -92,6 +92,12 @@ nav: - python/sdk-client-auth.md - python/async-sdk-guide.md - python/sdk-reference.md + - "Client Authentication": + - auth/auth-overview.md + - auth/auth-sdk.md + - auth/auth-dev-cli-managed.md + - auth/auth-dev-app-managed-oauth.md + - auth/auth-dev-app-managed-apikey.md - "Resources": - resources/index.md - "Home": 'index.md' diff --git a/planet/auth.py b/planet/auth.py index 385a50f6..f7acdb11 100644 --- a/planet/auth.py +++ b/planet/auth.py @@ -50,50 +50,81 @@ def _normalize_profile_name(profile_name: str): @staticmethod def from_user_default_session() -> Auth: """ - Create authentication from user defaults. + Create authentication context from user defaults. This method should be used when an application wants to defer auth profile management to the user and the `planet auth` CLI command entirely. - Users may use the `planet auth login` command to initialize - and manage sessions. + Users may use the `planet auth login` and `planet auth profile + commands to initialize and manage sessions. Defaults take into account environment variables (highest priority), - user configuration saved to `~/.planet.json` and `~/.planet/ + user configuration saved to `~/.planet.json` and `~/.planet/` (next priority), and built-in defaults (lowest priority). This method does not support the use a custom storage provider. - The session must be initialized entirely in memory (e.g. through - environment variables), or from on disk CLI managed settings. Environment Variables: - PL_AUTH_CLIENT_ID: Specify an OAuth2 M2M client ID - PL_AUTH_CLIENT_SECRET: Specify an OAuth2 M2M client secret - PL_AUTH_API_KEY: Specify a legacy Planet API key - PL_AUTH_PROFILE: Specify a custom planet_auth library auth - client profile (Advanced use cases) + + | Variable Name | Description | + | --------------------- | ------------------------------------------------------------------ | + | PL_AUTH_CLIENT_ID | Specify an OAuth2 M2M client ID | + | PL_AUTH_CLIENT_SECRET | Specify an OAuth2 M2M client secret | + | PL_AUTH_API_KEY | Specify a legacy Planet API key | + | PL_AUTH_PROFILE | Specify a previously saved planet_auth library auth client profile | + """ return _PLAuthLibAuth(plauth=planet_auth_utils.PlanetAuthFactory. initialize_auth_client_context()) @staticmethod - def from_profile(profile_name: str) -> Auth: + def from_profile( + profile_name: str, + save_state_to_storage: bool = True, + ) -> Auth: """ - Create authentication for a user whose initialized login information - has been saved to `~/.planet.json` and `~/.planet/`. + Create authentication context from an auth session that has been + initialized and saved to `~/.planet.json` and `~/.planet/`. - A user should perform a login to initialize this session out-of-band - using the command `planet auth login`. + Users can initialize and save such a session out-of-band + using the `planet auth login` and `planet auth profile` commands. To initialize this session programmatically without the CLI, you must complete an OAuth2 user login flow with one of the login - methods. + methods on this class. The login method used must be compatible + with the specified profile. This method does not support the use a custom storage provider. + + In addition to sharing sessions with other programs through the user's + home directory, this method may also be used to load SDK built-in + client profiles. This is provided as a developer convenience. + Applications _should_ register unique client IDs with the Planet service + and use `from_oauth_user_auth_code()` or `from_oauth_user_device_code()` + to create profiles unique to the application. + At present, the following built-in profiles are available: + + | Profile Name | Description | + | ------------ | -------------------------------------------------------------------- | + | `planet-user` | User interactive OAuth2 client profile shared with the `planet` CLI. | + + Parameters: + profile_name: Named profile from which to load auth configuration + and state. This should be a name of a CLI managed profile. + save_state_to_storage: Boolean controlling whether login sessions + should be saved to storage. This nearly always should be true, + since this constructor exists to share state through storage + backed profiles. The only exception may be when using a SDK + built-in profile in an application that should not attempt to + save state to disk. """ + if not profile_name: + raise APIKeyAuthException('Profile name cannot be empty.') pl_authlib_context = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context( - auth_profile_opt=profile_name) + auth_profile_opt=profile_name, + save_token_file=save_state_to_storage, + save_profile_config=save_state_to_storage) return _PLAuthLibAuth(plauth=pl_authlib_context) # TODO: add support for confidential clients @@ -108,7 +139,7 @@ def from_oauth_user_auth_code( planet_auth.ObjectStorageProvider] = None, ) -> Auth: """ - Create authentication for the specified registered client + Create authentication context for the specified registered client application. Developers of applications must register clients with @@ -169,7 +200,7 @@ def from_oauth_user_device_code( planet_auth.ObjectStorageProvider] = None ) -> Auth: """ - Create authentication for the specified registered client + Create authentication context for the specified registered client application. Developers of applications must register clients with @@ -182,7 +213,8 @@ def from_oauth_user_device_code( This method does not perform a user login to initialize a session. If not initialized out of band using the CLI, sessions must be initialized - with the device login methods before API calls may be made. + with the device login methods `device_user_login_initiate()` and + `device_user_login_complete()` before API calls may be made. Parameters: client_id: Client ID @@ -348,17 +380,17 @@ def from_env(variable_name: typing.Optional[str] = None) -> Auth: Reads the `PL_API_KEY` environment variable Pending Deprecation: - This method is pending deprecation. The method `from_defaults()` + This method is pending deprecation. The method `from_user_default_session()` considers environment variables and configuration files through the planet_auth and planet_auth_utils libraries, and works with - legacy API keys, OAuth2 M2M clients, OAuth2 interactive profiles. + legacy API keys, OAuth2 M2M clients, and OAuth2 interactive profiles. This method should be used in most cases as a replacement. Parameters: variable_name: Alternate environment variable. """ warnings.warn( - "from_env() will be deprecated. Use from_defaults() in most" + "from_env() will be deprecated. Use from_user_default_session() in most" " cases, which will consider both environment variables and user" " configuration files.", PendingDeprecationWarning) @@ -370,17 +402,6 @@ def from_env(variable_name: typing.Optional[str] = None) -> Auth: def from_login(email: str, password: str, base_url: typing.Optional[str] = None) -> Auth: - """Create authentication from login email and password. - - Note: To keep your password secure, the use of `getpass` is - recommended. - - Parameters: - email: Planet account email address. - password: Planet account password. - base_url: The base URL to use. Defaults to production - authentication API base url. - """ raise DeprecationWarning( "Auth.from_login() has been deprecated. Use Auth.from_user_session()." ) diff --git a/planet/cli/auth.py b/planet/cli/auth.py index c3ef0b1e..a789ec7a 100644 --- a/planet/cli/auth.py +++ b/planet/cli/auth.py @@ -32,8 +32,8 @@ def cmd_auth(ctx): planet_auth_utils.cmd_plauth_login, [ # Hide client ID / client secret until we are ready for OAuth M2M - "auth_client_id", - "auth_client_secret", + # "auth_client_id", + # "auth_client_secret", # Hide audience and organization. They are useful for plauth as a # generic OAuth client, but within the planet SDK we only care about # the built-ins. @@ -69,4 +69,6 @@ def cmd_auth_profile(ctx): cmd_auth_profile.add_command(name="show", cmd=planet_auth_utils.cmd_profile_show) cmd_auth_profile.add_command(name="set", cmd=planet_auth_utils.cmd_profile_set) +cmd_auth_profile.add_command(name="copy", + cmd=planet_auth_utils.cmd_profile_copy) cmd_auth.add_command(cmd_auth_profile) diff --git a/planet/cli/cli.py b/planet/cli/cli.py index 0c900bcd..2b63cd03 100644 --- a/planet/cli/cli.py +++ b/planet/cli/cli.py @@ -70,12 +70,16 @@ def _configure_cli_auth_ctx(ctx, auth_client_secret, auth_api_key): # planet-auth library Auth context type + # Embedded click commands imported from planet_auth_utils expect + # this in the 'AUTH' context field. ctx.obj[ 'AUTH'] = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context( auth_profile_opt=auth_profile, auth_client_id_opt=auth_client_id, auth_client_secret_opt=auth_client_secret, - auth_api_key_opt=auth_api_key) + auth_api_key_opt=auth_api_key, + use_env=True, + use_configfile=True) # planet SDK Auth context type ctx.obj['PLSDK_AUTH'] = planet.Auth._from_plauth( diff --git a/pyproject.toml b/pyproject.toml index dd97e18a..2fe2ec1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ dependencies = [ "pyjwt>=2.1", "tqdm>=4.56", "typing-extensions", - "planet-auth==2.0.11b1746663950", + "planet-auth==2.0.11b1748473964", ] readme = "README.md" requires-python = ">=3.9"