iSwitched

After 5 years of using different Android phones I switched to an iPhone. In 2009 I bought an HTC Hero, which was replaced by the HTC Desire a year later. Then my former employer gave me a Samsung Galaxy S2 which was replaced by the S3 after I switched jobs. I was about to switch to the Sony Xperia Z3 but I decided to go for an iDevice: the iPhone 6.

What do I miss in iOS so far?

Going back

I miss the back button on the phone. In iOS it’s up to the application to provide a back link somewhere in the screen. Usually in the top left corner, but sometimes it’s not there. That top left corner is hard to reach with one hand and Apple has created a workaround for that: tap (not click) the home button twice and the screen goes down so you can reach this button. Adding that extra physical button would have been easier. Another difference is that the back button is only within the context of the current application while the Android back button can bring you back to the previous application if that had opened another application.

No widgets on the home screen

When I opened the S3 I saw the latest weather information on my home screen. On the next screen I had an monthly overview of my calendar. On the iPhone there are only app icons. The weather and upcoming appointments for today are in the Notification Centre. It’s not in my system yet to open the Notification Centre or the Calendar app to see what’s on my schedule for the next week/month (and yes I already forgot an appointment).

Swype

It was one of the first apps I bought, but unfortunately there’s no dictionary available for Dutch yet. Let’s hope that’s just a matter of time, because Swype supports many more languages in the Android version.

Notification LED

The S3 had a blinking LED to notify me of unread messages: dark blue for mail and SMS, light blue for WhatsApp and green for Telegram and purple for MeetUp. It kept flashing until I took action to read the message or remove the notification. The iPhone blinks shortly when a message arrives, but that’s it. I don’t have my phone on me all of the time and sometimes I don’t hear or feel it, so that blinking LED was handy.

What is better?

Integration with iTunes

Samsung, I like your devices but Kies sucks. Most of the time it starts, but not always. When it has started it may or may not recognise the phone. After sacrificing a goat to the gods of Samsung it may also finish a back up successfully. More often it failed in the back up (luckily I never needed a restore) or didn’t recognise the phone. The KiesViaWifiAgent was turning my MacBook into a heating fan. iTunes just works. It recognises the phone, makes back ups and installs iOS updates.

Touch ID

The US department of Homeland Security took prints of all my fingers when I wanted to enter the US. The Dutch government wanted 2 finger prints for my new passport.  Now Apple also has a finger print of me to unlock my phone or authorise purchases (but I have no clue what else they do with it).

Permissions

I didn’t switch because of the Apple logo. Although I’ve been a fan of Apple’s desktop OS since System 6, I’ve never been attracted to the iOS. The main reason I switched from Android to iOS are the permissions apps get. In Android it’s an all or nothing decision. For instance the Facebook app wants access to my contacts, calendar, SMS and call history (and a lot more). If you don’t want to give permission to let the app access your SMS history, then you can’t install the app. This is different in iOS, where you as user can control whether the app gets access to your contacts or calendar (SMS and call history are normally inaccessible by apps). More information is in the article iOS Has App Permissions, Too: And They’re Arguably Better Than Android’s.

Posted in Apple, Technology

Retrieve Facebook profile data in Java: Apache Oltu

In previous blogposts I explained how you can get Facebook profile data using Scribe or Spring Social for the OAuth 2 handling. In this article you can read how to get the profile using Apache Oltu (formerly known as Apache Amber).

Update: browsing through the source of Apache Oltu I found an enum for the provider endpoints which wasn’t mentioned in the documentation.

Setup

The Maven dependency for the Apache Oltu OAuth client:

<dependency>
  <groupId>org.apache.oltu.oauth2</groupId>
  <artifactId>org.apache.oltu.oauth2.client</artifactId>
  <version>0.31</version>
</dependency>

The setup for the controller:

@Controller
public class FacebookOltuAuthenticator {

  private final String clientId;
  private final String clientSecret;
  private final String applicationHost;
  private final ObjectMapper objectMapper;

