bluesliverx / grails-spring-security-oauth2-provider

Grails Spring Security OAuth2 Provider Plugin
http://grails.org/plugin/spring-security-oauth2-provider
57 stars 58 forks source link

Thoughts on separating authorization / resource service? #71

Closed dynamind closed 9 years ago

dynamind commented 9 years ago

This is not a feature request per se. But I do hope to exchange some thoughts on this subject...

There are two distinct responsibilities offered by the Spring Security OAuth2 Provider, that is:

I have multiple "resource micro-services" that are load-balanced. I'm thinking about an architecture where I can take the shared "authorization service" and host it on a load-balanced host, e.g. oauth2.domain.co and run the various resource services on different hosts, e.g. api.domain.co/some-service/v1, api.domain.co/other-service/v2

I can already fake this scenario with a reverse proxy such as NginX; since all applications contain both authorization/resource services both are allocated to the authorization pool and the resource pool. That said, I'm curious if there's a better way so I thought I'd share it here.

The number of micro services could easily be 100+, all duplicating Spring Security logic. Performing updates on the oauth part implies redeployment of all services. That gets ugly really fast.

This is what I have in mind:

  1. Client contacts authorization endpoint (e.g. grant_type=client_credentials) to get access_token
  2. Client requests resource with Authorization: Bearer
  3. Resource service contacts authorization endpoint to check if is valid. This is not part of any OAuth spec, but should be supported by Spring Security OAuth2 Provider. There is very little documentation available on this mechanism; it might not even be usable. Also, there's the obvious problem of how to communicate roles and scopes with the resource service.
  4. Upon verification of the access token, resource service returns the data to the client.

All the magic happens in the third step. I'm considering using Redis to hold on to all the access tokens, but that's a separate challenge.

What do you think? Does this mean we would end up having two plugins that can optionally be used together, such as spring-security-oauth2-authorization-provider and spring-security-oauth2-resource-provider (the names get rather long ;-))

Addendum @EnableResourceServer adds filter; resource services should share TokenStore with authorization service. http://stackoverflow.com/questions/29051206/oauth2-how-should-the-resource-server-know-if-the-access-token-is-valid SpringBoot example trying to achieve something similar http://stackoverflow.com/questions/29003993/spring-boot-oauth2-splitting-authorization-server-and-resource-server

bluesliverx commented 9 years ago

Like you say, this should be possible. I haven't dug deep into the new configuration of beans since the upgrade to the newer versions of the OAuth provider, but the previous configuration had a clear separation between the resource server and the authentication server, with the plugin combining them for simplicity.

I would guess that the plugin still has some separation, and we would just need to expose configuration options to disable the authentication and/or resource portion, so you would still install the same plugin, but modify the configuration for each slightly so that they serve a single role instead of both roles.

dynamind commented 9 years ago

Sounds reasonable. The separation isn't obvious, and since we're not using any of those fancy new annotations (I think), all the Spring docs that state "just add annotation X and magic happens" don't help.

Anyway, your response is encouraging, so I'll start hacking a bit when I find the time.

bobby-vandiver commented 9 years ago

Re: Step 3: The RFC 6749 Section 7 does address the validation of the access_token presented to the resource server, but leaves it up to the implementor to decide how the validation with the authorization server is actually implemented.

It looks like the @EnableResourceServer probably registers an instance of OAuth2AuthenticationProcessingFilter in the filter chain to handle access_token validation, which the plugin already does under the name oauth2ProviderFilter. This is ultimately backed by the GORM token store.

From what I've seen (and I haven't investigated this extensively so I could be wrong), the annotations Spring OAuth provides are primarily for developer convenience so they don't have to deal with wiring up the relevant Spring beans themselves. It would be worthwhile to identify what functionality Spring OAuth has that isn't currently exposed by the plugin and incorporate that into the plugin if it makes sense.

If you want to split the resource server and authorization server functionalities up and still use the plugin, all of the functionality is there like @bluesliverx said. I would investigate replacing the aforementioned oauth2ProviderFilter for your resource server applications with a custom filter that performs whatever custom validation with your authorization server. For the authorization server, just configure the token and authorization endpoints to handle authorizing access_token requests and disable any resource handling.

bobby-vandiver commented 9 years ago

I updated the documentation to demonstrate how to accomplish this. In order to make it easy for the end developer, I tweaked the OAuth2AuthenticationManager bean definition slightly to depend on the resourceServerTokenServices bean, which by default is just an alias for the tokenServices bean.

I still need to stand up a few sample applications and test this more thoroughly, so I'll leave this issue open until I've done that.

dalthviz commented 7 years ago

Hi all, do you know if is possible to expose the oauth/check_token endpoint from Spring Security OAuth? Thanks in advance for all the info that you could provide me.

abhaygoel commented 6 years ago

Hi All, I have the same question. How do I expose oauth/check_token url. Any help is much appreciated.