Recently I started development on a new app to plan my meals. I wanted to make use of the rich collection of recipes I have accumlated on Pinterest. Thankfully there is an API that allows me to access my public pins. Unfortunately I was required to configure my application to use spring-security-oauth which is not so easy. Here I’d like to share my OAuth2 configuration for Pinterest with you, especially one problem that took me a while to figure out. I assume that you are familiar with the official OAuth2 standard (read it, its not that bad and really helpful) and have a general idea about Spring Boot.
Setting up an app
We first start by setting up our app on Pinterest. Create a developer account and register a new app. You can follow pinterests Getting started guide. When setting up your app make sure to add a redirect URI. In my case I have a controller listening on https://localhost:8443/boards. The moment you access that URL without a valid access token you’ll be redirect to Pinterest to authorize the app and you’ll be redirected back to the same URL you came from. In order for OAuth2 to work properly make sure to add that redirect URL to your app.
Furthermore it is important that you use https. Otherwise an access token might be accessed by an attacker. Even though we are running in development mode, it doesn’t hurt to use an SSL certificate. It’s just closer to production and I think that never hurts.
I personally found it to be a bit tricky to setup Springt Boot with SSL. There are tutorials out there that explain the steps quite ok. But I had to combine a few tutorials to get it right. So let me have another try here.
Generate a new certificate
… by using a Java tool called keytool:
When asked about your first and last name put in localhost. The result of this command will be a new file with the name keystore.jks. Put that file into your resources folder so it ends up in your classpath (mine is in /src/main/resources).
If you are running unittests and also integration tests you’ll notice that your tests are failing with a Java exception. That is due to the fact that you either configured something wrong, or your certifcate is simply not considered valid. That is because you generated it yourself. If you start your app and access it in the browser, he will tell you that the certificate is not trusted. It is easy to add a security exception in the browser, but not so easy in Java. While it is possible to add your custom certificate to the trusted certificates in Java, I prefer another simpler option (especially if you want to ease the setup for other users). While not the best solution I choose it for its simplicity.
It’s taken from: https://stackoverflow.com/questions/23504819/how-to-disable-ssl-certificate-checking-with-spring-resttemplate?noredirect=1&lq=1 . There is another way I found in the OAuth2 examples, where a HostnameVerifier is injected into the container that basically does the same thing, just with more configuration effort.
Create a new class with a static method to turn off the certificate validation and call it in your unittests (hint: @Before).
Setup the OAuth2 resource configuration
Now that we set up our SSL certificate and everything is up and running again, we have to configure our OAuth2 resource. This way we tell spring-security-oauth how our resource (Pinterest) expects the authorization to go down.
Note: Spring security will be enabled by default and you have to authenticate. That means you have to setup a user account to login with. Why? Because your access token will be tied to your session and it is not desired that one anonymous user has mutliple access tokens…
My security configuration with a user:
The acutal resource configuration, this one took me a bit to figure out:
Most of that configuration is probably straightforward to you, after understanding the OAuth2 standard and the developer documentation. There was just one stumbling block for me:
If you get a message along the way of “missing client_id”, it is because you are not sending your client id in the query, that is what you have to set specifically.