  @Autowired
  public FacebookOltuAuthenticator(
      @Value("#{properties['facebook.clientId']}") 
       String clientId,
      @Value("#{properties['facebook.clientSecret']}") 
       String clientSecret,
      @Value("#{properties['application.host']}") 
       String applicationHost) {
    this.clientId = clientId;
    this.clientSecret = clientSecret;
    this.applicationHost = applicationHost;
    this.objectMapper = new ObjectMapper();
    this.objectMapper.registerModule(new AfterburnerModule());
  }
}

Start the authentication

Scribe and Spring Social have classes that know the endpoint for the authorization. Currently Apache Oltu doesn’t have such convenience classes which means we have to provide the URL for the authorization endpoint. Apache Oltu has an enum OAuthProviderType for authorization and token endpoints of common OAuth 2 providers.

@RequestMapping("/auth/facebook")
public RedirectView startAuthentication(HttpSession session) 
    throws OAuthSystemException {
  String state = UUID.randomUUID().toString();
  session.setAttribute(OAuth.OAUTH_STATE, state);
  OAuthClientRequest oAuthClientRequest = OAuthClientRequest
      .authorizationProvider(OAuthProviderType.FACEBOOK)
      .setClientId(clientId)
      .setRedirectURI(applicationHost + "/auth/facebook/callback")
      .setParameter(OAuth.OAUTH_STATE, state)
      .buildQueryMessage();

   return new RedirectView(oAuthClientRequest.getLocationUri());
}

Handle the callback

Apache Oltu has a helper class to get the authorization response from the HttpServletRequest, which means we don’t have to define the code and state parameters in the method signature.

@RequestMapping("/auth/facebook/callback")
public RedirectView callback(HttpServletRequest request, HttpSession session) 
    throws IOException, OAuthSystemException, OAuthProblemException {
  String stateFromSession = (String) session.getAttribute(OAuth.OAUTH_STATE);
  session.removeAttribute(OAuth.OAUTH_STATE);

  OAuthAuthzResponse oar = OAuthAuthzResponse.oauthCodeAuthzResponse(request);
  String stateResponse = oar.getState();

  if (StringUtils.isBlank(stateResponse) || 
       !stateResponse.equals(stateFromSession)) {
    return new RedirectView("/login");
  }

  OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
  String accessToken = getAccessToken(oar, oAuthClient);

  OAuthResourceResponse resourceResponse = 
      getFacebookProfileResponse(oAuthClient, accessToken);
  if (resourceResponse.getResponseCode() != HttpServletResponse.SC_OK) {
    return new RedirectView("/login");
  }

  String facebookUserId = getFacebookUserId(resourceResponse);
  session.setAttribute("facebookUserId", facebookUserId);

  return new RedirectView("/logged-in");
}

Retrieve the AccessToken

Apache Oltu has two different classes to parse the access token response. Facebook’s response is not fully compliant with the final version of the OAuth 2 specification, but it can be parsed using the class GitHubTokenResponse.

We have to tell Apache Oltu which URL can exchange the authorization code for an access token, because there’s no Facebook specific implementation yet.

private String getAccessToken(OAuthAuthzResponse oar, OAuthClient oAuthClient)
    throws OAuthSystemException, OAuthProblemException {
  String code = oar.getCode();
  OAuthClientRequest oAuthClientRequest = OAuthClientRequest
    .tokenProvider(OAuthProviderType.FACEBOOK)
    .setGrantType(GrantType.AUTHORIZATION_CODE)
    .setClientId(clientId)
    .setClientSecret(clientSecret)
    .setRedirectURI(applicationHost + "/auth/facebook/callback")
    .setCode(code)
    .buildQueryMessage();

  GitHubTokenResponse oAuthResponse = oAuthClient.accessToken(
    oAuthClientRequest, GitHubTokenResponse.class);
  return oAuthResponse.getAccessToken(); 
}

Get the Facebook profile data

First we get the profile as JSON:

private OAuthResourceResponse getFacebookProfileResponse(
    OAuthClient oAuthClient, String accessToken)
    throws OAuthSystemException, OAuthProblemException {
  OAuthClientRequest bearerClientRequest =
      new OAuthBearerClientRequest("https://graph.facebook.com/me")
          .setAccessToken(accessToken).buildQueryMessage();

   return oAuthClient.resource(bearerClientRequest, OAuth.HttpMethod.GET,
      OAuthResourceResponse.class);
}

