Spring OAuth2 resource server with Google Authorization server

2.2k views Asked by At

I am trying to implement a simple Spring OAuth2 resource server using google as OAuth server.

Basically, I've been following guides like this one spring-oauth2-with-google

application.yml:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: *******.apps.googleusercontent.com
            client-secret:********_
            scope:
              - email
              - profile
              - openid
      resourceserver:
        jwt:
          issuer-uri: https://accounts.google.com
          jwk-set-uri: https://www.googleapis.com/oauth2/v3/certs

SecurityConfig.java:

@Configuration
public class SecurityConfig {

    @Bean
    protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .httpBasic().disable()
                .formLogin(AbstractHttpConfigurer::disable)
                .csrf(AbstractHttpConfigurer::disable)
                .authorizeRequests(authorize -> authorize
                                .anyRequest().authenticated()
                )
                .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
                .sessionManagement(sessionManagement ->
                        sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        ;
        return http.build();
    }
}

UserController.java

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {

    @GetMapping("/{id}")
    public void getUser(@PathVariable String id) {
        System.out.println("Id: " + id);
    }
}

I am able to get the google JWT through postman as described in the guide, but no matter how hard I try, when I try to consume my end point, through postman, the response is always 401. I have already tried to set a space between the Bearer keyword and token_id.

Error in postman:

Bearer error="invalid_token", error_description="Invalid token", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"

but if i review the token in google token info the result seems ok:

  "issued_to": "263667859573-jve8vplquh7qn4ft7aaj1t1m9boaq5d6.apps.googleusercontent.com",
  "audience": "263667859573-jve8vplquh7qn4ft7aaj1t1m9boaq5d6.apps.googleusercontent.com",
  "user_id": "112897290372529438679",
  "scope": "openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
  "expires_in": 3296,
  "email": "[email protected]",
  "verified_email": true,
  "access_type": "online"
1

There are 1 answers

3
ch4mp On

Maybe, the access-token you get from Google is just not a JWT but an opaque token, in which case configuring your resource-server with a JWT decoder won't work. try to "open" one of your access-tokens in a tool like https://jwt.io to be sure.

I couldn't find a standard introspection endpoint for such Google opaque tokens, just https://www.googleapis.com/oauth2/v3/tokeninfo to which you can submit access_token as request param. If token is valid, you'll get claims in response. So, you could actually configure your resource-server with token introspection (instead of JWT decoder), providing your own token introspector to call the tokeninfo endpoint, check the response and either throw an exception or return an Authentication of your choice.

        http.oauth2ResourceServer().opaqueToken().introspector(...);

But this is quite some work and introspection is far less efficient than decoding JWTs (first requires to submit token to Google for each and every incoming request on your resource server, when fetching public key only once for all request is enough for second).

It is likely that Google just doesn't want us to use their authorization-servers for our own resource-server except for a few limited cases (and I'm not sure which ones).

An alternative for you is using another authorization-server capable of federating "social" identities (Google, of course, but also Facebook, Github, etc.). Plenty do so: Keycloak is a famous on premise solution, but if you don't want to bother at maintaining an authorization-server yourself, you could have a look at SaaS like Auth0 (which has a free tier). Those two are just my current preferred in a galaxy of solutions, just search for "OIDC authorization-server" and choose your own.