2

I am trying to authenticate linkedin users for my site. I am using Scribe to handle the authentication.

I am trying to do this in a two step process.

step1 just gets the correct url and redirects the user to the confirmation page. this is working fine. and after I confirmed I am redirected back to a page on my site.

step 2 is the one I am having problem with. when the redirected xpage is opening I am calling the step2 method using the token and verifyer key from the url.

One thing that I do not get is if I really need to build the service in both steps and if this is what is causing my problems. how do I send the requestToken between my two steps. please advice how to get this scenario working

Thanks - Thomas


import org.scribe.builder.ServiceBuilder;
import org.scribe.oauth.OAuthService;
import java.util.Scanner;
import org.scribe.builder.*;
import org.scribe.model.*;
import org.scribe.oauth.*;
import org.scribe.builder.api.*;
import javax.faces.context.*;


public class DoDance
{
      private static final String PROTECTED_RESOURCE_URL = "http://api.linkedin.com/v1/people/~/connections:(id,last-name)";

  public void step1()
  {
     try {
            OAuthService service = new ServiceBuilder()
            .provider(LinkedInApi.class)
            .apiKey("key")
            .apiSecret("secret")
            .callback("http://www.acme.com/linkedin.xsp")
            .build();

        Token requestToken = service.getRequestToken();
        String authUrl = service.getAuthorizationUrl(requestToken);

        // Redirects the user to linkedin confirmation page
        // This is working fine
        FacesContext.getCurrentInstance().getExternalContext().redirect(authUrl);

    } catch (Exception e) {
        e.printStackTrace(); 
    }
  }

  public String step2(String tok,String ver){

      // this method is called in the beforeRenderResponse in the redirected xpage
      // I get the token and verifyer in from the url parameters

    Response response = null;
    try {
          OAuthService service = new ServiceBuilder()
          .provider(LinkedInApi.class)
          .apiKey("key")
          .apiSecret("secret")
          .build();

          Token accessToken = service.getAccessToken(???,new Verifier(ver));
          OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
          service.signRequest(accessToken, request);
          response = request.send();

    } catch (Exception e) {
        e.printStackTrace();
    }
    return "Body = " + response.getBody();

  }


}
Thomas Adrian
  • 3,543
  • 6
  • 32
  • 62
  • 2
    Did you take a look at social enabler plugin? – jjtbsomhorst Mar 22 '12 at 07:01
  • yes I did, the social enabler is closely tied to a key store. so you can't use it if you want another solution. – Thomas Adrian Mar 22 '12 at 07:14
  • If you need to pass the requestToken to step 2 you could create a (session scoped) userBean and store it there. – Mark Leusink Mar 22 '12 at 08:57
  • The code above is already a session scoped bean, I have tried to set the Token as field in the class and set it in step1, but when I call step 2 I get null pointer exception when calling the Token. – Thomas Adrian Mar 22 '12 at 10:10
  • @ThomasAdrian: save the request token either in the database or in the session and when your user is getting redirected back all you need to take out this from the session – Umesh Awasthi Mar 22 '12 at 11:47

2 Answers2

4

Try storing and retrieving the requestToken in a (session scoped) user bean.

public class User {

private Token requestToken;

private static String BEAN_NAME = "userBean";

public static User get() {
    FacesContext context = FacesContext.getCurrentInstance();
    return (User) context.getApplication().getVariableResolver().resolveVariable(context, BEAN_NAME);
}

public Token getRequestToken() {
    return requestToken;
}

public void setRequestToken(Token requestToken) {
    this.requestToken = requestToken;
}


}

You'll also probably need to change the JVM's security settings to use Scribe. Add this to the Domino server's java.policy file:

grant {
permission java.util.PropertyPermission
"http.keepAlive", "read, write";
};

Finally: you don't need to pass the token and verifier from the beforeRenderResponse event. They can easily be retrieved in the step2 function using

XSPContext context = XSPContext.getXSPContext( FacesContext.getCurrentInstance() );
String oauth_verifier = context.getUrlParameter("oauth_verifier");
Mark Leusink
  • 3,747
  • 15
  • 23
2

Don't try to reinvent the wheel. The social enabler does exactly this and much more.

Here is some early doc I wrote: http://www.openntf.org/Projects/pmt.nsf/DA2F4D351A9F15B28625792D002D1F18/%24file/SocialEnabler111006.pdf

Re "social enabler is closely tied to a key store" - this is in fact a big benefit. If you want to do more than a prototype you need to come up with a solution how and where to centrally manage both app keys and user keys.

You also don't want to put this OAuth dance code in every NSF, but use the social enabler plugin which can be deployed globally.

We're tried social enabler with LinkedIn and it works. We were just not allowed to open source this sample.

Niklas Heidloff
  • 952
  • 6
  • 13
  • 1
    Ok, this is valuable information, but hardly the answer to this question. For the record. I did not reinvent the wheel. Scribe is easy to understand and very little code is needed and I have full control. – Thomas Adrian Mar 23 '12 at 07:57
  • Thomas, using an OAuth library is not the problem. Managing the keys and using the same infrastructure for various apps is. I understand that this doesn't answer how to use Scribe but I recommend to use the social enabler. – Niklas Heidloff Mar 23 '12 at 11:32
  • Real pity that you're not allowed to release the LinkedIn code. I've also looked at the social enabler and agree with Thomas in that Scribe is easier to get started with: that's probably because of the simple samples they provide. – Mark Leusink Mar 25 '12 at 19:02