I am working on a project that involves secure communication between the WordPress site and my API server.
My API server acts as an Authorization and Resource server, where I set up an OAuth2 provider (via Doorkeeper Ruby gem).
My use case is as follows:
- WordPress plugin is open source and can be installed on multiple sites. So the
client_idis hardcoded in the plugin code. - In the plugin UI, the user starts the OAuth flow, and the server provides an access token which then persists in the WP database.
- I'm using PKCE flow, so I don't need to store
client_secretin the code.
Since the plugin is distributed, I don't know redirect_uri beforehand. This means the existing classic flows not well suited for my case.
Currently, I am working around it in the following way:
- OAuth app registered with
redirect_uripointing to server's/oauth/callback - User initiates the flow, and the plugin sends a request which includes
redirect_urifor my WordPress instance - On the server, I swap the plugin's URI with one defined in the app pass authorization
- Then, I use the plugin's URI to redirect the User back to the WordPress install.
While this approach "works", I wonder if there is a better way to implement it in my case. Also, I am worried that by messing with URI's I made OAuth less secure.
I just did a basic plugin with oauth recently for my own internal use, but my struggles might help you.
The key for me was to have my return url be the plug-in settings page with something like '?callback_oauth=1' value tagged on the end. So when the user gets redirected back to the settings page they have the code that was passed from the server and the callback value of 1(I can't remember why just the code wasn't working for me at the moment, but it just never did, bit adding a different thing to check for worked).
Anyways...
When that code comes in I grab it and make the call for the access token, and when that comes back im saving it in the options table along with the refresh token and the expiration time. AND I'm saving prefix_authorized with a value of 1 in the options table so that I can just refer to that to see that I'm authorized and good to go for certain things like showing buttons and css changes where I really don't need to constantly check that a key is valid.
I haven't implemented my refresh yet, mainly because I'm using it for a utility in house, so really I can just click disconnect and then authorize again if I need to at the moment.