Authentication API#
The shared auth contract. A provider that needs credentials exposes a <Provider>Auth / <Provider>Credentials
pair in its own auth.py with environment-variable fallbacks, and raises AuthenticationError on failure.
For which provider needs what, see Supported providers; for a worked example of supplying credentials, see Authentication examples.
AbstractAuth#
earthlens.base.AbstractAuth
#
Bases: ABC, Generic[CredentialsT]
Blueprint for every backend's auth class.
Concrete subclasses bind a credentials type (the CredentialsT
type parameter) and implement two methods:
configure— perform whatever one-time setup the backend needs (callee.Initialize, write~/.cdsapirc, fetch an OAuth bearer, etc.). Must be idempotent: calling it afteris_authenticatedreturnsTrueis a no-op.is_authenticated— returnTruewhen the in-process state has working credentials and the next download call will succeed without re-authenticating.
The class is a context manager: with FooAuth(creds) as auth:
enters by calling configure and exits by calling close. The
default close does nothing because most backends configure
their SDK globally; subclasses that genuinely hold a closeable
resource (e.g. an HTTP session, a boto3 client) override
close to release it.
Attributes:
| Name | Type | Description |
|---|---|---|
_creds |
The credentials value object passed at
construction. Stored verbatim so subclasses can read
individual fields ( |
Examples:
- A minimal concrete subclass that flips an internal flag:
>>> from pydantic import BaseModel, SecretStr >>> from earthlens.base import AbstractAuth >>> class _Creds(BaseModel): ... token: SecretStr >>> class _Auth(AbstractAuth[_Creds]): ... def __init__(self, creds): ... super().__init__(creds) ... self._authed = False ... def configure(self): ... if self.is_authenticated(): ... return ... self._authed = True ... def is_authenticated(self): ... return self._authed >>> auth = _Auth(_Creds(token="abc")) >>> auth.is_authenticated() False >>> auth.configure() >>> auth.is_authenticated() True - The context-manager form configures on enter:
>>> from pydantic import BaseModel, SecretStr >>> from earthlens.base import AbstractAuth >>> class _Creds(BaseModel): ... token: SecretStr >>> class _Auth(AbstractAuth[_Creds]): ... def __init__(self, creds): ... super().__init__(creds) ... self._authed = False ... def configure(self): ... self._authed = True ... def is_authenticated(self): ... return self._authed >>> with _Auth(_Creds(token="x")) as auth: ... auth.is_authenticated() True
Source code in libs/core/src/earthlens/base/auth.py
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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 | |
__init__(credentials)
#
Store the credentials value object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
credentials
|
CredentialsT
|
A frozen / validated value object holding the
secrets the backend needs (service-account email + key
path, CDS URL + API key, EDL username + password, …).
Type-parameterised on the concrete subclass so
|
required |
Source code in libs/core/src/earthlens/base/auth.py
close()
#
Release any resource held by :meth:configure.
Default: no-op. Backends whose configure() opens a
long-lived HTTP session, boto3 client, or background thread
override this to close it. Most backends configure their SDK
globally and have nothing to release here.
Source code in libs/core/src/earthlens/base/auth.py
configure()
abstractmethod
#
Perform the one-time setup so subsequent calls work without re-auth.
Subclasses implement this to (e.g.) call ee.Initialize,
write a credentials file, or mint an OAuth bearer. Must be
idempotent: a second call after :meth:is_authenticated
returns True is a no-op (typical implementation is an
early-return guarded by if self.is_authenticated(): return).
Raises:
| Type | Description |
|---|---|
AuthenticationError
|
When the credentials are missing/invalid or the backend rejects them. |
Source code in libs/core/src/earthlens/base/auth.py
is_authenticated()
#
Return True when the in-process state has working credentials.
Cheap predicate — must not call the network. Used by
:meth:configure for idempotency and by callers that want to
skip a redundant setup pass.
The default reports whether :meth:mark_configured has run, which is
the "did configure() succeed?" flag the majority of the auth classes
each declared by hand. Override it when the real answer lives elsewhere
— an SDK's own session object (asf), a token expiry, or a backend whose
credentials are always present (ghsl, worldpop return True).
Source code in libs/core/src/earthlens/base/auth.py
mark_configured()
#
Record that :meth:configure completed, for the default predicate.
Call this at the end of a successful configure() so the inherited
:meth:is_authenticated starts returning True and the next
configure() short-circuits.
Source code in libs/core/src/earthlens/base/auth.py
AuthenticationError#
earthlens.base.AuthenticationError
#
Bases: Exception
Raised when a backend cannot establish an authenticated session.
Subclasses re-raise this with backend-specific context (missing
~/.cdsapirc, unregistered Earth Engine project, expired CDSE
token, missing Earthdata Login). Every backend's auth class
catches the underlying SDK / HTTP exception and wraps it with
an actionable message — never propagates a raw
cdsapi.api.Exception or ee.EEException to the user.
The class is intentionally a flat Exception subclass and not
ConnectionError because half the failure modes are not
network errors (no credentials at all, malformed key file,
misconfigured project IAM). Callers should catch
AuthenticationError directly rather than its causes.
Examples:
- The error preserves its constructor message:
- Catch every backend's auth failure with one clause:
Source code in libs/core/src/earthlens/base/auth.py
S3 credentials#
Used by the two backends that resolve AWS credentials through this helper — amazon-s3 (ERA5 and the other
public buckets) and dem (Copernicus DEM). The other bucket-backed backends open their clients directly.
earthlens.base.S3Auth
#
Bases: AbstractAuth[S3Credentials]
Build an unsigned (or profile-signed) boto3 S3 client lazily.
Implements the :class:~earthlens.base.AbstractAuth contract for
public AWS Open-Data buckets. configure() constructs the client on
first use (importing boto3 lazily so the package imports without
the [s3] extra); is_authenticated() reports whether the client
exists; :meth:client is the accessor the backend's fetch step
calls.
Because the target buckets are public, "authenticated" simply means "a client has been built" — there is no token to mint or expire.
Examples:
- The client is not built until
configure()runs:
Source code in libs/core/src/earthlens/base/s3.py
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 148 149 150 151 152 153 154 155 156 157 158 | |
__init__(credentials=None)
#
Store credentials and reset the (lazily built) client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
credentials
|
S3Credentials | None
|
The :class: |
None
|
Source code in libs/core/src/earthlens/base/s3.py
client()
#
Return the S3 client, building it on first access.
Returns:
| Type | Description |
|---|---|
Any
|
The configured |
configure()
#
Build the boto3 S3 client if it does not exist yet.
Idempotent: returns immediately once :meth:is_authenticated
is True. Imports boto3 / botocore lazily so importing the
package without the [s3] extra does not fail.
Raises:
| Type | Description |
|---|---|
ImportError
|
When the |
Source code in libs/core/src/earthlens/base/s3.py
earthlens.base.S3Credentials
#
Bases: BaseModel
Credentials for the AWS S3 backend.
The seeded datasets are all public, so the default (all fields
unset) yields an unsigned client. Set aws_profile to sign requests
with a named profile from the local AWS configuration — needed only
for signed / requester-pays buckets, which are out of the first-cut
scope.
Attributes:
| Name | Type | Description |
|---|---|---|
aws_profile |
str | None
|
Name of a profile in |
signed |
bool
|
Force a signed client from the default credential chain (without naming a profile) — used for requester-pays buckets. |
region |
str | None
|
AWS region to build the client in ( |
Examples:
- The default is unsigned (no profile):