I’ll be trying to post several times a week during these first couple of weeks to get some content going. A blog without posts is, well… basically just a placeholder, right? And I’m also trying to stay true to one of the words in the subtitle: commitment. I started this blog for a reason, after all.
So, back on the topic of the day.
In my line of work I do a lot with Oracle SOA/Middleware and Oracle Service Bus (OSB) and its related products. And because security is always an issue, making your software more secure is always a priority. An option is to secure your flows with JWT tokens handed out by a third party product. Handling this can be done with Oracle Web Services Manager, or OWSM for short. OWSM is part of the Oracle SOA/Middleware software stack, so it should be quite easy to use, right?
The biggest problem is documentation, and not in the way you think. Oracle is very good at documenting their products — so good, in fact, that finding what you actually need becomes almost impossible. So the next step is to look for others who’ve run into the same problem and use their experience as a reference. We found this blog: https://planetofsolutions.wordpress.com/2020/04/22/how-to-validate-oauth2-token-in-oracle-service-bus/
The biggest problem with using blog posts is that the original author has the context how to interpret the text and the images used. And that context is exactly what made my work a lot harder. So, in this post, I’ll try to clarify all the difficult parts — and hopefully not step into the same context trap.
It boils down to these two steps.
- Attach an OWSM policy to your OSB .proxy ( oracle/http_jwt_token_service_policy )
- Configure OWSM to verify the integrity of the JWT token that is sent as an HTTP Authorization header in a request to a OSB proxy
Step 1 is the easy part, step 2 is where the configuration nightmare begins when you don’t know exactly what you’re doing.
The secret lies in understanding what OWSM actually does before you even start configuring it. Once you know what’s happening under the hood, it becomes much easier to explain where it needs to be configured. And even more important: how those different parts of the configuration interact with each other!
JWT
A JSON Web Token (JWT) consists of three distinct parts.
- Header
- Payload
- Signature
For the purpose of this blog post, parts 3 and 2 are the most important. And yes — I’ll explain in a minute why I’m listing part 3 before part 2.
Part 1, is the token valid?
This is where part 3, the signature, of the token comes into play. The very first thing OWSM needs to do is verify that the signature is valid. A JWT is signed using a private key, and to verify it, OWSM needs the public certificate — or more precisely, the entire public certificate chain — to be imported and available.
Part 2, is the issuer trusted?
Great — the signature is valid. Now what? This is where part 2, the payload, comes into play. OWSM somehow needs to know whether the issuer of the JWT token can actually be trusted.
This is typically done by validating the CN (Common Name) or DN (Distinguished Name) from the public certificate used to sign the token. And this is where things can start to get a little confusing… But don’t worry — I’ll get back to this in more detail soon.
Part 3, is the token expired?
At this point, OWSM starts looking into the payload itself. The first field it checks is the "exp"
claim.
This field contains the expiration time of the token, expressed in Unix Epoch time — the number of seconds since January 1, 1970. If the current time is greater than this value, the token is considered expired and will be rejected.
Part 4, is the audience trusted
OWSM will now check the "aud"
field inside the payload.
This field tells you who the token is intended for. In other words: “This token was issued specifically for application X.” OWSM (or any secure service) can be configured to check whether the "aud"
value matches the expected identifier of the service. If it doesn’t match, the token is considered invalid — even if the signature is correct and the token hasn’t expired.
This is a useful way to prevent token misuse — for example, if someone tries to use a token meant for Service A to access Service B.
But there’s a huge catch with this.
(See the note at the bottom of this blog post.)
It means we somehow need to maintain a list of trusted audiences somewhere in the OWSM configuration — and that’s where things start to get tricky.
Part 5, subject check
And this is where Oracle deviates from the standard.
According to the JWT specification, there’s an optional field called "sub"
— short for subject. It’s meant to identify the principal (usually the user or system) that the token refers to.
Optional, as in: nice to have, but not required. Except… Oracle made it mandatory
At least in the version of OWSM we use, the "sub"
field is treated as mandatory — and this wasn’t documented anywhere at the time. By now you can find a support document on Oracle Support.
Let’s just say: that one took us a while to figure out.
This does mean that we need to configure the subject somewhere!
Summary #1 – OWSM validation flow
OWSM will go through the following five validation layers:
-
Is the token valid?
→ Signature check using the public key. -
Is the issuer trusted?
→ Based on the certificate’s CN/DN. -
Is the token expired?
→ Checked via the"exp"
(expiration) claim. -
Is the audience trusted?
→ Checked via the"aud"
claim, if configured. -
Is the subject trusted?
→ The"sub"
claim must be present — and is it configured.
Configuration
Prerequisites
-
Obtain the full public certificate chain from your JWT token provider.
You can usually use your browser to download the entire chain (via the HTTPS padlock icon). -
Get at least one valid JWT token that will be used for testing.
Open it in a tool that can visualize the payload, e.g. https://jwt.io. -
Take note of the following fields from the payload:
-
The
"aud"
(audience) claim - The
"iss"
(issuer) claim -
The
"sub"
(subject) claim
-
Step 1, import the certificates
-
Open Oracle Enterprise Manager (EM) by pointing your browser to:
http://yourserver:port/em
-
Open the menu and navigate to:
Security → Keystore -
Under the
owsm
section, check if there’s a keystore named"keystore"
. If it is not there create it.
> Note: If allowed, I’ll add screenshots later. - Import the public certificate chain. After importing the client certificate of your JWT token provider please make a copy of the CN (common name ) of the certificate as you will need this in the next step!
Step 2, configure trust for the issuer
- Navigate to WSM Domain Configuration in Oracle Enterprise Manager.
- Switch to the Authentication tab.
- Locate the JWT Trust section.
- Add a new entry:
- Issuer name, this has to be the exact
"iss"
from the example JWT token. - Issuer DN, this is the CN you saved before!
- Issuer name, this has to be the exact
Note:
The blog post I mentioned earlier claims you need to do a whole lot more here — but that’s not the case! This one step is enough to tell OWSM which issuer(s) to trust based on their certificate.
Now OWSM knows how to connect the certificate from the token to the right certificate chain
Step 3, audience configuration
For some reason, this step can’t be performed through the browser interface. It has to be done via the WLST console instead.
Please read this full block — including the comments — before entering any commands in WLST.
- Open WLST and connect to your server
beginWSMSession() listWSMTokenIssuerTrustDocuments(detail='true') selectWSMTokenIssuerTrustDocument("tokenissuertrust-WLS-osb_domain") addWSMTokenIssuerTrustRP("literal.jwt", "<iss>", ["<aud>"]) displayWSMTokenIssuerTrustRP("literal.jwt", "<iss>") commitWSMSession()
Explanation
-
listWSMTokenIssuerTrustDocuments()
This command lists all available Trust Documents.
Depending on your setup, you might see something like:tokenissuertrust-WLS-osb_domain
,tokenissuertrust-WLS-osb_domain_cluster
,
or something similar. -
selectWSMTokenIssuerTrustDocument(...)
Use this to select the correct Trust Document from the list above. -
addWSMTokenIssuerTrustRP("literal.jwt", "iss", ["aud"])
Here you’re literally stating:
“When I receive a token from this issuer (iss
) and it contains this audience (aud
), then I will trust it.”
In this step, you’re connecting the aud
claim from the token to the JWT Trust entry you defined in the previous step.
Example:
You decoded a JWT token and it contains:
{ "iss": "https://auth.example.com/issuer/jwt/token/something", "sub": "user12345", "aud": "00000003-0000-0ff1-ce00-000000000000", "exp": 1711854000, "iat": 1711850400, "nbf": 1711850400, "jti": "abc123xyz", "scope": "read:all write:limited", "role": "admin" }
In step 2 you configured:
- Issuer name: https://auth.example.com/issuer/jwt/token/something
- Issuer DN: The public Common Name
In step 3 you will do:
beginWSMSession() listWSMTokenIssuerTrustDocuments(detail='true') selectWSMTokenIssuerTrustDocument("tokenissuertrust-WLS-osb_domain") addWSMTokenIssuerTrustRP("literal.jwt", "https://auth.example.com/issuer/jwt/token/something", ["00000003-0000-0ff1-ce00-000000000000"] ) displayWSMTokenIssuerTrustRP("literal.jwt", "https://auth.example.com/issuer/jwt/token/something" ) commitWSMSession()
I hope this clarifies how to do this part of the configuration, this took me a long while to figure out.
Step 4, subject configuration
-
Open the Oracle WebLogic Console by navigating to:
http://yourserver:port/console
-
Go to Security, and click on myrealm.
-
Add a new user with the exact value used in the
"sub"
(subject) field of the JWT token.
Note:
No additional roles or permissions are needed for this user. OWSM only checks whether the user exists in the security realm — that’s it!
Summary #2, OWSM configuration
-
Import the public certificate chain into the OWSM keystore.
-
Configure JWT issuer trust by linking the certificate’s CN/DN to the issuer name.
-
Configure trusted audiences by associating them with the correct issuer.
-
Add a user to your WebLogic security realm matching the
sub
(subject) value in the token.
→ No roles or permissions required — existence is enough!
OSB
Now you can add the oracle/http_jwt_token_service_policy policy to a proxy and test it.
Testing
I prefer testing using SoapUI — it’s quick, flexible, and easy to use.
-
Import your WSDL or REST endpoint URI into SoapUI.
-
Add a custom HTTP header:
-
Name:
Authorization
-
Value:
Bearer <your base64-encoded JWT token>
-
-
Send the request and test!
If all goes well you should get a HTTP 200 status code in response.
Errors?!?!
While testing, you can — and probably will — run into various WSM-xxxxx
errors in your logs. Listing them all here would make this blog post even longer. So I’ll cover those in a separate post, where I go into the most common error messages, what they actually mean, and — more importantly — how to fix them.
Note: OSB and “audience enforcement”
What if all your requests come from the same JWT issuer — even if they use different aud
values?
Now combine that with Oracle Service Bus, where all services are secured using the same oracle/http_jwt_token_service_policy
.
See the problem?
There’s no built-in mechanism in OWSM to enforce that a specific OSB proxy only accepts tokens with a certain aud
value. Since the policy is reused across proxies, OWSM will happily validate the signature and accept any token from that issuer — regardless of the audience or other claims in the token itself.
But, there might be a solution! I will write a separate blog post for that soon!
Conclusion
If this post helped you get through the proverbial jungle that is OSB, OWSM policies & JWT tokens, let me know!
Brain out!
1 thought on “Oracle OWSM and JWT token handling”