using spring boot app as resource server and google oauth2 as authorization server

Viewed 2176

I have a web app using angular6 for frontend and spring boot for the rest apis.

My angular app is running on localhost:4200 and is able to authenticate successfully with google and I can see authToken and idToken. (I used angularx-social-login plugin in angular)

Now, I want to use this auth token to secure my spring boot api server running at localhost:8080 as well.

I am trying to do similar to (image source) picture Here client is my angular app, resource server is spring boot application and authorization server is google

I tried using EnableResourceServer annotation and many different approaches but nothing seems to work. It always gives me invalid token by checking in memory token store and doesn't even try to validate with google for the right token.

I am using the same client-id and secret for the oauth2 configuration in spring app and angular app.

How can I make spring boot application validate the token with google for every request?

My application.properties

server.servlet.context-path=/api

spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:file:~/h2/testdb

logging.level.org.springframework.web=TRACE
logging.level.org.springframework.security=TRACE
logging.level.org.hibernate=TRACE
    
security.oauth2.resource.filter-order = 3
spring.security.oauth2.client.registration.google.client-id=#google-client-id
spring.security.oauth2.client.registration.google.client-secret=#google-client-secret    
security.oauth2.resource.user-info-uri= https://www.googleapis.com/oauth2/v3/userinfo # URI of the user endpoint.

Here is my resource server configuration class

@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
    private static final String RESOURCE_ID = "rest_api";
    
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID).stateless(false);
    }
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .requestMatcher(new RequestHeaderRequestMatcher("Authorization"))
            .authorizeRequests().anyRequest().fullyAuthenticated();
    }
    
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    protected static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {
        @Override
        protected MethodSecurityExpressionHandler createExpressionHandler() {
            return new OAuth2MethodSecurityExpressionHandler();
        }
    }
}
2 Answers

Hopefully you've already found a solution. Otherwise have a look at this article.

On a side note: you're declaring the resource stateful

resources.resourceId(RESOURCE_ID).stateless(false);

Have you tried using it stateless?

resources.resourceId(RESOURCE_ID).stateless(true);

I found that most of the answers were not helpful to this topic, so i figured out myself how i could make it possible to use google as authorization server.

Googles Access token is not in the format of JWT so the standard implementation of resource server with jwt is not possible. So what i did to work around this problem is, that i wrote an own GoogleAuthenticationManager and a GoogleQueryFilter. In the Query filter happens basically the same as in BearerAuthenticationFilter, just that i send the token over query because when u send it over Authorization, the BearerAuthenticationFilter will delete the Auth and return Unauthorized. In the AuthenticationManager i send the token to the googles endpoint and watch for 200ok. and then i create a token with all relevant data. The QueryFilter will push it into SecurityContext

Related