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!




    Thursday 27 March 2014

    Getting Spring ApplicationContext

    This post list down the steps to get Sprint ApplicationContext

    1. Create a class ApplicationContextProvider

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;

    public class ApplicationContextProvider implements ApplicationContextAware {
        private static ApplicationContext context;

        public static ApplicationContext getApplicationContext() {
            return context;
        }

        @Override
        public void setApplicationContext(ApplicationContext ctx) {
            context = ctx;
        }
    }

    2. Declare a bean in applicationContext.xml
        <bean id="applicationContextProvider" class="aa.bb.cc.ApplicationContextProvider"/>

    3. Get the ApplicationContext
            context = ApplicationContextProvider.getApplicationContext();

    Tuesday 18 March 2014

    Vaadin & Google App Engine

    Deploying your first Vaadin Application to Google App Engine.

    This blog demonstrates what you will need to deploy your Vaadin application to Google App Engine. In this exercise, I use eclipse kepler.

    Prerequisites: Please ensure you got the following plugins installed:
    1. Google Update Site for Eclipse 4.3 - http://dl.google.com/eclipse/plugin/4.3
    2. Vaadin Update Site for Eclipse - http://vaadin.com/eclipse

    Step1.
    Go to File --> New --> Project --> Vaadin 7 Project



    Step 2 - Select the options as shown in the screenshot.



    Step 3 - Select the default setting on the next set of screen and complete the creation of the project (Change it if you know what you are doing)

    Step 4 - Right click the project just created and select Properties

    Step 5 - Look for App Engine under Google



    Step 6 - Select 'Use Google App Engine' and put in your 'Application ID' and 'Version'


    Step 7 - Create a web.xml under war/WEB-INF

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        id="WebApp_ID" version="3.0">
        <display-name>HelloGoogle</display-name>
        <context-param>
            <description>Vaadin production mode</description>
            <param-name>productionMode</param-name>
            <param-value>false</param-value>
        </context-param>
        <servlet>
            <servlet-name>myservlet</servlet-name>
            <servlet-class>com.vaadin.server.GAEVaadinServlet</servlet-class>
            <init-param>
                <description>Vaadin UI</description>
                <param-name>UI</param-name>
                <param-value>com.example.hellogae.HellogaeUI</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>myservlet</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    </web-app>

     Step 8 - Go to Java Build Path -> Order and Export tab and change the order to look like as shown in the screenshot



    Step 9 - Make sure that the appengine-web.xml contains the "<threadsafe>true</threadsafe>"


    <?xml version="1.0" encoding="utf-8"?>
    <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
        <application>genieincloud</application>
        <version>1</version>
        <!-- Configure java.util.logging -->
        <system-properties>
            <property name="java.util.logging.config.file" value="WEB-INF/logging.properties" />
        </system-properties>
        <sessions-enabled>true</sessions-enabled>
        <threadsafe>true</threadsafe></appengine-web-app>


    Step 10 - Make sure that war/WEB-INF/lib has got the following JARs




    Step 11 - Right click, Google - > 'Deploy  to App Engine' -> Deploy




    Give it a minute. Your application should now be deployed to GAE


    That's it. That was simple enough. If you get into issues, drop me a comment. I'll try responding to it as soon as I can.

    rgds