This is the second post in a series on OSB, JWT and OWSM. In the first post, I explained how to implement JWT validation using the standard OWSM configuration.
Introduction
However, there’s a fundamental limitation to that approach: you can’t create fine-grained access control — for example, allowing token X to access service Y, but not service Z. As long as the token is valid, it grants access to all secured services using the same policy.
That’s why I wanted to create a custom policy — to add fine-grained access control to individual services. At first, things looked promising. Oracle provides a good example of a custom policy that limits access based on IP address — you can apply it to a specific proxy and define allowed IPs, and can be easily attached to a SOAP/WSDL proxy service.
However, when I tried attaching this policy to a REST or ANY/XML proxy, I ran into this error:
[OSB-398128] One of the Web service policy attached is not allowed on service TEST/TestProxy because the service binding does not support it.
For that reason, I opened a Service Request (SR) with Oracle, explaining that OWSM custom policies don’t work on REST and ANY/XML proxies. Oracle Support was responsive and helpful — and they did find an answer. Unfortunately, it wasn’t the one I was hoping for: They pointed to an outstanding enhancement request. Their response confirmed that attaching custom policies to REST or ANY_XML proxies isn’t supported.
Luckily, I kept working on the JIRA ticket while the SR was open.
Spoiler alert: I got it working!
In this blog post, I’ll walk you through how I got it to work — step by step — and how you can implement your own custom policies and attach them to REST and ANY/XML services in OSB.
Oh, and this isn’t just about JWT. This workaround will likely work for any custom policy you want to attach to a REST or ANY/XML proxy.
Disclaimer
This solution was tested and validated on Oracle Service Bus 12c (12.2.1.4). At the time of writing, I haven’t tested it on 14c yet — that work is in progress. I’ll update this post (or write a follow-up) once I’ve confirmed compatibility with 14c. The example code has been cleaned and modified to avoid exposing proprietary details.
It serves as a proof of concept, not a production-ready implementation — you’ll need to adapt it to your own environment.
Important: This approach is NOT officially supported by Oracle. Use it at your own risk and discretion.
I got lucky?
Honestly, if I have seen the enhancement request beforehand, I probably wouldn’t even have picked up the ticket. But I didn’t know. I was just being stubborn, curious, and — let’s be honest — a bit lucky. Sometimes not knowing something is “impossible” is the best way to get it done.
The key to making this work was something surprisingly simple:
You can’t export internal Oracle policies directly. But you can clone them. And once you’ve cloned an internal policy, you’re free to download it, see its contents and modify it. By adding a reference to your own custom Java class and giving the policy a new name, it suddenly becomes attachable to REST services — and it works.
My proof of concept was based on just that:
- I exported a standard internal policy as-is. ( oracle/http_jwt_token_service_policy )
- I modified a few properties
- I added a single element to trigger my Java class.
- That was it. That small change made the difference. And it executed as expected.
Step 1. Export cloned policy
First, open <yourhost:yourport/em>
and navigate to Weblogic Domain -> Web Services -> WSM Policies
Select the oracle/http_jwt_token_service_policy
and click Create Like in the top bar.
Give your copy a meaningful name — adjust the name, display name, and description as needed.
Next, locate the copy you just created, click Export, and save the resulting ZIP file somewhere on your local drive.
Step 2. Modify the policy XML
Locate the ZIP file and extract its contents. Inside, you’ll find a META-INF
directory, and within that, a policies
directory. That’s where your exported policy lives.
Start by renaming policy.xml
to something more meaningful — for example: proofofconcept_policy.xml
, or whatever fits your naming convention.
Then open the file in a text editor such as Notepad++.
Next, remove both “Logging” sections — they serve no purpose in your custom policy and can be safely deleted.
There are several parts in the file that need to be modified:
1. Update the <wsp:Policy>
attributes:
-
orawsp:description
-
orawsp:Name
-
orawsp:displayName
-
wsu:Id
Make sure these values are unique to avoid conflicts with existing policies.
2. Update the <orasp:http-jwt-security>
section:
-
ns0:category
→ usesecurity/authorization
(Important: You can’t attach two identical policies to the same proxy.) -
ns0:name
→ give your policy a distinct name
3. Link to your custom Java class:
Inside the <orawsp:bindings>
block, add:
<orawsp:Implementation>nl.test.owsmpolicy.jwt.SomeCustomExecutor</orawsp:Implementation>
Now save your changed file. Make sure that the XML file is valid!
4. Check the orawsp:provides
block:
Make sure it includes the following bindings:
orawsp:provides=" {http://docs.oasis-open.org/ns/opencsa/sca/200912}authentication, {http://docs.oasis-open.org/ns/opencsa/sca/200912}clientAuthentication, {http://docs.oasis-open.org/ns/opencsa/sca/200912}clientAuthentication.transport, {http://schemas.oracle.com/ws/2006/01/policy}SOAP_HTTP, {http://schemas.oracle.com/ws/2006/01/policy}REST_HTTP, {http://schemas.oracle.com/ws/2006/01/policy}URL, {http://schemas.oracle.com/ws/2006/01/policy}token.http.jwt"
Explanation:
- SOAP_HTTP: binding for WSDL/SOAP
- REST_HTTP: binding for REST
- URL: binding for ANY/XML
5. Save and validate
Once you’ve made your changes, save the file and make sure the XML is valid. A simple typo or missing namespace can break the policy deployment.
Summary
My guess is that the <orasp:jwt-token-policy>
element is the key to all of this. It behaves differently than a <orasp:genericAssertion>
. You can’t attach a genericAssertion
to a REST or ANY/XML proxy — it’s simply not allowed.
However, the combination of jwt-token-policy
and a reference to custom Java code does work. And that’s the key: because the Java class takes precedence over the internal/default behavior, it effectively overrides Oracle’s limitation.
This subtle difference is what makes the workaround possible.
Step 3. Import the custom policy
Before you can import your newly created policy, you need to package it into a specific ZIP structure.
The required format is:
- META_INF
- policies
- proofofconcept_policy.xml
- policies
Create this simple folder structure and place your modified policy.xml
inside the policies
directory.
Then open <yourhost:yourport/em>
again and navigate to: WebLogic Domain → Web Services → WSM Policies
Click Import, select your ZIP file, and complete the import.
After importing, you’ll see a confirmation message indicating that the policy was successfully imported.
Once the import is complete, scroll down the list of policies. Your newly imported policy should be listed near the bottom, using the name you provided earlier.
This is what the newly imported policy looks like. The green checkmark confirms that it’s active and ready to be attached.
Step 4. Attach the policy
Now it’s time to attach the policy to a REST proxy service.
In this example, I’ll be using the sbconsole.
Open <yourhost:yourport/sbconsole>
and locate the proxy service you want to modify.
Create a new session and navigate to the Policy tab inside your Proxy Service definition.
Click Add Policy — a popup will open.
Navigate to the last page of the list, where you’ll find your newly imported policy. Select it and click Attach.
Press OK to confirm the policy attachment.
You can now see that the policy has been added. Click the Save icon to persist your changes.
Normally, at this point, you would get the known error I mentioned earlier — but this time, it won’t appear.
That’s it — the OSB part is done.
Java implementation
Now create a simple Java project. Oracle’s IPAssertion example provides a good starting point — just make sure your class extends AssertionExecutor
. The only JAR that is needed as a dependency is: com.oracle.webservices.fmw.client.jar. This file can be found somewhere in your weblogic installation directory.
For this proof of concept, I created a minimal Java project. A screenshot of the code is shown below:
The code is executed in three possible stages: request, response, and error. In our case, we only want to run it during the request stage.
This code does a few simple things:
-
It fetches all policy properties.
(Note:debug.location
isn’t shown in the screenshot, but the static method defaults it to/var/opt/log/weblogic
.) -
It writes the line
"This is a test"
to a log file.
Now simply create a plain JAR file — name it something like TestPoc.jar
— and copy it to your osb_domain/lib
directory.
For good measure, restart your OSB domain after placing the file.
Now simply call your REST endpoint and check the log file — either in /var/opt/log/weblogic
or in the directory you configured.
If everything went well, you should see the line:
This is a test
That’s your proof: the custom policy was triggered, and your Java code was executed. See screenshot below:
It works!
The custom policy is attached to a REST proxy, the Java code is executed, and the proof is in the log.
Minor glitch
There is one minor glitch in this approach.
The IResult
object has a setWSMException()
method, and the WSMException
class provides several constructors to choose from. In theory, setting a WSMException
should allow you to influence the HTTP response code returned by the proxy. Without it, the policy result will be either:
-
HTTP 200 (OK), or
-
HTTP 500 (Internal Server Error)
I suspect that when a WSMException
is properly set, a more appropriate HTTP 401 (Unauthorized) could be returned. However — and here’s the problem — no matter which constructor I try, the instantiation of the WSMException
always fails.
Not the line that sets it, but the line that creates it.
The most likely explanation is that the loophole used here — cloning and reusing an internal policy structure — isn’t designed to handle a WSMException
being returned from a custom implementation.
Another possibility is that it has to do with the specific binding type of the proxy service (REST vs. SOAP or ANY_XML).
For now, I’m not entirely sure what’s causing it.
If you find the solution, please let me know — I’d love to update this workaround with a cleaner way to return proper HTTP status codes.
Summary
Even though Oracle WSM does not officially support attaching custom policies to REST or ANY/XML proxies, there is a fully working workaround using an existing policy structure.
My guess is that the custom Java class is picked up earlier — and executed before the default internal logic of that policy kicks in.
I hope this code helps you get custom policies working in your own project. It took me quite some time to figure this out — hopefully, this article will help you save that time.
And again, I can’t stress this enough:
Important: this approach is not officially supported by Oracle. Use it at your own risk and discretion.
If it helped you, feel free to share it — or drop me a note.
Files
Brain out!