I’m creating an application integrating with Shopify’s API, which uses OAuth2 for authentication and authorization. Using the tutorial for Spring Security OAuth2, and the tutorial for Shopify, I’ve been able to get integration working with a single shop. The YAML configuration looks like this:
shopify:
shop: myshop
scopes: read_customers,read_orders
security:
oauth2:
client:
clientId: myclientid
clientSecret: mysecret
tokenName: access_token
authenticationScheme: query
clientAuthenticationScheme: form
accessTokenUri: https://${shopify.shop}.myshopify.com/admin/oauth/access_token
userAuthorizationUri: https://${shopify.shop}.myshopify.com/admin/oauth/authorize?scope=${shopify.scopes}&grant_options[]=
pre-established-redirect-uri: https://myapp/login
registered-redirect-uri: https://myapp/login
use-current-uri: false
resource:
userInfoUri: https://${shopify.shop}.myshopify.com/admin/shop.json
However, this static configuration won’t work for an app published in Shopify’s App Store because the redirect, access token, user info, and user authorization URIs depend on the shop name. There are examples of using more than one provider, but they still have to be static.
To allow these URI’s to be dynamic, I’ve come up with a few possible options:
-
Use a parameter in the
/login
path to identify the shop, then create a filter that adds the shop name to aThreadLocal
that runs before everything else, then dynamically create theAuthorizationCodeResourceDetails
that is needed by the OAuth2 filter via a Spring proxied factory bean. -
Use a sort of “metafilter” that dynamically recreates the
OAuth2ClientAuthenticationProcessingFilter
per request along with all of the resources that it needs. -
Override
OAuth2ClientAuthenticationProcessingFilter
so that it can handle recreating theRestTemplate
it needs to obtain the access token.
All of these options seem pretty difficult. What’s a good way to handle dynamically-generated URI’s for access tokens and user information in Spring Security OAuth2?
Also, since I’m new to OAuth2 in general, do I need to enable a Resource Server in my Spring configuration to protect my app with the access token?
2
Answers
a bit late but I did return a dynamic url for an oauth resource by overriding the getter for the Oauth2ProtectedResource
I’m having the same problem you are and I’m leaning toward your first theory of using ThreadLocal storage. Here is how I’ll probably go about my solution:
Set values from ServletRequest in LocalThread storage by overriding methods in OAuth2ClientAuthenticationProcessingFilter:
Then translate the URI’s within the OAuth2RestTemplate by overriding the followign methods:
I’ll probably have to make my own @Bean for the RestTemplate that has an injected @Service that will lookup the dynamic Shopify domain.
I’ll post my solution if it works.