Just like we did with Scribe, we use Jackson to extract the user id from the JSON response:

private String getFacebookUserId(OAuthResourceResponse resourceResponse) 
    throws IOException {
  String resourceResponseBody = resourceResponse.getBody();
  JsonNode jsonNode = objectMapper.readTree(resourceResponseBody);
  JsonNode idNode = jsonNode.get("id");
  return idNode.asText();
}

Conclusion

As you can see, a lot more knowledge of the OAuth 2 flow and the specific endpoints are is needed to make this implementation with Apache Oltu. It would help developers if convenience classes are added for the larger OAuth 2 providers as Facebook, Google etc. On the other hand it does help you understand better how the flow works. When you have implemented it once, you can add any other OAuth 2 provider by changing endpoints and the way the profile is parsed from the JSON response.

Posted in Development, Geen categorie, Social Media, Technology, tools Tagged with: , , , , ,

Retrieve Facebook profile data in Java: Spring Social

In the previous blogpost I explained how you can get Facebook profile data using Scribe. This blogpost will do the same for Spring Social.

Setup

The Maven dependency for Spring Social Facebook:

<dependency>
  <groupId>org.springframework.social</groupId>
  <artifactId>spring-social-facebook</artifactId>
  <version>1.0.3.RELEASE</version>
</dependency>

Setup of the Spring controller:

@Controller
public class FacebookSpringSocialAuthenticator {
  public static final String STATE = "state";
  private String applicationHost;
  private FacebookConnectionFactory facebookConnectionFactory;

  @Autowired
  public FacebookSpringSocialAuthenticator(
      @Value("#{properties['facebook.clientId']}") 
        String clientId,
      @Value("#{properties['facebook.clientSecret']}") 
        String clientSecret,
      @Value("#{properties['application.host']}") 
        String applicationHost) {
    this.applicationHost = applicationHost;
    facebookConnectionFactory = 
      new FacebookConnectionFactory(clientId, clientSecret);
  }
}

Start the authentication

@RequestMapping("/auth/facebook")
public RedirectView startAuthentication(HttpSession session) 
    throws OAuthSystemException {
  String state = UUID.randomUUID().toString();
  session.setAttribute(STATE, state);

  OAuth2Operations oauthOperations = 
      facebookConnectionFactory.getOAuthOperations();
  OAuth2Parameters params = new OAuth2Parameters();
  params.setRedirectUri(applicationHost + "/auth/facebook/callback");
  params.setState(state);

  String authorizeUrl = oauthOperations.buildAuthorizeUrl(
      GrantType.AUTHORIZATION_CODE, params);
  return new RedirectView(authorizeUrl);
}

Handle the callback

@RequestMapping("/auth/facebook/callback")
public RedirectView callBack(@RequestParam("code") String code,
                             @RequestParam("state") String state,
                             HttpSession session) {
  String stateFromSession = (String) session.getAttribute(STATE);
  session.removeAttribute(STATE);
  if (!state.equals(stateFromSession)) {
    return new RedirectView("/login");
  }

  AccessGrant accessGrant = getAccessGrant(code);

  String facebookUserId = getFacebookUserId(accessGrant);
  session.setAttribute("facebookUserId", facebookUserId);
  return new RedirectView("/logged-in");
}

Retrieve the AccessGrant

private AccessGrant getAccessGrant(String authorizationCode) {
  OAuth2Operations oauthOperations = 
      facebookConnectionFactory.getOAuthOperations();
  return oauthOperations.exchangeForAccess(authorizationCode,
      applicationHost + "/auth/facebook/callback", null);
}

Get the Facebook user id

Spring social splits up the profile response into several classes. With Connection#fetchUserProfile you get the username, but not his identifier, which is retrieved with Connection#getKey.

private String getFacebookUserId(AccessGrant accessGrant) {
  Connection<Facebook> connection = 
      facebookConnectionFactory.createConnection(accessGrant);
  ConnectionKey connectionKey = connection.getKey();
  return connectionKey.getProviderUserId();
}

Conclusion

