Forum Discussion
APM Oauth AS Opaque Token Introspection
This is not real easy, but it is possible. There are two issues to contend with:
1- The built-in OAuth response cannot be modified directly inside of the configuration because the introspect response is hard-coded.
2- iRules cannot be applied directly to an APM virtual to modify its own self-response (such as logon pages, SAML, OAuth, etc). You can work around this by removing the clientSSL profile from the APM virtual and use an intremediate virtual server. You can think of it a little like "self SSL offload", but instead of using a pool, you use the iRule "virtual" command to switch the switch the flow to the APM VS. Then you can modify the response payload. This is the same issue faced in this old SAML DevCentral question:
So basically, you:
- Remove the clientSSL profile from your APM OAuth AS virtual and change its IP address to another value.
- Create another virtual with the old IP of the APM Oauth AS using the clientSSL profile.
- Customize (the regex in the HTTP_RESPONSE_DATA event and the name of the OAuth virtual), then apply the below iRule. You could change the code here to do whatever you want, though you won't have any access to the APM data (ACCESS::session and friends) from the intermediate virtual because it has no access profile, by design.
- Watch the APM and LTM logs while testing to correct any errors: tail -f /var/log/ltm /var/log/apm
when RULE_INIT {
# Set below value to be the name of your OAuth AS virtual server
# After testing, remove or comment out all the log statements below to avoid clutter
set static::virtual_OAuth_server "/Common/my_oauth_as.app/my_oauth_as_vs"
}
when HTTP_REQUEST {
log local0. "[HTTP::host] [HTTP::method] [HTTP::uri]"
set uri [HTTP::uri]
set method [HTTP::method]
if {$method equals "POST" and $uri equals "/f5-oauth2/v1/introspect"} {
set is_introspect 1
} else {
log local0. "Not an introspect request"
}
virtual $static::virtual_OAuth_server
}
when HTTP_RESPONSE {
log local0. "response"
if { [info exists "is_introspect"] } {
if { [HTTP::header value Content-Length] <= 1048576 } {
set content_length [HTTP::header value Content-Length]
} else {
set content_length 1048576
}
if { $content_length > 0 } {
HTTP::collect $content_length
log local0. "response content collected: $content_length"
} else {
log local0. "cannot collect the content, length: $content_length"
}
}
}
when HTTP_RESPONSE_DATA {
log local0. "response data"
if { [info exists "is_introspect"] } {
# Put a regex below that represents the replacement you want to apply to APM's introspection response
# Any normal TCL string manipulation can be applied here
regsub "Common" [HTTP::payload] "Common-Replaced" fixeddata
log "Replacing payload with fixed data."
HTTP::payload replace 0 $content_length $fixeddata
HTTP::release
}
}
Thank you for the detailed response. I appreciate it. I may have to resort to this if the RS cannot parse it out. I also included the username as a scope name with the %{session.logon.last.username} as the value. Maybe they can pull that out to match the user. Thanks again.
- Lucas_ThompsonJan 19, 2023Employee
No problem, glad to help. It's a complicated issue. APM is designed to support multi-tenancy so there are a lot of areas where there are seemingly unnecessary things (like "/Common") prepended to object names.
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com