Monday 31 March 2014

Google OAuth2 / Vaadin Web Application

This tutorial explains how you can use Google OAuth 2.0 to authenticate / authorize your users in Vaadin Web Applications and allow users to login using their Google Id.
  1. Logon to Google Developer Console
  2. Navigate to API & Auth --> Credentials
  3. Create a Client ID. This will return a generate Client ID and Client Secret Key 
  4. Click Download JSON to download client_secrets.json.
  5. Save client_secrets.json to WAR/WEB-INF directory
  6. Define the following methods in a Utils file
    1. public static GoogleClientSecrets getGoogleClientSecrets(ServletContext context)            throws InvalidClientSecretsException {
              GoogleClientSecrets secrets;
              try {
                  secrets = GoogleClientSecrets.load(JSON_FACTORY,
                          getClientSecretsStream(context));
              } catch (IOException e) {
                  throw new InvalidClientSecretsException(
                          "client_secrets.json is missing or invalid.");
              }
              return secrets;
          } 
    2. public static Oauth2 getOauth2Service(Credential credentials) {
              HttpTransport httpTransport = new NetHttpTransport();
              JsonFactory jsonFactory = new JacksonFactory();
              return new Oauth2.Builder(httpTransport, jsonFactory, credentials).build();
          }
    3. public static AuthorizationCodeFlow getAuthorizationCodeFlow(ServletContext context) {
                final List<String> SCOPE = Arrays.asList(
                      // Required to access and manipulate files.
                      "https://www.googleapis.com/auth/drive.file",
                      // Required to identify the user in our data store.
                      "https://www.googleapis.com/auth/userinfo.email",
                      "https://www.googleapis.com/auth/userinfo.profile");
                 HttpTransport httpTransport = new NetHttpTransport();
                 JsonFactory jsonFactory = new JacksonFactory();
                 GoogleAuthorizationCodeFlow flow = null;
                 try {
                  GoogleClientSecrets clientSecrets = getGoogleClientSecrets(context);
                  GoogleAuthorizationCodeFlow.Builder builder = new GoogleAuthorizationCodeFlow.Builder(
                          httpTransport, jsonFactory, clientSecrets, SCOPE)
                          .setAccessType("online")
                          .setApprovalPrompt("force");
                 
                  builder.setCredentialStore(credentialStore);
                  flow = builder.build();
                  } catch (InvalidClientSecretsException e) {
                      e.printStackTrace();
                  }
                 return flow;
              }
    4.  public static String getRedirectURL(ServletContext context) {
              String redirectURL = "";
              GoogleClientSecrets clientSecrets;
              try {
                  clientSecrets = getGoogleClientSecrets(context);
                  redirectURL = clientSecrets.getWeb().getRedirectUris().get(0);
              } catch (InvalidClientSecretsException e) {
                  e.printStackTrace();
              }
              return redirectURL;
       }
    5. public static UserDetails loginSuccessful(ServletContext context, HttpServletRequest request) {
              UserDetails userDetails = null;

              StringBuffer fullUrlBuf = request.getRequestURL();
              if (request.getQueryString() != null) {
                fullUrlBuf.append('?').append(request.getQueryString());
              }

              try {
                  AuthorizationCodeResponseUrl authResponse =
                      new AuthorizationCodeResponseUrl(fullUrlBuf.toString());
                  // check for user-denied error
                  if (authResponse.getError() != null) {
                      login = false;
                  } else {
                      String code = authResponse.getCode();
                      if(code != null) {

                          /* Get the Token */
                          String redirectURL = getRedirectURL(context);
                          GoogleTokenResponse tokenResponse = (GoogleTokenResponse) Utils.getAuthorizationCodeFlow(context).newTokenRequest(code).setRedirectUri(redirectURL).execute();
                          GoogleCredential credential = new GoogleCredential().setFromTokenResponse(tokenResponse);

                          /* Get the UserInfo */
                          Oauth2 oauth = Utils.getOauth2Service(credential);
                          Userinfo about = oauth.userinfo().get().execute();
                          userDetails = new UserDetails();
                          userDetails.setEmail(about.getEmail());
                          userDetails.setName(about.getName());
                          /* Create and Store the Token */
                          Utils.getAuthorizationCodeFlow(context).createAndStoreCredential(tokenResponse, userDetails.getEmail());
                          login = true;
                      }
                  }
              } catch (Exception ex) {
                  ex.printStackTrace();
              }      
              return userDetails;      
          }
  7.  On click of 'Login with Google', call the following snippet of code GoogleAuthorizationCodeFlow flow = (GoogleAuthorizationCodeFlow)Utils.getAuthorizationCodeFlow(context);
               String redirectURL = Utils.getRedirectURL(context);
               String url = flow.newAuthorizationUrl().setRedirectUri(redirectURL).build();
               open(url); //go to the URL
     
  8.  In your Servlet, ensure you have the following code   
public class MyServlet extends GAEVaadinServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            VaadinSession vaadinSession = null;
            if(VaadinSession.getCurrent() == null) {
                vaadinSession = getService().findVaadinSession(createVaadinRequest(request));
            } else {
                vaadinSession = VaadinSession.getCurrent();
            }
            ServletContext context = this.getServletContext();
            WrappedSession wSession = vaadinSession.getSession();
            if(wSession != null && wSession.getAttribute("userDetails") == null) {
                UserDetails userDetails = Utils.loginSuccessful(context, request);
                wSession.setAttribute("userDetails", userDetails);
            }
        } catch (ServiceException e) {
            e.printStackTrace();
        } catch (SessionExpiredException e) {
            e.printStackTrace();
        }
        super.service(request, response);
    }
}



    Important Links
    https://developers.google.com/console/help/new/#generatingoauth2
    https://code.google.com/p/google-api-java-client/wiki/OAuth2
    https://developers.google.com/accounts/docs/OAuth2

    Drop me a comment if you are facing any issues.

    Good Luck!




    1 comment:

    1. Hello, thanks for the tutorial! Which are the required libraries to make it work? Can you provide us with the Maven/Ivy dependencies? Thank you

      ReplyDelete