ArcGIS Enterprise OAuth helper with per user token cache.
Project description
age-oauth
age-oauth is a convenience package which makes it easier for script users to interact with an ArcGIS Enterprise by simplifying the OAuth 2.0 process, and eliminating the need (and bad security practice) of having to store username/passwords in your scripts.
Install
Minimal (fine if you're installing into an ArcGIS Pro conda environment, e.g. arcgispro-py3 or clones):
python -m pip install age-oauth
Full dependencies (installs arcgis and arcgis-mapping):
python -m pip install "age-oauth[full]"
Usage
Step 0: Prereqs
This README presumes you already have the needed permissions to have created a valid set of OAuth 2.0 app/developer tokens on a target ArcGIS Enterprise system. You should have ready:
- the Portal root URL (e.g.,
https://somwhere.com/portal) - OAuth2 client ID
- OAuth2 client secret
- The app's Redirect URI set to
urn:ietf:wg:oauth:2.0:oob(Esri's default out of band URI)
Step 1: Add a Portal to your local store
Run:
age-oauth connections add
You'll be prompted for the following:
Connection label: <short, plain language name to identify portal, no spaces>
Portal URL: https://somewhere.com/portal
Verify SSL: false, true, or path to custom CA cert
OAuth Client ID: <your client ID>
OAuth Client Secret: <your client secret>
When it's done, you'll see:
[OK] Created connection: my_portal
Step 1.a: Add the Portal non-interactively
You can also add the Portal non-interactively. Assuming a PowerShell environment:
age-oauth connections add `
--label "Prod" `
--portal "https://somewhere.com/portal" `
--verify-ssl false `
--client-id "client_id_value" `
--client-secret "client_secret_value"
Step 2: Authenticate / Onboard
Now we'll authenticate for the first time (interactively, from CLI)
age-oauth login --connection my_portal
You'll see:
Opening browser for ArcGIS Enterprise OAuth sign-in...
A browser will open to your Portal login screen. You need to:
- Sign in
- Portal displays an authorization code
- Copy the code
- Paste it back into the terminal where you are being prompted for it
age-oauth will swap the authorization code for an access token, a refresh token, and an expiration timestamp. This is then securely stored in your user profile. If all is successful, you'll see:
New access_token acquired! Expires in: 1:00:00
Token is for user: your.username
Step 3: Confirm authentication
To verify, do:
age-oauth whoami --connection my_portal
You should see:
your.username
Your OAuth credentials are now onboarded and you can proceed to use it programmatically.
Step 4: Programmatic use
Now, you can use it in Python:
from age_oauth import get_gis
gis = get_gis(connection="my_portal")
# verify
print(gis.properties.portalName)
print(gis.users.me.username)
No username/passwords, no tokens, no PKI decryption in your scripts. age-oauth handles negotiation and refresh automatically.
Storage
Portal profiles are stored per-user under your OS home (profile) directory. Nothing is stored globally:
Windows
%APPDATA%\age_oauth\
Each connection contains the following:
connections/
my_portal_<uuid>/
.env # OAuth settings and tokens
meta.json # metadata
Why does this exist?
It is tempting to write scripts like:
gis = GIS("https://my-portal.com/portal", "username", "password")
# or
gis = GIS("https://my-portal.com/portal", token="abcdef12345abcdef12345abcdef...")
Or do any number of other sketchy things like -
- usernames/passwords in
.pyor sidecar files - decrypt PKI client certs into unencrypted, plain-text
.pemfiles - copy static access tokens from a browser
- paste your API keys right into scripts
All of these practices create both security and maintainability problems, with compromise at worst and increased technical debt at best. In a secure setting, we're going for:
- credentials that can be revoked
- clear ownership of access
- clear expiration policy
- centralized control
This is exactly what the OAuth workflow gives you when it's properly used. You have to authenticate via Portal. A short-lived access_token is issued (expiration and rotation policy). A longer-lived refresh_token can renew access automatically once the "app" is authorized. These tokens can then be revoked via Portal (centralization). So while nothing's perfect, this workflow aligns much better with typical enterprise security expectations.
age-oauth is designed to make the more secure way also the more convenient way. It will give you:
- A per-user connection store to manage multiple Portal connections
- OAuth client configuration per Portal
- Automatic token refresh
- A simple, injected
arcgis.gis.GISclass object instantiated viaage_oauth.get_gis()
But why not just use API keys?
ArcGIS Enterprise developer API keys are useful, but they have short lifetimes and require manual renewal. This introduces friction into automations you may need to run under your human-user persona. OAuth supports refresh tokens that can be reused indefinitely to get new access tokens. Going through the up-front setup to establish OAuth client access pays off in the long run by giving you way cleaner scripts that are:
- more easily maintained,
- can be passed around without fear of accidentally leaking credentials,
- better aligned with enterprise security and therefore help everyone sleep better at night.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file age_oauth-0.1.7.tar.gz.
File metadata
- Download URL: age_oauth-0.1.7.tar.gz
- Upload date:
- Size: 31.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7813fe96a7079bded81dd0cd14ec2e0d8a1b5c6821cc2acc8d7529cfe7d0a45d
|
|
| MD5 |
27b5715243e923a8a64c035fffee7747
|
|
| BLAKE2b-256 |
051fc29d7d464217bdb14261f310cc0f1426348216138e4693a00b699ae89c8a
|
Provenance
The following attestation bundles were made for age_oauth-0.1.7.tar.gz:
Publisher:
publish.yml on vovchykbratyk/age_oauth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
age_oauth-0.1.7.tar.gz -
Subject digest:
7813fe96a7079bded81dd0cd14ec2e0d8a1b5c6821cc2acc8d7529cfe7d0a45d - Sigstore transparency entry: 992170198
- Sigstore integration time:
-
Permalink:
vovchykbratyk/age_oauth@4e03065644633be518f5e552e730ea8109bc103e -
Branch / Tag:
refs/tags/v0.1.7 - Owner: https://github.com/vovchykbratyk
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4e03065644633be518f5e552e730ea8109bc103e -
Trigger Event:
release
-
Statement type:
File details
Details for the file age_oauth-0.1.7-py3-none-any.whl.
File metadata
- Download URL: age_oauth-0.1.7-py3-none-any.whl
- Upload date:
- Size: 29.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc4386c63c3ed5a4a1a6281f5294192f94d341c85539eb5d2dab2acecfc8c1af
|
|
| MD5 |
b4e385c5e4de3cdfc70a9bd3d0b99132
|
|
| BLAKE2b-256 |
4cf47357b00a0502479ecaee74423801e93952158dc216e7eab7a9d2c9771f4b
|
Provenance
The following attestation bundles were made for age_oauth-0.1.7-py3-none-any.whl:
Publisher:
publish.yml on vovchykbratyk/age_oauth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
age_oauth-0.1.7-py3-none-any.whl -
Subject digest:
cc4386c63c3ed5a4a1a6281f5294192f94d341c85539eb5d2dab2acecfc8c1af - Sigstore transparency entry: 992170200
- Sigstore integration time:
-
Permalink:
vovchykbratyk/age_oauth@4e03065644633be518f5e552e730ea8109bc103e -
Branch / Tag:
refs/tags/v0.1.7 - Owner: https://github.com/vovchykbratyk
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4e03065644633be518f5e552e730ea8109bc103e -
Trigger Event:
release
-
Statement type: