Ok, so HttpInvoker
may not be the what the hipsters are using (it’s been around since 2003 or so) but there are still plenty of Java desktop applications out there communicating over RMI or EJB that could use a security boost by using OAuth 2.0.
If you’ve got a desktop app communicating to a server over RMI, how are you authorizing the calls? If the app is on the end-user’s machine, how can you keep any secret auth information?
- username/password? - exposed
- static token? - exposed
Although obfuscation mechanisms can be used, any text can be extracted from the jar on the persons machine.
So how can you keep a secret on a public application? You can’t. But OAuth 2.0 authorization grant type can be used in combination with PKCE to obtain short-lived access tokens for a specific user to securely communicate with server endpoints.
How can we do this?
Let’s build on baeldungs’ http-invoker tutorial. It doesn’t use a typical desktop client but you can imagine this Spring Boot application running on the end users machine, and communicating securely with a server somewhere else, without needing to have any secrets! Essentially, the server allows remote invocations of a CabBookingService via the http://localhost:8080/booking
endpoint. The client invokes it by hitting http://localhost:8081
on the client after an authorization code flow to obtain access tokens for the server. Here we go!
First create an OAuth 2.0-aware WebClient:
Create a custom WebClientHttpInvokerRequestExecutor
that will send your requests using the OAuth 2.0-aware WebClient
:
Ensure your security configuration uses Spring Security’s OAuth 2.0 Client and uses OAuth 2.0 Login to protect every endpoint. When you hit a protected endpoint via a web browser, Spring Security will request authentication and redirect you to its login page.
To use our WebClientHttpInvokerRequestExecutor, hook it up to HttpInvokerProxyFactoryBean something like so
The client registration and provider are below. Notice there is no client-secret and that the client-authentication-method is none
. This tells Spring Security to use PKCE to secure the authorization code flow.
The server config is super simple.
I’ve shown most but not all of the code but let’s try it all out!
Assuming you’ve cloned the project from GitHub, start up the server and then the client. Trigger a login flow on your client by going to http://localhost:8081 in your browser and you’ll get a screen like this:
Click on the Okta link and you should see the Okta IdP sign in page below (unless you’ve already signed in to the Okta IdP)
Sign in with user@example.com
/Password1
(if someone hasn’t changed it!) or sign up for your own account with Okta on that IdP instance (using the sign up link on the page). Once you’ve signed in to Okta’s IdP, your client should have an access token with which it can talk to the server! In fact, you should already see something like this in your browser:
Ride confirmed: code '0d0b9f4a-0244-4c26-a8b2-1ce908e6756f'.
This means you hit the server using HttpInvoker and received a response! Woohoo :)
I hope you enjoyed doing fun learning how to do modern OAuth 2.0 PKCE stuff even with older tech like Http Invoker! Please let me know what you thought of this tutorial in the comments below or on Twitter. Feel free to clone, star, or browse the code on GitHub.