Spring Social has built in methods to convert the JSON response of the profile into Java objects which Scribe doesn’t do for you. Its setup is a bit simpler and there are no traces of OAuth 1 support in the Facebook classes. Spring social seems to handle the flow a bit slower (200-300 ms slower) than Scribe.

Posted in Development, Geen categorie, Social Media, Technology, tools Tagged with: , , ,

Retrieve Facebook profile data in Java: Scribe

In a series of blogposts I’ll describe how to retrieve a Facebook profile using several OAuth2 libraries for Java and Spring MVC. The first example is for Scribe.

Setup

The Maven dependency for Scribe:

<dependency>
    <groupId>org.scribe</groupId>
    <artifactId>scribe</artifactId>
    <version>1.3.5</version>
</dependency>

First you need to register an application with Facebook. Then add an HTML snippet to your site that triggers the login flow:

<a href="/auth/facebook">Get my Facebook profile</a>

We create a Spring Controller and inject the Facebook client id, client secret and the host of our application:

@Controller
public class FacebookScribeAuthenticator {

  public static final String STATE = "state";
  private String applicationHost;
  private OAuthService oAuthService;
  // Jackson ObjectMapper
  private ObjectMapper objectMapper;

  @Autowired
  public FacebookScribeAuthenticator(
      @Value("#{properties['facebook.clientId']}") 
      String clientId,
      @Value("#{properties['facebook.clientSecret']}") 
      String clientSecret,
      @Value("#{properties['application.host']}") 
      String applicationHost) {
    this.applicationHost = applicationHost;
    this.oAuthService = buildOAuthService(clientId, clientSecret);
    this.objectMapper = new ObjectMapper();
    this.objectMapper.registerModule(new AfterburnerModule());
  }
}

private OAuthService buildOAuthService(String clientId, 
                                       String clientSecret) {
  // The callback must match Site-Url in the Facebook app settings
  return new ServiceBuilder()
      .apiKey(clientId)
      .apiSecret(clientSecret)
      .callback(applicationHost + "/auth/facebook/callback")
      .provider(FacebookApi.class)
      .build();
  }
}

Start the authentication

Now we add a @RequestMapping to start the OAuth2 authorization flow. To prevent CSRF we add and store a state parameter that should be returned by Facebook. Scribe doesn’t handle this parameter in its API, so we have to add it to the authorization URL.

@RequestMapping("/auth/facebook")
public RedirectView startAuthentication(HttpSession session) 
    throws OAuthSystemException {
  String state = UUID.randomUUID().toString();
  session.setAttribute(STATE, state);
  String authorizationUrl = 
      oAuthService.getAuthorizationUrl(Token.empty()) 
        + "&" + STATE + "=" + state;
  return new RedirectView(authorizationUrl);
}

When the user goes to /auth/facebook, he is redirected to the Facebook authentication URL. If it’s his first visit, he has to approve the access to his data for your application:

Facebook approval

Handle the callback

After the user has approved the access to his profile, he is redirected to our callback endpoint with two request parameters: code and state. The code is the authorization code that can be exchanged for an access token. The state parameter should have the same value as we have sent to Facebook in the authorization request.

In case of failure we redirect the user to /login. If we can retrieve the user’s Facebook user id successfully, he is redirected to /logged-in.

@RequestMapping("/auth/facebook/callback")
public RedirectView callback(@RequestParam("code") String code,
                             @RequestParam(STATE) String state,
                             HttpSession session) 
      throws IOException {
  // Check the state parameter
  String stateFromSession = (String) session.getAttribute(STATE);
  session.removeAttribute(STATE);
  if (!state.equals(stateFromSession)) {
    return new RedirectView("/login");
  }

  // Exchange the code for an AccessToken and retrieve the profile
  Token accessToken = getAccessToken(code);
  Response response = getResponseForProfile(accessToken);
  if (!response.isSuccessful()) {
    return new RedirectView("/login");
  }

  // Store the Facebook user id in the session and redirect the user
  // to the page that needs the profile.
  String facebookUserId = getFacebookUserId(response);
  session.setAttribute("facebookUserId", facebookUserId);
  return new RedirectView("/logged-in");
}

Retrieve the AccessToken

The Token.empty() is passed because Scribe’s OAuthService handles both OAuth1 and OAuth2 providers.

