0

I have an angular project that runs on localhost://4200 and a spring boot project that runs on locathost://8081. When i'm trying to send an authorization request to gmail api i am getting the following error.

login:1 Failed to load https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&client_id=954782724108-ifm1o8if53ma6g6saalvn1suj20i5dqh.apps.googleusercontent.com&redirect_uri=http://localhost:8081/user/login/gmailCallback&response_type=code&scope=https://www.googleapis.com/auth/gmail.readonly: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private Environment env;

    @Autowired
    private UserSecurityService userSecurityService;

    private PasswordEncoder passwordEncoder() {
        return SecurityUtility.passwordEncoder();
    }

    private static final String[] PUBLIC_MATCHERS = {
        "/css/**",
        "/js/**",
        "/user/**"
    };

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().cors().configurationSource(request -> {
            return new CorsConfiguration().applyPermitDefaultValues();
        }).and().httpBasic().and().authorizeRequests()
        .antMatchers(PUBLIC_MATCHERS).permitAll().anyRequest().authenticated();
    }
    }

}

RequestFilter.java

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestFilter implements Filter{
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, x-auth-token");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");

        if(!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
            try {
                chain.doFilter(req, res);
            } catch (IOException | ServletException e) {
            }
        } else {
            System.out.println("Pre-fight");
            response.setHeader("Access-Control-Allowed-Methods", "POST, GET, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "authorization, content-type, x-auth-token, " +
                    "access-control-request-headers,access-control-request-method,accept,origin,authorization,x-requested-with");
            response.setStatus(HttpServletResponse.SC_OK);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {}

    @Override
    public void destroy() {}
}

method callled in restController from angular

@RequestMapping(value="/gleConsole",method=RequestMethod.GET)
   public RedirectView googleConnectionStatus(HttpServletResponse response) throws Exception {
//        response.sendRedirect(authorize());
       return new RedirectView(authorize());
   }

   private String authorize() throws Exception {
       AuthorizationCodeRequestUrl authorizationUrl;
       if (flow == null) {
           GoogleClientSecrets.Details web = new GoogleClientSecrets.Details();
           web.setClientId(CLIENT_ID);
           web.setClientSecret(CLIENT_SECRET);
           clientSecrets = new GoogleClientSecrets().setWeb(web);
           httpTransport = GoogleNetHttpTransport.newTrustedTransport();
           flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY, clientSecrets,
                   Collections.singleton(GmailScopes.GMAIL_READONLY)).build();
       }
       authorizationUrl = flow.newAuthorizationUrl().setRedirectUri(REDIRECT_URI).setAccessType("offline").setApprovalPrompt("force");

       System.out.println("gamil authorizationUrl ->" + authorizationUrl);
       return authorizationUrl.build();
   }

   @RequestMapping(value = "user/login/gmailCallback", method = RequestMethod.GET, params = "code")
   public ResponseEntity<Map<String, ArrayList<String>>> oauth2Callback(@RequestParam(value = "code") String code, HttpSession session, Model model) {
       Map<String, ArrayList<String>> headerColumns = new LinkedHashMap<>();

       return new ResponseEntity(headerColumns, HttpStatus.OK);
   }

client.service.ts

  gleConsole(){    
       let url = "http://localhost:8081/gleConsole";  
       return this.http.get(url,'');

    }
nidhi
  • 299
  • 3
  • 4
  • 21
  • Even I have the same issue – eshwar chettri Aug 08 '18 at 09:55
  • https://stackoverflow.com/questions/28359730/google-place-api-no-access-control-allow-origin-header-is-present-on-the-req – Tahir Hussain Mir Aug 08 '18 at 10:24
  • @TahirHussainMir I've gone through the link, but i am using the .subscribe() method in angular 6. couls you help me out in how to use the ajax call in .subscribe() – nidhi Aug 08 '18 at 10:37
  • That error message is pretty clear: Your frontend code is making a request to https://accounts.google.com/o/oauth2/auth, but https://accounts.google.com/o/oauth2/auth by intentionally doesn’t send back the Access-Control-Allow-Origin response header — because it’s not meant to be called from frontend JavaScript code running in a browser. The server-side Java code in the question is irrelevant in this case. Nothing you do in your own server-side code is going to change the fact that your frontend code is trying to send a request to https://accounts.google.com/o/oauth2/auth cross-origin – sideshowbarker Aug 08 '18 at 10:44
  • @sideshowbarker I tried with response.sendRequest(url), still it gives the same issue. i have edited the code. could you look into it. – nidhi Aug 08 '18 at 10:58
  • Can you try the [OAuth 2.0 for Client-side Web Applications](https://developers.google.com/identity/protocols/OAuth2UserAgent) since you're using REST calls? Here's an additonal [Spring Boot + AngularJS login Youtube tutorial](https://www.youtube.com/watch?v=fN7ZMoKLrAU)? – ReyAnthonyRenacia Aug 08 '18 at 15:25
  • @sideshowbarker I've spent 2 days for solving problem, thank you for explanation, yes I use server side auth and it works if I try to auth from browser but from webapp still unsuccessful. My frontend built with VueJS, I'm thinking what if I find some intercepter which will add in header 'Access-Control-Allow-Origin' before making calling accounts.google.com/o/oauth2/auth? How do you think it's possible? – Dave Sep 25 '18 at 20:44
  • As far as adding an 'Access-Control-Allow-Origin', the header would need to be injected in the *response* from accounts.google.com/o/oauth2/auth. It would do no good to add it to the request. And I don’t know how Vue interceptors work, but if they somehow run on the server side outside a browser, then I assume they could proxy requests like any other server-side proxy could. But if they only run on the client side in a browser, there’s no way they could add a *response* header to a response from accounts.google.com/o/oauth2/auth – sideshowbarker Sep 25 '18 at 22:41
  • @sideshowbarker you're right it sounds very difficult and not good. So, it means there is only one way to implement "Client-side (JavaScript) applications" oauth2 to work? How to solve such problem when you have frontend and backend on different ports? – Dave Sep 26 '18 at 07:25
  • @Dave did you figure out a way to solve the problem when having frontend and backend on different ports? – Nipuna Saranga Jun 24 '20 at 12:38

0 Answers0