Share / Save this...

Share/Bookmark

2010-11-19

GWT + Struts 1.x + Netbeans Tutorial (Part 8c)




<c:choose>
     <c:when test="${user.likes}"
          Share this with your friends
     </c:when>
     <c:otherwise>  
          Send me feedback.
     </c:otherwise>
<:choose>
oDesk Certified Java Developer

The algorithms to make the authorization flow described in the previous 2 parts of this chapter are simple and they provide for tweaking and the usual stakeholder requisite changes.

First the core of our filter, how to know in which part of the authorization flow through which the user is in transit:

  • Returning authorized user(1)
  • Everyone else(2)
    • After authorization prompt(2.1)
      • Authorized(2.1.1)
        • Canvas(2.1.1.1)
        • Site(2.1.1.2)
      • Not Authorized(2.1.2)
        • Canvas(2.1.2.1)
        • Site(2.1.2.2)
    • Canvas(2.2)
      • UserId(2.2.1)
        • ProfileId(2.2.1.1)
        • No profileId(2.2.1.2)
      • No UserId(2.2.2)
    • Site(2.3)

Now let me explain how to know and what parameters to check to know in which part of that tree the user is located and what you might do after that:

(1)access_token present in session
Retrieve user information using access_token
(2)access_token not present in session
(2.1)requestURL == redirect_uri
(2.1.1)code parameter present
Retrieve "access_token" using "code"
Store "access_token" in session
(2.1.1.1)source parameter == canvas
Redirect to canvas
(2.1.1.2)source parameter == site
Continue to site
(2.1.2)error_reason parameter present
log error reson
(2.1.2.1)source parameter == canvas
Redirect to canvas with onclick auth link
(2.1.2.2)source parameter == site
Continue to site with regular auth link
(2.2)signed_request parameter present
Decode signed request
(2.2.1)userId present in signed_request
Retrieve user information using access_token
(2.2.1.1)profileId present in signed_request
Retrieve user information using access_token
(2.2.1.2)profileId not present in signed_request
Retrieve user information using access_token
(2.2.2)userId not present in signed_request
Redirect to canvas with onclick auth link
(2.3)signed_request parameter not present
Continue to site with regular auth link

To decode the signed_request you need to use a Base64 decoder which handles URLsafe decoding. After decoding use class javax.crypto.Mac to get a Message Authentication Code for the algorithm passed in the JSON decoded signed_request. Use your aplication secret (known only to you as a developer) and sign the JSON payload of the signed request and compare it to the decoded signature. If they match then you can rest assured the signed_request comes from the Facebook servers.


A few things to keep in mind which will be important when you test your code: use the EXACT same redirect_uri (including the source parameter) to retrieve the access_token. This was clearly stated in the documentation even from the early stages of the migration to the new Graph API, it helped me a lot to remember it. I used all the parameters used by Facebook (appId, appSecret, appKey, redirectUri, canvasUrl, siteUrl) as init parameters of the filter to be able to reuse the filter for other applications without changing code, and just changing those init parameters in the xml configuration.

If you have any suggestions, ideas for full blown system integration (sb) or comments, leave a message below.
I would appreciate if you could Share this with your friends



GWT + Struts 1.x + Netbeans Tutorial (Part 8b)



<c:choose>
     <c:when test="${user.likes}"
          Share this with your friends
     </c:when>
     <c:otherwise>  
          Send me feedback.
     </c:otherwise>
<:choose>
oDesk Certified Java Developer

Now that we know where was the user before we redirected him/her to the authorization prompt, we know the structure of our redirect_uri. After decoding (Base64) the Signed Request then we need to look for an attribute named "user_id", if this attribute is not present then the user has not yet authorized our application to access their information. In the first draft I decided to do an automatic redirection to the authorization prompt but then I thought about it and I chose not allow the user to have control over the flow; never force the user to do things if you don't know whether they want to do them or not.

In this design a simple Facebook logo with a link to the authorization prompt will be displayed to let the user decide to link their profile information to our application or to browse the application as a guest user. In the canvas version the link provides an onclick event handler to set the window.top.location and in the web application version a regular link.

Now, how to know if the user authorized our application after the prompt? The user is going to be redirected to the redirect_uri you provide and the parameters passed to this uri are the key. If you get a "code" parameter then the user authorized the app, if you get an "error_reason" parameter (along with other error parameters) then the user did not authorize it. In the filter I check if the requested URL is the redirect_uri and then I do 2 things, first i look for the "source" parameter I passed along with the redirect_uri to know where to send the user after I retrieve their access token which provides us with a means to know the information they have allowed us to access, second I look for the "code" or "error_reason" parameters and if the "code" parameter is present then we need to exchange it for an access token by fetching a URL (web service) and parsing the (JSON) response. If the "error_reason" is present then we can log the error reason, nothing much after that. The filter redirects the user to the canvas if the "source" parameter is canvas or simply continues to the regular flow if the "source" is site.

