You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The current Devportal authentication model is primarily browser-oriented and depends on federated login through an external IdP. This works well for interactive web sessions, but it does not provide a clean non-interactive authentication model for CLI usage.
This creates a gap for CLI and CI/CD usage because:
Devportal does not provide a native REST API to generate a JWT token for a user.
CLI users cannot complete the browser-based federated login flow in non-interactive environments.
CI/CD pipelines need a stable authentication mechanism that supports RBAC and least-privilege access.
A single shared master API key is not suitable for user-bound or role-bound automation.
As a result, Devportal REST APIs cannot be cleanly consumed by CLI tools or automation pipelines today.
Motivation
Devportal needs first-class CLI support for automation use cases such as:
CI/CD pipeline integration for Devportal REST APIs
Automation of application, subscription, and key management tasks
Controlled non-interactive access with proper RBAC
The CLI authentication model should allow an authorized API key to invoke Devportal APIs.
Goals
Provide CLI-friendly authentication for Devportal REST APIs.
Support file-based users, roles, and scopes for API key generation.
Generate user-bound API keys with expiration.
Store only hashed API keys in the database.
Validate API key scopes when Devportal scope validation is enabled.
Preserve existing browser login and federated authentication behavior.
Proposed Solution
Introduce a file-based user, role, and scope configuration for Devportal automation users.
These file-based users can authenticate to a new CLI API key generation endpoint using Basic authentication. Once authenticated, they can request an API key with a subset of their assigned scopes.
The Basic authentication support introduced in this proposal is intended only as a bootstrap mechanism for generating scoped API keys for internal automation use cases. This API key generation capability is not exposed through the Devportal UI and is not intended to be a publicly available end-user feature. It is designed for controlled internal use, such as CI/CD pipelines, internal CLI tooling, and automation workflows where browser-based federated login is not practical.
Therefore, Basic authorization is introduced only for the CLI API key generation endpoint. Once the API key is generated, subsequent CLI or automation requests must use the generated scoped API key instead of Basic authorization.
The generated API key can then be used to invoke Devportal REST APIs. If scope validation is enabled, the API key scopes are validated against the scope required by the target endpoint.
This proposal does not replace the current federated browser login flow. Instead, it adds a parallel non-interactive bootstrap mechanism for automation.
API Changes
New endpoint
POST /devportal/organizations/{orgId}/cli-api-keys/generate
This endpoint support Basic authorization. Authorization: Basic <base64(username:password)>
Requested scopes are not a subset of the caller’s assigned scopes
Does not have the valid scopes
400 Bad Request
invalid validDuration
missing name
missing scopes when scope validation is enabled
Configuration Changes
New File-based user management config
Introduce a new file: user-mgt.json
This file defines automation users, roles, scopes & scope mapping if the user wants define their own scopes but needs to map to the scopes used in Devportal.
The initial implementation will keep the existing route-level scopes (admin, dev) unchanged. A scopeMappings section will be introduced in user-mgt.json to map those route-level scopes to file-based fine-grained scopes. This allows the generated API keys to carry more descriptive scopes while remaining compatible with the current route protection model.
flowchart LR
A["Client sends API key generation request"] --> B["Read Basic authorization header"]
B --> C["Decode username and password"]
C --> D["Load user-mgt.json"]
D --> E{"User exists?"}
E -- "No" --> X["Reject with 401 Unauthorized"]
E -- "Yes" --> F{"Password valid?"}
F -- "No" --> X
F -- "Yes" --> G{"User allowed for orgId?"}
G -- "No" --> Y["Reject with 403 Forbidden"]
G -- "Yes" --> H["Resolve scopes from user's roles"]
H --> I{"Scope validation enabled?"}
I -- "No" --> J["Use empty scope set"]
I -- "Yes" --> K{"Requested scopes subset of assigned scopes?"}
K -- "No" --> Y
K -- "Yes" --> L["Approve requested scopes"]
J --> M["Generate Key, Hash & Persist"]
L --> M
M --> N["Return raw API key once"]
Loading
API Key Persistance
The raw API Key never be stored.
Only hash will be stored: HMAC-SHA256(raw_api_key, masterApiKeySecret)
Database Model
Column
Description
API_KEY_ID
Public key identifier extracted from API key
ORG_ID
Organization binding
USER_ID
File-based user id or federated user id
NAME
API key display name
KEY_HASH
HMAC hash of the raw API key
SCOPES
Space-separated approved scopes
STATUS
ACTIVE, REVOKED, or EXPIRED
CREATED_AT
Created timestamp
EXPIRED_AT
Expiry timestamp
API Key Validation Flow
flowchart LR
A["Client invokes Devportal REST API"] --> B{"API key header available?"}
B -- "No" --> C["Continue existing web session or bearer token authentication"]
B -- "Yes" --> D{"API key equals master API key?"}
D -- "Yes" --> E["Authenticate as internal/system API key caller"]
E --> Z["Continue request"]
D -- "No" --> F["Parse generated API key"]
F --> G{"Format valid?"}
G -- "No" --> X["Reject with 401 Unauthorized"]
G -- "Yes" --> H["Extract key_id"]
H --> I["Load API key metadata from DB by key_id"]
I --> J{"Key record found?"}
J -- "No" --> X
J -- "Yes" --> K{"Status ACTIVE?"}
K -- "No" --> X
K -- "Yes" --> L{"Key expired?"}
L -- "Yes" --> M["Update DB status to EXPIRED"]
M --> N["Reject with 401 API key expired"]
L -- "No" --> O["Generate hash from received API key using master secret"]
O --> P{"Hash matches DB hash?"}
P -- "No" --> X
P -- "Yes" --> Q{"API key belongs to requested organization?"}
Q -- "No" --> R["Reject with 403 Forbidden"]
Q -- "Yes" --> S{"Scope validation enabled?"}
S -- "No" --> T["Set request user context from DB user_id"]
S -- "Yes" --> U{"Stored scopes match required endpoint scope?"}
U -- "No" --> R
U -- "Yes" --> T
T --> Z
Loading
Error Handling
Scenario
Response
Invalid Basic credentials
401 Unauthorized
Requested scopes exceed assigned scopes
403 Forbidden
Invalid API key format
401 Unauthorized
API key not found
401 Unauthorized
API key revoked
401 Unauthorized
API key expired
401 Unauthorized with explicit expired message
API key organization mismatch
403 Forbidden
API key missing required scope
403 Forbidden
Security Considerations
Basic authentication must be accepted only over HTTPS.
Basic authentication should be used only for API key generation, not general Devportal API access.
The Basic-authenticated API key generation endpoint is an internal-only capability and should not be exposed as a public UI feature.
Generated API keys should be used for internal automation scenarios such as CI/CD and CLI workflows.
user-mgt.json must store password hashes, not plaintext passwords.
The raw generated API key must be returned only once.
The raw generated API key must never be stored in the database or logs.
File permissions for user-mgt.json should be restricted.
Invalid user-mgt.json should fail fast during startup or feature initialization.
API keys should always have an expiry.
The master API key should remain an internal operational credential and should not be used as the normal CLI authentication path.
Backward Compatibility
This proposal is additive.
Existing behavior remains unchanged for:
Browser-based federated login
Existing Devportal UI sessions
Existing Devportal functionalities performed through Devportal
Existing master API key behavior
Future Improvements
Add fine-grained route scopes in devportalRoute which replaces broad admin / dev route scopes with endpoint-specific scopes like dp:api:create, dp:application:view etc.
Add API key list endpoint.
Add API key revoke endpoint.
Add LAST_USED_AT to API key metadata.
Add audit logs for API key usage.
Add support for loading file-based users from mounted Kubernetes secrets/mounted configs.
Add config validation for user-mgt.json at startup.
Conclusion
This proposal introduces a practical CLI authentication model for Devportal without changing the existing browser-based federated login flow.
By adding file-based automation users, role-to-scope mapping, and scoped generated API keys, Devportal can support CI/CD and CLI use cases with RBAC, expiry, and secure key storage.
The generated API key model also aligns with the existing Devportal implementation direction: API keys are user-bound, organization-bound, stored only as hashes, and validated against scopes when Devportal scope validation is enabled.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Problem
The current Devportal authentication model is primarily browser-oriented and depends on federated login through an external IdP. This works well for interactive web sessions, but it does not provide a clean non-interactive authentication model for CLI usage.
This creates a gap for CLI and CI/CD usage because:
As a result, Devportal REST APIs cannot be cleanly consumed by CLI tools or automation pipelines today.
Motivation
Devportal needs first-class CLI support for automation use cases such as:
The CLI authentication model should allow an authorized API key to invoke Devportal APIs.
Goals
Proposed Solution
Introduce a file-based user, role, and scope configuration for Devportal automation users.
These file-based users can authenticate to a new CLI API key generation endpoint using Basic authentication. Once authenticated, they can request an API key with a subset of their assigned scopes.
The Basic authentication support introduced in this proposal is intended only as a bootstrap mechanism for generating scoped API keys for internal automation use cases. This API key generation capability is not exposed through the Devportal UI and is not intended to be a publicly available end-user feature. It is designed for controlled internal use, such as CI/CD pipelines, internal CLI tooling, and automation workflows where browser-based federated login is not practical.
Therefore, Basic authorization is introduced only for the CLI API key generation endpoint. Once the API key is generated, subsequent CLI or automation requests must use the generated scoped API key instead of Basic authorization.
The generated API key can then be used to invoke Devportal REST APIs. If scope validation is enabled, the API key scopes are validated against the scope required by the target endpoint.
This proposal does not replace the current federated browser login flow. Instead, it adds a parallel non-interactive bootstrap mechanism for automation.
API Changes
New endpoint
This endpoint support Basic authorization.
Authorization: Basic <base64(username:password)>Request Body
{ "name": "admin-key-for-cli", "validDuration": 36000, "scopes": ["dp:dev", "dp:admin"] }Example Request
Example Response
{ "apiKey": "dpak_v1_3139b689-c7eb-4873-ac1a-e3174b160de3_Hg_f7uR1YyR1cUxQnRDOLJSHDPKfTkQl5bIkZnRq7OM", "apiKeyId": "3139b689-c7eb-4873-ac1a-e3174b160de3", "name": "admin-key-for-cli", "validDuration": 36000, "scopes": "dp:dev dp:admin", "expiredAt": "2026-04-24T18:48:24.475Z" }Error Behavior
401 Unauthorized403 Forbidden400 Bad RequestvalidDurationnamescopeswhen scope validation is enabledConfiguration Changes
New File-based user management config
Introduce a new file:
user-mgt.jsonThis file defines automation users, roles, scopes & scope mapping if the user wants define their own scopes but needs to map to the scopes used in Devportal.
The initial implementation will keep the existing route-level scopes (
admin,dev) unchanged. AscopeMappingssection will be introduced inuser-mgt.jsonto map those route-level scopes to file-based fine-grained scopes. This allows the generated API keys to carry more descriptive scopes while remaining compatible with the current route protection model.Example
user-mgt.json{ "users": [ { "id": "ci-admin", "username": "ci-admin", "passwordHash": "$2b$12$P4mY3r...snipped...", "roles": ["devportal-admin"], "organization": ["Prime"] }, { "id": "ci-developer", "username": "ci-developer", "passwordHash": "$2b$12$Hf82k...snipped...", "roles": ["devportal-developer"], "organizations": ["Prime"] } ], "roles": { "developer": ["dp:keygen", "dp:dev"], "admin": ["dp:keygen", "dp:dev", "dp:admin"] } }API Key Generation Flow
flowchart LR A["Client sends API key generation request"] --> B["Read Basic authorization header"] B --> C["Decode username and password"] C --> D["Load user-mgt.json"] D --> E{"User exists?"} E -- "No" --> X["Reject with 401 Unauthorized"] E -- "Yes" --> F{"Password valid?"} F -- "No" --> X F -- "Yes" --> G{"User allowed for orgId?"} G -- "No" --> Y["Reject with 403 Forbidden"] G -- "Yes" --> H["Resolve scopes from user's roles"] H --> I{"Scope validation enabled?"} I -- "No" --> J["Use empty scope set"] I -- "Yes" --> K{"Requested scopes subset of assigned scopes?"} K -- "No" --> Y K -- "Yes" --> L["Approve requested scopes"] J --> M["Generate Key, Hash & Persist"] L --> M M --> N["Return raw API key once"]API Key Persistance
HMAC-SHA256(raw_api_key, masterApiKeySecret)Database Model
API_KEY_IDORG_IDUSER_IDNAMEKEY_HASHSCOPESSTATUSACTIVE,REVOKED, orEXPIREDCREATED_ATEXPIRED_ATAPI Key Validation Flow
flowchart LR A["Client invokes Devportal REST API"] --> B{"API key header available?"} B -- "No" --> C["Continue existing web session or bearer token authentication"] B -- "Yes" --> D{"API key equals master API key?"} D -- "Yes" --> E["Authenticate as internal/system API key caller"] E --> Z["Continue request"] D -- "No" --> F["Parse generated API key"] F --> G{"Format valid?"} G -- "No" --> X["Reject with 401 Unauthorized"] G -- "Yes" --> H["Extract key_id"] H --> I["Load API key metadata from DB by key_id"] I --> J{"Key record found?"} J -- "No" --> X J -- "Yes" --> K{"Status ACTIVE?"} K -- "No" --> X K -- "Yes" --> L{"Key expired?"} L -- "Yes" --> M["Update DB status to EXPIRED"] M --> N["Reject with 401 API key expired"] L -- "No" --> O["Generate hash from received API key using master secret"] O --> P{"Hash matches DB hash?"} P -- "No" --> X P -- "Yes" --> Q{"API key belongs to requested organization?"} Q -- "No" --> R["Reject with 403 Forbidden"] Q -- "Yes" --> S{"Scope validation enabled?"} S -- "No" --> T["Set request user context from DB user_id"] S -- "Yes" --> U{"Stored scopes match required endpoint scope?"} U -- "No" --> R U -- "Yes" --> T T --> ZError Handling
401 Unauthorized403 Forbidden401 Unauthorized401 Unauthorized401 Unauthorized401 Unauthorizedwith explicit expired message403 Forbidden403 ForbiddenSecurity Considerations
HTTPS.user-mgt.jsonmust store password hashes, not plaintext passwords.user-mgt.jsonshould fail fast during startup or feature initialization.Backward Compatibility
This proposal is additive.
Existing behavior remains unchanged for:
Future Improvements
devportalRoutewhich replaces broadadmin/devroute scopes with endpoint-specific scopes likedp:api:create,dp:application:viewetc.LAST_USED_ATto API key metadata.user-mgt.jsonat startup.Conclusion
This proposal introduces a practical CLI authentication model for Devportal without changing the existing browser-based federated login flow.
By adding file-based automation users, role-to-scope mapping, and scoped generated API keys, Devportal can support CI/CD and CLI use cases with RBAC, expiry, and secure key storage.
The generated API key model also aligns with the existing Devportal implementation direction: API keys are user-bound, organization-bound, stored only as hashes, and validated against scopes when Devportal scope validation is enabled.
Beta Was this translation helpful? Give feedback.
All reactions