private Token getAccessToken(String code) {
  Verifier verifier = new Verifier(code);
  return oAuthService.getAccessToken(Token.empty(), verifier);
}

Get the Facebook profile data

Anyone can access the public profile data for https://graph.facebook.com/<userId>, but you need to be logged in to get https://graph.facebook.com/me

private Response getResponseForProfile(Token accessToken) {
  OAuthRequest oauthRequest = 
      new OAuthRequest(Verb.GET, "https://graph.facebook.com/me");
  oAuthService.signRequest(accessToken, oauthRequest);
  return oauthRequest.send();
}

Facebook will return the profile as JSON (I know, this is not my profile):

{
 "id":"4",
 "name":"Mark Zuckerberg",
 "first_name":"Mark",
 "last_name":"Zuckerberg",
 "link":"https:\/\/www.facebook.com\/zuck",
 "username":"zuck",
 "gender":"male",
 "locale":"en_US"
}

We use Jackson to get the Facebook identifier from the JSON response:

private String getFacebookUserId(Response response) 
    throws IOException {
  String responseBody = response.getBody();
  JsonNode jsonNode = objectMapper.readTree(responseBody);
  JsonNode idNode = jsonNode.get("id");
  return idNode.asText();
}

Now you have the Facebook user id in the HttpSession. In the next blogposts I’ll explain how to do this with other Java libraries.

Posted in Development, Geen categorie, Social Media, Technology, tools Tagged with: , ,

WidgetGap: a Wookie & Cordova (PhoneGap) mashup widget

WidgetGap icon

I knew PhoneGap as a tool to make native mobile apps from HTML, CSS and JavaScript, but had never used it myself. When I had to debug a PhoneGap application I read that the project you’re uploading is basically a W3C widget. I should have known from Scott’s blogpost, but apparently I forgot. I did remember that Apache Wookie is responsible for rendering W3C widgets in Apache Rave.

WidgetGap iconI decided to make my own demo widget called WidgetGap, that can be used for making both a mobile app and a widget in Rave. Then I started a new iOS project for Apache Cordova (the open source project behind PhoneGap). If you don’t develop in OSX, pick a getting started guide that works on your machine.

I copied the result of a JSON call to the REST API of the Hippo Go Green demo in a Javascript variable to process that into the HTML. I chose this local variable because I didn’t want to call the REST interface over and over again just to get my markup right. After modifying the CSS it was time to replace the local resultset with a real AJAX call. The app and Wookie widget refuse to fetch the data because it’s a call to a different domain. Luckily there are solutions for this. For the mobile app you should add the following entry to the config.xml

<access origin="http://www.demo.onehippo.com"/>

For the iPhone simulator you also need to add this domain to the “External Hosts” entry in Resources/Cordova.plist file in the Xcode project.

For the Wookie widget I still didn’t get the data, but a few extra lines of Javascript made it work:

var loc = productLink;
if (window.widget && typeof window.widget.proxify == 'function') {
    loc = widget.proxify(loc);
}

Apart from issues with DOM manipulations in Javascript (not my expertise), I was able to create the widget that displayed a list of products from the Go Green REST interface with more detailed information when you click on the title.

Try it

The mobile app is available on PhoneGap (except for iOS because of Apple’s licensing policy).

To see the widget in Wookie, download and start the standalone version of Wookie.
In a different shell clone the WidgetGap repository from Github and go to the www folder. Package the contents and move this package to the deployment directory of the running Wookie instance:

git clone git://github.com/jashaj/WidgetGap.git
cd WidgetGap/www
zip -r widgetgap.wgt *
mv widgetgap.wgt ~/apache-wookie-0.11.0-incubating-standalone/build/webapp/wookie/deploy/

In the shell where you started Wookie you see the feedback about the deployment. If you see “‘WidgetGap’ – Widget was successfully imported into the system as WidgetGap” in the shell, you can view the widget it in your browser on http://localhost:8080/wookie/demo/.

The code is not optimised at all and maybe there is a better way to create this widget, but I wanted to show that you can write a single widget for the web and build a mobile app from it.

Posted in Apache, Apache Rave, Development, Front end technology, Geen categorie, Technology Tagged with: , ,

Archives

Categories