google-oauthgoogle-calendar-apigoogle-api-java-client

Integrating Google calendar to a jsf web App


Our web application, developed in JSF, allows its users to schedule meetings in their calendar. The goal is that in the application settings, each user can integrate their Google account, so that the meetings scheduled in the application can be recorded in their Google calendar.

the first step is integrating Google account in the settings section of the application:

Calendar Settings

clicking the button calls the function connectGoogleAcount in the backbean as shown in the code:

public void connectGoogleAcount() throws IOException, GeneralSecurityException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
        .setApplicationName(APPLICATION_NAME).build();

System.out.printf("Account connected !");}

and the function getCredentials:

private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
    // Load client secrets.
    InputStream in = CalendarQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
    if (in == null) {
        throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
    }
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));

    // Build flow and trigger user authorization request.
    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
            clientSecrets, SCOPES)
            .setDataStoreFactory(
                    new FileDataStoreFactory(new java.io.File(USER_DIRECTORY_PATH + "/" + TOKENS_DIRECTORY_PATH)))
            .setAccessType("offline").build();
    LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8080).build();
    Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
    // returns an authorized Credential object.
    return credential;
}

it works on clicking the button. On the server, I see that the URL to open in browser is :

Please open the following address in your browser: https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=00000000000000-yyyyyyyyyyyyyyyyyyddd.apps.googleusercontent.com&redirect_uri=http://localhost:80/Callback&response_type=code&scope=https://www.googleapis.com/auth/calendar.readonly

My question is how to make the page open automatically in the browser after clicking the button?


Solution

  • Opening the page automatically in a browser is not going to help you.

    The code you are using is designed for an installed application. Its going to open the browser on the machine the code is running on. This will not work with a webserver.

    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
                clientSecrets, SCOPES)
                .setDataStoreFactory(
                        new FileDataStoreFactory(new java.io.File(USER_DIRECTORY_PATH + "/" + TOKENS_DIRECTORY_PATH)))
                .setAccessType("offline").build();
        LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8080).build();
    

    You should be using the Web server applications example.

    public class CalendarServletSample extends AbstractAuthorizationCodeServlet {
    
      @Override
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws IOException {
        // do stuff
      }
    
      @Override
      protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
        GenericUrl url = new GenericUrl(req.getRequestURL().toString());
        url.setRawPath("/oauth2callback");
        return url.build();
      }
    
      @Override
      protected AuthorizationCodeFlow initializeFlow() throws IOException {
        return new GoogleAuthorizationCodeFlow.Builder(
            new NetHttpTransport(), GsonFactory.getDefaultInstance(),
            "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
            Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
            DATA_STORE_FACTORY).setAccessType("offline").build();
      }
    
      @Override
      protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
        // return user ID
      }
    }