Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue + Google oAuth2 + Spring Boot Rest Api + different ports

I have a web application, which consist of 2 parts

  1. Spring boot rest , server-side on port 8081
  2. Vue + vuex + axios , front-end on port 8080
  • Below my Spring Boot app

package com.example.googleoauth;

package com.example.googleoauth;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GoogleoauthApplication {

    public static void main(String[] args) {
        SpringApplication.run(GoogleoauthApplication.class, args);
    }
}

package com.example.googleoauth.Controllers;

package com.example.googleoauth.Controllers;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.Map;

@RestController
@RequestMapping("/")
public class MainController {

    @GetMapping("/test")
    public String test() {
        return "Success test from Spring Boot";
    }

    @GetMapping("/login")
    public Map<String, Object> login(@AuthenticationPrincipal OAuth2User principal) throws IOException {
        return principal.getAttributes();
    }
}

package com.example.googleoauth.Configuration;

   package com.example.googleoauth.Configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
public class WebConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors().configurationSource(corsConfigurationSource())
                .and()
                .authorizeRequests(a -> a
                        .antMatchers("/", "/error", "/webjars/**", "/test").permitAll()
                        .anyRequest().authenticated()
                )
                .exceptionHandling(e -> e
                        .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
                )
                .oauth2Login().defaultSuccessUrl("/login");
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:8080"));
        configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS"));
        configuration.setAllowCredentials(true);
        //the below three lines will add the relevant CORS response headers
        configuration.addAllowedOrigin("http://localhost:8080");
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
  • My Vue app

     actions: {
     SIGNIN({commit}) {
         axios.get('http://localhost:8081/oauth2/authorization/google')
             .then((profile) => {
                 commit('SET_AUTH_API', profile.data)
                 return profile;
             })
             .catch((error) => {
                 console.log(error)
                 return error;
             })
     },
    

I can access http://localhost:8081/oauth2/authorization/google and successfully authenticate using Google and get user data

But I had issues accessing this link through Vue app from port 8080 I get an error below

Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=964744021349-cvsr63lt5gvb8dgatihgegr4d1hcqqsc.apps.googleusercontent.com&scope=openid%20profile%20email&state=Vk2BoAfzU7xY7a00SXjzLWn2dW6WThgaNsDVrY_9m3I%3D&redirect_uri=http://localhost:8081/login/oauth2/code/google&nonce=ziJzRyteq-DSKN7MUHcFy918PJK9PNGQdU5jp4_kMsI' (redirected from 'http://localhost:8081/oauth2/authorization/google') from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

enter image description here

Then this post answer helped me a bit , after I added headers: {} to axios GET request

With help of Chrome CORS extension , I got rid of message "has been blocked by CORS policy" , but seems like nothing happens when I send "http://localhost:8081/oauth2/authorization/google" request

    actions: {
    SIGNIN({commit}) {
        console.log("store-SIGNIN")
        const options = {
            method: 'GET',
            url: 'http://localhost:8081/oauth2/authorization/google',
            headers: {}
        };
        axios(options)
            .then((profile) => {
                // console.log(resp)
                console.log(1)
                commit('SET_AUTH_API', profile.data)
                console.log(2)
                return profile;
            })
            .catch((error) => {
                console.log(error)
                return error;
            })
    }

in the dev console output I get

enter image description here

Please point me in right direction

like image 371
Lagi Avatar asked Oct 23 '25 09:10

Lagi


1 Answers

Answer to my post:

I should have done the whole thing the other way around.

I found an answer in this repo https://github.com/bmstefanski/spring-vue-rest-oauth2 There's a complete solution that I needed

Solution looks like

  1. Vue login component has <v-btn class="ma-1 pa-2" href="/api/fwd">Login
  2. Backend rest api redirects to "response.sendRedirect("/oauth2/authorization/google");"
  3. Then Google auth form opens, auth process is done, then according to security adopter in spring success login redirects us here defaultSuccessUrl("/api/logged-user")
  4. Then we get back to frontend by redirect "response.sendRedirect("http://localhost:8080/login%22);"
  5. Finally at frontend in created hook using axios we get user profile data from spring rest api - ResponseEntity.ok(principal)

and this is it , no CORS or OPTIONS errors (though we need CORS config at backend side)

like image 170
Lagi Avatar answered Oct 26 '25 01:10

Lagi