-
Notifications
You must be signed in to change notification settings - Fork 168
Authzen Interop Writeup
Purpose:
Demonstrate how Gluu Flex acts as an Identity Provider (IdP) that calls a compliant AuthZen PDP during token issuance, enriching the issued token with claims returned by the PDP.
Interop scenario reference:
The demo aligns with the AuthZen IdP interop scenario, where the IdP uses AuthZen’s Search API during the authentication flow to decide which claims a user should be granted, then embeds those claims into the ID token. Sample Data
What this demo shows:
- Gluu Flex extensibility (custom scripts)
- How Flex makes an AuthZen-compliant call
- How PDP results drive claim enrichment
- How the enriched token is consumed by a demo RP
-
User → Flex Server
User initiates an OIDC login against Gluu. -
Gluu Authentication Flow
A custom Gluu script executes after authentication but before token issuance:- Extracts user identity
- Calls AuthZen PDP Search API
- Receives allowed resources/claims
- Inserts them into JWT
-
Token Issuance
Gluu issues an ID token containing the enriched claims. -
Demo App / RP
A relying party processes the token and displays the enriched claims.
Gluu supports custom “person authentication scripts.”
Steps (via Admin UI):
- Navigate to Scripts
- Create an Update Token script
- Insert the AuthZen integration logic
This script:
- Extracts authenticated user context and retrieves username
- Builds AuthZen-style Search API request
- Sends request to the PDP
- Parses PDP response
- Maps the
resultarray of the response to therecordclaim - Injects mapped claims into token
In Auth Server → Clients:
- Create a client for the demo RP
- Configure redirect URIs (
https://sts.authzen-interop.net/idp/jans/callback) - Add scopes (
openid,profile,role) - Enable appropriate grant and response types (
authorization_code) - Go to Client Scripts and associate the
Update Tokenfield with the script created in the previous step
- Obtain PDP endpoint URL for the vendor participating
- Insert the URL into the script via config variable
You may use the AuthZen interop demo application
- User logs into the RP → redirected to Flex
- Flex authenticates the user
- AuthZen script triggers
- Flex requests resources from PDP
- PDP returns resource/claim list
- Flex enriches token and issues it
- RP decodes the token and displays enriched claims
- Intro: “Gluu is acting as an AuthZen-enabled IdP. During login, it queries a PDP to determine which claims to include.”
-
Show Script: Display the custom AuthZen script configuration in Admin UI (search for
authzen_interopunder Update Token) - Login: Run the login flow in the demo RP.
- Token Inspection: Decode the JWT to show enriched claims.
- PDP Swap: Switch to a different vendor PDP and repeat — demonstrating interoperability.
Custom script:
from io.jans.model.custom.script.type.token import UpdateTokenType
from io.jans.service.cdi.util import CdiUtil
from io.jans.as.server.service import SessionIdService
from io.jans.as.server.model.config import ConfigurationFactory
from io.jans.as.server.service import ClientService
from io.jans.as.server.service.net import HttpService
from java.nio.charset import Charset
from org.json import JSONObject
import json
class UpdateToken(UpdateTokenType):
def __init__(self, currentTimeMillis):
self.currentTimeMillis = currentTimeMillis
def init(self, customScript, configurationAttributes):
print "AuthZen interop script. Initializing ..."
if (not configurationAttributes.containsKey("PDP_URL")):
print "AuthZen interop script. Property PDP_URL is not specified"
return False
self.PDP_URL = configurationAttributes.get("PDP_URL").getValue2()
httpService = CdiUtil.bean(HttpService)
self.http_client = httpService.getHttpsClient()
print "AuthZen interop script. Initialized successfully"
return True
def destroy(self, configurationAttributes):
print "AuthZen interop script. Destroying ..."
print "AuthZen interop script. Destroyed successfully"
return True
def getApiVersion(self):
return 11
def modifyIdToken(self, jsonWebResponse, context):
print "Authzen Interop script. Modify idToken: %s" % jsonWebResponse
sessionIdService = CdiUtil.bean(SessionIdService)
sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn())
uid = sessionId.getSessionAttributes().get("auth_user")
url = self.PDP_URL + "/access/v1/search/resource"
body = {
"subject": {
"type": "user",
"id": uid
},
"action": {
"name": "delete"
},
"resource": {
"type": "record"
}
}
body_json = json.dumps(body)
request_headers = { "Content-type" : "application/json; charset=UTF-8", "Accept" : "application/json" }
try:
httpService = CdiUtil.bean(HttpService)
# call demo app's PDP search endpoint
http_service_response = httpService.executePost(self.http_client, url, None, request_headers, body_json)
http_response = http_service_response.getHttpResponse()
response_bytes = httpService.getResponseContent(http_response)
response_string = httpService.convertEntityToString(response_bytes, Charset.forName("UTF-8"))
if not httpService.isResponseStastusCodeOk(http_response):
print "Authzen Interop Script. PDP returned %s" % str(http_response.getStatusLine().getStatusCode())
return False
json_response = JSONObject(response_string)
httpService.consume(http_response)
http_service_response.closeConnection()
except:
print "Authzen Interop Script. Exception: %s ", sys.exc_info()[1]
return False
# parse results array into record claim
jsonWebResponse.getClaims().setClaim("record", json_response.getJSONArray("results"))
print "Update token script. After modify idToken: %s" % jsonWebResponse
return True
def modifyRefreshToken(self, refreshToken, context):
return True
def modifyAccessToken(self, accessToken, context):
return True
def getRefreshTokenLifetimeInSeconds(self, context):
return 0
def getIdTokenLifetimeInSeconds(self, context):
return 0
def getAccessTokenLifetimeInSeconds(self, context):
return 0