Authentication#
PyDPlus supports two connection types:
legacyoauth
For new integrations, OAuth (Private Key JWT) is recommended.
Connection Type Resolution#
When connection_type is not explicitly set, PyDPlus resolves it in this order:
Complete OAuth credentials ->
oauthComplete legacy credentials ->
legacyFallback default ->
oauth
You can always override with connection_type="legacy" or connection_type="oauth".
Legacy Authentication#
Legacy auth requires:
legacy_access_idprivate key material (
private_keypath or key material from helper/env)
Example:
from pydplus import PyDPlus
pydp = PyDPlus(
connection_type="legacy",
base_admin_url="https://example-company.access.securid.com",
legacy_access_id="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
private_key="/path/to/legacy-private-key.pem",
)
OAuth Authentication (Admin API)#
OAuth (Private Key JWT) requires:
oauth_client_idoauth_private_key(path to.jwk) oroauth_private_key_jwk(inline JWK)issuer_url(oauth_issuer_urlargument,connection_info["oauth"]["issuer_url"], or inferred from base URLs)oauth_scope(required;+-delimited, space-delimited, comma-delimited, or iterable values)Optional:
oauth_api_type(authby default,adminsupported)
Token endpoint defaults to: {issuer_url}/token
When requesting tokens, PyDPlus sends scopes to /oauth/token as a space-delimited value and sets
Content-Type: application/x-www-form-urlencoded; charset=UTF-8.
Argument-Based Example#
from pydplus import PyDPlus, constants as const
pydp = PyDPlus(
connection_type="oauth",
base_admin_url="https://example-company.access.securid.com",
oauth_client_id="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
oauth_private_key="/path/to/oauth-private-key.jwk",
oauth_scope=[
const.OAUTH_SCOPES.USER_READ,
const.OAUTH_SCOPES.USER_MANAGE,
],
)
Explicit Issuer URL Example#
from pydplus import PyDPlus
pydp = PyDPlus(
connection_type="oauth",
base_admin_url="https://example-company.access.securid.com",
oauth_issuer_url="https://example-company.auth.securid.com/oauth",
oauth_client_id="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
oauth_private_key="/path/to/oauth-private-key.jwk",
oauth_scope="rsa.user.read+rsa.user.manage",
)
Helper File Example#
{
"connection_type": "oauth",
"base_urls": {
"admin": "https://example-company.access.securid.com"
},
"connection": {
"oauth": {
"issuer_url": "https://example-company.auth.securid.com/oauth",
"client_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"scope": "rsa.user.read+rsa.user.manage",
"scope_preset": "user_read_only",
"grant_type": "Client Credentials",
"client_authentication": "Private Key JWT",
"private_key_path": "/path/to/keys",
"private_key_file": "oauth-private-key.jwk"
}
}
}
Environment Variable Example#
PYDPLUS_CONNECTION_TYPE=oauth
PYDPLUS_ADMIN_BASE_URL=https://example-company.access.securid.com
PYDPLUS_OAUTH_ISSUER_URL=https://example-company.auth.securid.com/oauth
PYDPLUS_OAUTH_CLIENT_ID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
PYDPLUS_OAUTH_SCOPE=rsa.user.read+rsa.user.manage
PYDPLUS_OAUTH_SCOPE_PRESET=user_read_only
PYDPLUS_OAUTH_PRIVATE_KEY_FILE=oauth-private-key.jwk
PYDPLUS_OAUTH_PRIVATE_KEY_PATH=/path/to/keys
The canonical environment-variable names are available from const.ENV_VARIABLES, for example
const.ENV_VARIABLES.OAUTH_SCOPE and const.ENV_VARIABLES.OAUTH_SCOPE_PRESET.
OAuth Scope Strategies#
Use one of these patterns based on how your team manages permissions. For official permission descriptions, see RSA’s OAuth 2.0-based permissions reference.
1) Configure default scopes in RSA Cloud Administration Console#
In the OAuth client configuration, set the default permissions your integration should use. This gives your tenant-side configuration a stable baseline for permissions.
In PyDPlus, still provide oauth_scope (directly, helper file, or environment variable) so token requests are explicit,
repeatable, and validated before requests are made.
2) Define scopes explicitly (manual or constants)#
You can pass raw scope strings:
oauth_scope = "rsa.user.read+rsa.user.manage"
Or define a reusable constant-style variable with typed scope values from const.OAUTH_SCOPES:
from pydplus import constants as const
OAUTH_SCOPE = [
const.OAUTH_SCOPES.USER_READ,
const.OAUTH_SCOPES.USER_MANAGE,
]
3) Use OAuth scope presets#
Presets are named bundles of scopes passed via oauth_scope_preset (argument),
connection.oauth.scope_preset (helper setting), or PYDPLUS_OAUTH_SCOPE_PRESET (environment variable).
Supported preset names:
all,admin,authagent,audit,authenticator,fido,group,report,userall_read_only,agent_read_only,authenticator_read_only,fido_read_onlygroup_read_only,report_read_only,user_read_only
Preset behavior:
Presets are additive and merge with explicit
oauth_scopevalues.Duplicate scopes are removed.
Invalid preset names are ignored (with warning logs).
Final scope values are normalized internally and submitted to
/oauth/tokenas space-delimited values.
Example:
from pydplus import PyDPlus, constants as const
pydp = PyDPlus(
connection_type="oauth",
base_admin_url="https://example-company.access.securid.com",
oauth_client_id="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
oauth_private_key="/path/to/oauth-private-key.jwk",
oauth_scope=const.OAUTH_SCOPES.USER_MANAGE,
oauth_scope_preset=("user_read_only", "group_read_only"),
)
Token Refresh Behavior#
For OAuth Admin API requests:
PyDPlus caches access-token metadata in memory.
It refreshes the token when expired or near-expiry.
If an Admin API call returns
401, PyDPlus forces one token refresh and retries once.
Additional Notes#
Current OAuth support in PyDPlus is scoped to Administration API usage.
Client Credentialsandclient_credentialsare both accepted.Private Key JWTandprivate_key_jwtare both accepted.OAuth issuer inference defaults to the Authentication base URL (
authmode).When only
base_admin_urlis provided and it matches*.access.*, PyDPlus attempts to inferbase_auth_url.Use
oauth_api_type="admin"to force issuer inference frombase_admin_url.
OAuth 403 Troubleshooting#
If token requests fail with 403 Forbidden at /oauth/token:
Verify the configured token issuer host for your tenant.
Verify
oauth_scopecontains one or more valid, enabled permissions for that OAuth client.Set
oauth_issuer_urldirectly from the tenant UI issuer value when available.If you rely on inferred URLs, provide both
base_admin_urlandbase_auth_urlexplicitly.