That covers, on an eagle-view, the canvas authorization process, now the web app authorization process and at the end of this chapter there will be a detailed design for the filter.

The web app authorization process is now more simple since we made the canvas authorization process practically the same by providing a link to the authorization prompt. The difference comes in the JSP file, if you find a "signed_request" parameter then the user is coming from canvas and we need to use an onclick event to set "window.top.location=<fb_auth_url>" and if it's not present then a regular link to the fb_auth_url.

The rest is the same because we now took the common parts of the authorization and the only thing that changes can be decided by checking the "source" parameter and redirecting to the relevant page accordingly. After we have fetched the access_token (the user authorized our application to access their information) we need to store it for safe-keeping and to avoid going through the whole process each time the user comes to our application. It's is so that now we need to change the first part of our algorithm, we need to check if the access_token is present for the current visitor and if it's not then provide a link to the authorization flow.

That's all there is to it on paper, now on the next section the relevant algorithms to decide in which part of the authorization process currently the user is going through, how to parse the "signed_request" parameter, how to verify the encoded signature and how to fetch the "acccess_token" after the user has authorized us.


If you have any suggestions, ideas for full blown system integration (sb) or comments, leave a message below.
I would appreciate if you could Share this with your friends

GWT + Struts 1.x + Netbeans Tutorial (Part 8a)




<c:choose>
     <c:when test="${user.likes}"
          Share this with your friends
     </c:when>
     <c:otherwise>  
          Send me feedback.
     </c:otherwise>
<:choose>
oDesk Certified Java Developer
Part 8: Facebook Authentication (Canvas + Web Application)

If you're a curious developer, as I suppose you are, then you probably are always on a quest for new APIs and new ways of making your work easier to accomplish. Facebook has a platform to publish your work and expose it to millions of potential users. It provides a range of options from low-level (low-level for an experienced developer like you) badges and widgets like those you can find scattered around this blog post to full-fledged database persistence, JSON-based web services, and the like (pun intended ;D).

In this part of the tutorial i'll try to explain my <adjective related to pain here> experience in hopes of preventing others from falling in the same pits. When i started working on the integration of a website with the Facebook platform, the process of authentication and app authorization was in the process of change. My experience was not the greatest because of all the rapid changes happening to the authentication and authorization flow needed for your application to communicate with the Facebook servers to request user info and do all the nice things you probably have in mind to provide a great user experience.

There are 3 ways of integrating with the Facebook platform: as a canvas app, as a web application, or as a standalone application (a.k.a. desktop app). I was integrating a website so the 3rd option would be left for a future development cycle, if at all. After going through the documentation provided by Facebook I was wondering where to find an Aramaic translator, it's understandable (NOT) that they didn't have a stable design at the time as they were going through the authentication process change (they were changing to OAuth2.0). So I decided to go with the flow and work the Facebook way (trial and error until something works). I took the little that could be salvaged of the documentation and started coding according to their explanation of what needed to be done, and all the interaction between the different actors.

After a couple of days working with the code I got to an acceptable solution, involving a filter, a servlet and a jsp. I decided (more like deciphered, amirite?) the phase in the authentication process in the filter, did the heavy-lifting in the servlet and then provided the view in the jsp. As time went by the solution broke with all the changes going on on the FB side of the process so i decided to go through the documentation again and to design a solution flexible enough to withstand the changes and that provided for future tweaking as it evolved. Always keep that in mind in your designs, evolution and change.

The final solution involved just a filter which does all the heavy-lifting and would act as a Facebook client. Now the part you're looking for is how to organize the workflow. After reading the documentation again I noticed it had changed and it now provided a few hints to common pitfalls (some I found along the way) and I decided to dissect it. A user arrives and it can view your website through the FB canvas or through the regular Internet. The way to know which version the user is currently viewing is to look for the Signed Request parameter. After you know the version then you know how to request for authorization from the user to access their information. In the canvas version you can't simply redirect the user to the authorization screen because the screen is going to be inside an iframe and a bug (hopefully in the future it'll be solved) prevents the auth prompt from showing up, so I decided to do an ol' "window.top.location=" to redirect the user to the relevant location. This introduces an issue, you need to pass a redirect_uri for the auth prompt to redirect the user after he/she has made the choice to allow us to access (or not) their information. I solved this by appending a "source" parameter at the end of the redirect_uri: source=canvas or source=site.

In the next section we'll continue dissecting and solving the small parts involved in integrating a website with the Facebook platform.



If you have any suggestions, ideas for full blown system integration (sb) or comments, leave a message below.

I would appreciate if you could Share this with your friends



Hits