Use OAuth2 to protect API calls #134
Replies: 2 comments 2 replies
-
Beta Was this translation helpful? Give feedback.
-
|
OpenIDM (v7.0.3-SNAPSHOT) already ships with built-in OAuth2 and OpenID Connect (OIDC) authentication modules in ArchitectureRecommended OAuth2 Flow for Headless / Pure-API UseFor 100% API usage with no browser interaction, use the OAuth2 Client Credentials Grant (RFC 6749 §4.4): POST /oauth2/token
grant_type=client_credentials
&client_id=<id>
&client_secret=<secret>
&scope=<scopes>
→ {"access_token": "...", "token_type": "Bearer", "expires_in": 3600}The client then calls OpenIDM with: Step-by-Step Implementation PlanPhase 1 — Set Up the OAuth2 Authorization ServerChoose an AS. The existing code uses a userinfo endpoint for token validation, so any standards-compliant AS works:
Configuration steps:
Phase 2 — Configure OpenIDM Authentication ModuleEdit Option A: OAuth2 (userinfo-based token validation)Use this when the AS is NOT OpenID Connect or you want explicit control over the userinfo endpoint call. {
"serverAuthContext": {
"sessionModule": {
"name": "JWT_SESSION",
"properties": {
"keyAlias": "&{openidm.https.keystore.cert.alias}",
"privateKeyPassword": "&{openidm.keystore.password}",
"keystoreType": "&{openidm.keystore.type}",
"keystoreFile": "&{openidm.keystore.location}",
"keystorePassword": "&{openidm.keystore.password}",
"maxTokenLifeMinutes": "120",
"tokenIdleTimeMinutes": "30",
"sessionOnly": true,
"isHttpOnly": true
}
},
"authModules": [
{
"name": "OAUTH",
"properties": {
"authTokenHeader": "Authorization",
"authResolverHeader": "X-OAuth-Provider",
"resolvers": [
{
"name": "my-as",
"type": "OAUTH",
"userinfo_endpoint": "https://as.example.com/oauth2/userinfo",
"authenticationId": "sub",
"client_id": "openidm-resource-server",
"client_secret": "secret"
}
],
"queryOnResource": "managed/user",
"propertyMapping": {
"authenticationId": "oauthSubject",
"userRoles": "authzRoles"
},
"defaultUserRoles": ["openidm-authorized"],
"augmentSecurityContext": {
"type": "text/javascript",
"source": "require('auth/customAuthz').setProtectedAttributes(security)"
}
},
"enabled": true
},
{
"name": "INTERNAL_USER",
"properties": {
"queryId": "credential-internaluser-query",
"queryOnResource": "repo/internal/user",
"propertyMapping": {
"authenticationId": "username",
"userCredential": "password",
"userRoles": "roles"
},
"defaultUserRoles": []
},
"enabled": true
}
]
}
}How the OAUTH module works (from source code):
Option B: OpenID Connect (OIDC, with auto-discovery)Preferred when the AS supports OIDC (Keycloak, ForgeRock AM, Okta, Azure AD, etc.). This uses the {
"name": "OPENID_CONNECT",
"properties": {
"resolvers": [
{
"name": "my-oidc-provider",
"type": "OPENID_CONNECT",
"well-known": "https://as.example.com/.well-known/openid-configuration",
"client_id": "openidm-client",
"client_secret": "secret",
"scope": ["openid", "profile", "email"],
"authenticationId": "sub",
"enabled": true
}
],
"queryOnResource": "managed/user",
"openIdConnectHeader": "authToken",
"propertyMapping": {
"authenticationId": "oauthSubject",
"userRoles": "authzRoles"
},
"defaultUserRoles": ["openidm-authorized"],
"augmentSecurityContext": {
"type": "text/javascript",
"source": "require('auth/customAuthz').setProtectedAttributes(security)"
}
},
"enabled": true
}Phase 3 — Extend the Managed User SchemaThe managed user schema ( Add a field to the managed user object in {
"name": "oauthSubject",
"type": "string",
"title": "OAuth Subject",
"viewable": false,
"searchable": true,
"userEditable": false
}Also add a query to "credential-oauth-query": {
"query": "SELECT * FROM ${unquotedtable} WHERE oauthSubject = ${uid}",
"table": "managed_user",
"useType": "managed/user"
}
Phase 4 — Create Managed User Accounts for API ClientsEach OAuth2 API client (or human user) needs a corresponding managed user entry in OpenIDM with:
Create via API: curl -X POST https://openidm.example.com/openidm/managed/user \
-H "Content-Type: application/json" \
-H "X-OpenIDM-Username: openidm-admin" \
-H "X-OpenIDM-Password: openidm-admin" \
-d '{
"userName": "api-client-1",
"oauthSubject": "client-credentials-sub-from-as",
"authzRoles": [
{ "_ref": "repo/internal/role/openidm-admin" }
]
}'
Phase 5 — Role-Based AuthorizationOpenIDM's built-in roles control what operations are allowed on each resource:
Recommended approach for API clients:
Phase 6 — API Call Flow (End-to-End)Once configured, the API client flow is: # Step 1: Get an access token from the AS
TOKEN=$(curl -s -X POST https://as.example.com/oauth2/token \
-d "grant_type=client_credentials" \
-d "client_id=my-api-client" \
-d "client_secret=my-secret" \
-d "scope=openid" \
| jq -r .access_token)
# Step 2: Call OpenIDM API with the Bearer token
# (also send the provider header so OpenIDM knows which resolver to use)
curl -X GET https://openidm.example.com/openidm/managed/user \
-H "Authorization: Bearer $TOKEN" \
-H "X-OAuth-Provider: my-as"
# Step 3: Create a user
curl -X POST https://openidm.example.com/openidm/managed/user \
-H "Authorization: Bearer $TOKEN" \
-H "X-OAuth-Provider: my-as" \
-H "Content-Type: application/json" \
-d '{
"userName": "newuser",
"givenName": "New",
"sn": "User",
"mail": "newuser@example.com",
"password": "Passw0rd!"
}'
# Step 4: List roles
curl -X GET "https://openidm.example.com/openidm/managed/role?_queryFilter=true" \
-H "Authorization: Bearer $TOKEN" \
-H "X-OAuth-Provider: my-as"Phase 7 — Optional: JWT Introspection for Better PerformanceThe current Options to mitigate:
Phase 8 — Disable Unused Authentication ModulesFor pure OAuth2 API access with no UI, disable the modules that are no longer needed to reduce the attack surface: { "name": "STATIC_USER", "enabled": false },
{ "name": "MANAGED_USER", "enabled": false }
Configuration File Checklist
Key Source Files for Reference
|
Beta Was this translation helpful? Give feedback.



Uh oh!
There was an error while loading. Please reload this page.
-
We are willing to use OpenIDM with a100% API use, for user creation and life-cycle and role management. But our customer would like to use OAuth2 to authenticate and authorize the API calls.
Would it be possible to add this feature for authentication or authorization ?
Beta Was this translation helpful? Give feedback.
All reactions