Spring: google authentication redirect_uri_mismatch and url will not open in browser

I am working on a Spring-MVC application running on tomcat, in which I would like to use the functionality of a Google drive. I tried with a service account on my local machine and I had no problems. But when I downloaded the code on the server, the browser URL will not be open. Then I thought that I should not use a service account, I should use a regular web application account. Now when I do this, I get redirect_uri_mismatch.

I don’t understand anything, I set the redirect URL to the stream in JSON, why does it get redirect_url with random port numbers. If I change the port number in the browser url, it works fine. But still, on the server it will not open the browser URL, I see it in tomcat logs, but hell the URL does not open.

Here is my redirect URL from a Google app:

http://localhost/authorizeuser http://localhost:8080/ http://localhost:8080 http://localhost http://localhost:8080/Callback https://testserver.net/Callback http://testserver.net/Callback http://127.0.0.1 

Here is my client_secret.json:

 {"web": { "client_id": "clientid", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://accounts.google.com/o/oauth2/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_email": "clientemailstuff", "client_x509_cert_url": "certurlstuff", "client_secret": "itsasecret", "redirect_uris": ["http://localhost:8080/","http://localhost:8080"], "javascript_origins": ["https://testserver.net", "http://testserver.net","http://localhost:8080"] }} 

And here is the code where I am trying to authenticate:

  @Override public Credential authorize() throws IOException { InputStream in = DriveQuickstartImpl.class.getResourceAsStream("/client_secret.json"); GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES) .setDataStoreFactory(DATA_STORE_FACTORY) .setAccessType("offline") .build(); flow.newAuthorizationUrl().setState("xyz").setRedirectUri("http://localhost:8080/Callback"); Credential credential = new AuthorizationCodeInstalledApp( flow, new LocalServerReceiver()).authorize("user"); if(credential!=null && credential.getRefreshToken() != null){ storeCredentials(credential); } return credential; } 

This annoys me a lot because I set the redirect URL and it is simply ignored, and why the browser tab doesn't actually open when the application is deployed to the server.

Update Spring problem has also been fixed, the code below can be used to authorize GoogleDrive on a server with tomcat or others.

 @Service @Transactional public class GoogleAuthorization{ @Autowired private DriveQuickstart driveQuickstart; private static final String APPLICATION_NAME ="APPNAME"; private static final java.io.File DATA_STORE_DIR = new java.io.File( "/home/deploy/store"); private static FileDataStoreFactory DATA_STORE_FACTORY; private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); private static HttpTransport HTTP_TRANSPORT; private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE); private static final String clientid = "clientid"; private static final String clientsecret = "clientsecret"; private static final String CALLBACK_URI = "http://localhost:8080/getgooglelogin"; private String stateToken; private final GoogleAuthorizationCodeFlow flow; public GoogleAuthorization(){ try { HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR); } catch (GeneralSecurityException | IOException e) { e.printStackTrace(); } flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientid, clientsecret, SCOPES).setAccessType("offline").setApprovalPrompt("force").build(); generateStateToken(); } /** * Builds a login URL based on client ID, secret, callback URI, and scope */ public String buildLoginUrl() { final GoogleAuthorizationCodeRequestUrl url = flow.newAuthorizationUrl(); return url.setRedirectUri(CALLBACK_URI).setState(stateToken).build(); } /** * Generates a secure state token */ private void generateStateToken(){ SecureRandom sr1 = new SecureRandom(); stateToken = "google;"+sr1.nextInt(); } /**s * Accessor for state token */ public String getStateToken(){ return stateToken; } /** * Expects an Authentication Code, and makes an authenticated request for the user profile information * * @param authCode authentication code provided by google */ public void saveCredentials(final String authCode) throws IOException { GoogleTokenResponse response = flow.newTokenRequest(authCode).setRedirectUri(CALLBACK_URI).execute(); Credential credential = flow.createAndStoreCredential(response, null); System.out.println(" Credential access token is "+credential.getAccessToken()); System.out.println("Credential refresh token is "+credential.getRefreshToken()); // The line below gives me a NPE. this.driveQuickstart.storeCredentials(credential); } } 

Controller Method:

  @RequestMapping(value = "/getgooglelogin") public String getGoogleLogin(HttpServletRequest request, HttpServletResponse response, HttpSession session,Model model) { // Below guy should be autowired if you want to use Spring. GoogleAuthorization helper = new GoogleAuthorization(); if (request.getParameter("code") == null || request.getParameter("state") == null) { model.addAttribute("URL", helper.buildLoginUrl()); session.setAttribute("state", helper.getStateToken()); } else if (request.getParameter("code") != null && request.getParameter("state") != null && request.getParameter("state").equals(session.getAttribute("state"))) { session.removeAttribute("state"); try { helper.saveCredentials(request.getParameter("code")); return "redirect:/dashboard"; } catch (IOException e) { e.printStackTrace(); } } return "newjsp"; } 

newjsp just has a button for clicking on the url.

+7
java google-apps google-oauth google-api google-api-java-client
source share
2 answers

In particular, you get random ports because you use LocalServerReceiver , which runs an instance of the berth on a free port to get an authorization code.

At a higher level, it looks like you are developing a web server application , but you are trying to use Google OAuth as if it were an installed application . If you are really building a web server application, you should use the server hostname instead of localhost in the callback URL, providing an end-user link for authentication with flow.newAuthorizationUrl () , and your callback will retrieve the token using flow.newTokenRequest (String) . Also make sure that the client ID that you created in console has a web application of the type or you get redirect_uri_mismatch errors . A full working example of how to do this can be found here .

+2
source share

Instead of using:

 Credential credential = new AuthorizationCodeInstalledApp( flow, new LocalServerReceiver).authorize("user"); 

Use

 LocalServerReceiver localReceiver = new LocalServerReceiver. Builder().setPort(XXXX).build(); 

to set the static port number

 Credential credential = new AuthorizationCodeInstalledApp( flow, localReceiver).authorize("user"); 

although you cannot change the redirect URL, however, you can set both the host and port. To change the way you use .setHost() host

You can also use the default constructor:

 Credential credential = new AuthorizationCodeInstalledApp( flow, new LocalServerReceiver("Host", XXXX).authorize("user"); 
+2
source share

All Articles