<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Mike&#039;s Notes &#187; Java</title>
	<atom:link href="http://mrdwnotes.wordpress.com/category/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://mrdwnotes.wordpress.com</link>
	<description>Power, knowledge, wise guy</description>
	<lastBuildDate>Sat, 06 Oct 2012 17:26:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='mrdwnotes.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Mike&#039;s Notes &#187; Java</title>
		<link>http://mrdwnotes.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://mrdwnotes.wordpress.com/osd.xml" title="Mike&#039;s Notes" />
	<atom:link rel='hub' href='http://mrdwnotes.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Twitter Login to a Java Web Application</title>
		<link>http://mrdwnotes.wordpress.com/2011/11/29/twitter-login-to-a-java-web-application/</link>
		<comments>http://mrdwnotes.wordpress.com/2011/11/29/twitter-login-to-a-java-web-application/#comments</comments>
		<pubDate>Tue, 29 Nov 2011 23:35:47 +0000</pubDate>
		<dc:creator>mrmikewarren</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://mrdwnotes.wordpress.com/?p=170</guid>
		<description><![CDATA[Having taken  Bruce Phillips Shiro tutorial&#8217;s app and added a login via Facebook option I&#8217;m now going to have a bash at implementing a &#8220;log in via twitter&#8221; option, I then will hopefully be able to step back and see what generlisations might be appropriate to make some of the code more generic between Facebook [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mrdwnotes.wordpress.com&#038;blog=29808387&#038;post=170&#038;subd=mrdwnotes&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Having taken  <a title="http://www.brucephillips.name/blog/index.cfm/2009/4/5/An-Introduction-to-Ki-formerly-JSecurity--A-Beginners--Tutorial-Part-2" href="http://www.brucephillips.name/blog/index.cfm/2009/4/5/An-Introduction-to-Ki-formerly-JSecurity--A-Beginners--Tutorial-Part-2">Bruce Phillips Shiro tutorial&#8217;s app</a> and added a <a title="http://mrdwnotes.wordpress.com/2011/11/28/using-apache-shiro-security-to-allow-login-via-facebook-part-1/" href="http://mrdwnotes.wordpress.com/2011/11/28/using-apache-shiro-security-to-allow-login-via-facebook-part-1/">login via Facebook </a>option I&#8217;m now going to have a bash at implementing a &#8220;log in via twitter&#8221; option, I then will hopefully be able to step back and see what generlisations might be appropriate to make some of the code more generic between Facebook and Twitter logins, and also genererally for OAuth.</p>
<h2>So first Create a Twitter Application</h2>
<p>Do this on dev.twitter.com ,  with an application name, description and website.</p>
<p>There&#8217;s also an optional field for a call back URL, I&#8217;ve filled this in with the URL of the servlet that will be handling twitter login&#8217;s for my application, although twitter does say &#8221; OAuth 1.0a applications should explicitly specify their <tt>oauth_callback</tt> URL on the request token step, regardless of the value given here&#8221;. So I may have to revisit this to determine which URL exactly should be entered.</p>
<p>This gives a consumer key and secret, and 4 URLS (Request token URL, Authorize URL , Access token URL and Callback URL ), so make a note of these, I&#8217;m assuming they may come in useful. Also note twitter&#8217;s &#8220;rules of the road&#8221;, which include things like display of a users twitter avatar if you&#8217;re using the twitter login mechanism, I&#8217;m not sure if Facebook makes the same requirement but if so will have to check.</p>
<h2>Get Twitter4j</h2>
<p>I&#8217;ll be using twitter4j to do a lot of the work, I&#8217;m already using it elsewhere, and been very happy so far with it&#8217;s ease of use.</p>
<p><a title="http://twitter4j.org/en/index.html" href="http://twitter4j.org/en/index.html">http://twitter4j.org/en/index.html</a></p>
<p>I&#8217;ll be using the Sign in Via Twitter example as my guide (EDIT &#8211; I pretty much copy it)</p>
<p><a title="http://twitter4j.org/en/code-examples.html#signinwithtwitter" href="http://twitter4j.org/en/code-examples.html#signinwithtwitter">http://twitter4j.org/en/code-examples.html#signinwithtwitter</a></p>
<h2>Code</h2>
<p>The first thing to do is add a log in via twitter link to our webpage, unlike the facebook one which is a link to facebook, this will be a link to a servlet implemented by our app.</p>
<p>The example above uses the following link.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;a href=&quot;TwitterLogin&quot;&gt;&lt;img src=&quot;./images/Sign-in-with-Twitter-darker.png&quot;/&gt;&lt;/a&gt;
</pre>
<p>Taking the Twitter4j example I then ended up with a TwitterLoginServlet (which maps to &#8220;TwitterLogin&#8221; linked to above) and a TwitterCallbackServlet.<br />
I did find I had to fix the code below to hardcode the URL of the call back servlet when the app was deployed, possibly because I&#8217;m using Nginx as a reverse proxy so it was ending up with 127.0.0.1 instead of the host name, maybe I could fix Nginx configuration to avoid this.<br />
Twitter properties is just a convenience class used in this demo to hold the properties given when the app was created, twitter4J would read in properties from a properties file on the class path by default.</p>
<pre class="brush: plain; title: ; notranslate">
package uk.co.mrdw.shiroexp.servlets;

import java.io.IOException;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.RequestToken;
import twitter4j.conf.ConfigurationBuilder;

public class TwitterLoginServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println( &quot;TwitterLoginServlet:doGet&quot; );
ConfigurationBuilder cb = new ConfigurationBuilder();

Properties props = new TwitterProperties().getProperties();
cb.setDebugEnabled(true)
.setOAuthConsumerKey((String)props.get(&quot;twitterConsumerKey&quot;))
.setOAuthConsumerSecret((String)props.get(&quot;twitterConsumerSecret&quot;))
.setOAuthRequestTokenURL((String)props.get(&quot;twitterRequestTokenURL&quot;))
.setOAuthAuthorizationURL((String)props.get(&quot;twitterAuthorizeURL&quot;))
.setOAuthAccessTokenURL((String)props.get(&quot;twitterAccessTokenURL&quot;));
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();
request.getSession().setAttribute(&quot;twitter&quot;, twitter);
try {
StringBuffer callbackURL = request.getRequestURL();
System.out.println( &quot;TwitterLoginServlet:callbackURL:&quot;+callbackURL );
int index = callbackURL.lastIndexOf(&quot;/&quot;);
callbackURL.replace(index, callbackURL.length(), &quot;&quot;).append(&quot;/TwitterCallback&quot;);

RequestToken requestToken = twitter.getOAuthRequestToken(callbackURL.toString());
request.getSession().setAttribute(&quot;requestToken&quot;, requestToken);
System.out.println( &quot;requestToken.getAuthenticationURL():&quot;+requestToken.getAuthenticationURL() );
response.sendRedirect(requestToken.getAuthenticationURL());

} catch (TwitterException e) {
throw new ServletException(e);
}

}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
*      response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
System.out.println(&quot;Unexpected doPost ...&quot;);
}
}
</pre>
<p>and the callback servlet (URL it&#8217;s mapped to needs to match the callbackURL generated in the login servlet above) &#8230;</p>
<pre class="brush: plain; title: ; notranslate">
package uk.co.mrdw.shiroexp.servlets;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.auth.RequestToken;

public class TwitterCallbackServlet  extends HttpServlet {

private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Twitter twitter = (Twitter) request.getSession().getAttribute(&quot;twitter&quot;);
RequestToken requestToken = (RequestToken) request.getSession().getAttribute(&quot;requestToken&quot;);
System.out.println( &quot;TwitterCallbackServlet:requestToken:&quot;+requestToken);
String verifier = request.getParameter(&quot;oauth_verifier&quot;);
try {
twitter.getOAuthAccessToken(requestToken, verifier);
request.getSession().removeAttribute(&quot;requestToken&quot;);
} catch (TwitterException e) {
throw new ServletException(e);
}
response.sendRedirect(request.getContextPath() + &quot;/&quot;);
}
}
</pre>
<p>This is pretty much a straight copy of the Twitter4J example.</p>
<p>Just to prove it was working I was able to add the following to the index.jsp</p>
<pre class="brush: plain; title: ; notranslate">
&lt;%
&lt;%@ page import=&quot;twitter4j.Twitter&quot;%&gt;
&lt;%@ page import=&quot;twitter4j.ProfileImage&quot;%&gt;

....

Twitter twitter = (Twitter) request.getSession().getAttribute(&quot;twitter&quot;);
if(twitter!=null){
String imageUrl = &quot;&quot;;
try {
imageUrl = twitter.getProfileImage(twitter.getScreenName(), ProfileImage.NORMAL).getURL();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
%&gt;
&lt;p&gt;Twitter ID:&lt;%=twitter.getId()%&gt;&lt;/p&gt;
&lt;p&gt;Twitter Screen Name:&lt;%=twitter.getScreenName()%&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;&lt;%=imageUrl %&gt;&quot;/&gt;
&lt;/p&gt;
&lt;%
}
%&gt;
</pre>
<p>So that&#8217;s the basics of a twitter login to a Java web application working &#8211; I know it&#8217;s not actually logging in via Shiro at them moment, or doing anything useful, that will come ( I&#8217;ll also need to check the Twitter &#8220;Rules of the Road&#8221; before deploying and make sure I&#8217;m complying).</p>
<p>Haven&#8217;t looked at what there is in common with the Facebook login yet from a point of view of making the Shiro implementation more generic,<br />
but I can see differences:<br />
Unlike the Facebook example this works wherever its deployed &#8211; Facebook uses the URL configured for the application to call back to.<br />
The login link on the web page goes to the web app, not to twitter.<br />
Using Twitter4j has hidden a lot of the nuts and bolts, which is good, but may mean less chance of sharing OAuth code between Facebook and Twitter implementations.</p>
<p>Next step login via google I think, then try and put it all together in a Shiro implementation.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mrdwnotes.wordpress.com/170/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mrdwnotes.wordpress.com/170/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mrdwnotes.wordpress.com&#038;blog=29808387&#038;post=170&#038;subd=mrdwnotes&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mrdwnotes.wordpress.com/2011/11/29/twitter-login-to-a-java-web-application/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/fca20f14a7459b3c6df7f1bb2458cfc4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mrmikewarren</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Apache Shiro Security to allow login via Facebook &#8211; part 2</title>
		<link>http://mrdwnotes.wordpress.com/2011/11/28/using-apache-shiro-security-to-allow-login-via-facebook-part-2/</link>
		<comments>http://mrdwnotes.wordpress.com/2011/11/28/using-apache-shiro-security-to-allow-login-via-facebook-part-2/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 12:53:29 +0000</pubDate>
		<dc:creator>mrmikewarren</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://mrdwnotes.wordpress.com/?p=138</guid>
		<description><![CDATA[Using Apache Shiro So in part 1 I got a basic servlet that can be used to determine if a user has logged in via Facebook, and get hold of details like the Facebook users&#8217;s ID and name etc. Now comes configuring and extending Shiro to handle Facebook login. I&#8217;ve taken the approach of creating [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mrdwnotes.wordpress.com&#038;blog=29808387&#038;post=138&#038;subd=mrdwnotes&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h2>Using Apache Shiro</h2>
<p>So in part 1 I got a basic servlet that can be used to determine if a user has logged in via Facebook, and get hold of details like the Facebook users&#8217;s ID and name etc.</p>
<p>Now comes configuring and extending Shiro to handle Facebook login.</p>
<p>I&#8217;ve taken the approach of creating a new realm for Facebook, which will use a custom CredentialsMatcher (which won&#8217;t actually have to do much as it&#8217;s Facebook that handles any credentials matching). So with two new classes to be written uk.co.mrdw.security.facebook.FacebookCredentialsMatcher and uk.co.mrdw.security.facebook.FacebookRealm the config in shiro.ini (or embedded in web.xml in the tutorial) will have the following &#8220;main&#8221; section.</p>
<pre class="brush: plain; title: ; notranslate">
[main]
 realmA = name.brucephillips.somesecurity.dao.RoleSecurityJdbcRealm
 fbCredentialsMatcher = uk.co.mrdw.shiro.facebook.FacebookCredentialsMatcher
 realmB = uk.co.mrdw.security.facebook.FacebookRealm
 realmB.credentialsMatcher = $fbCredentialsMatcher
 securityManager.realms = $realmA, $realmB

</pre>
<p>(Maybe realmA and and realmB could be better named)</p>
<p>So shiro will first try realmA (the jdbc realm, backed by a users table), and if that realm doesn&#8217;t support the token being passed in to the             SecurityUtils.getSubject().login(token) it will try realmB, the Facebook realm. So we&#8217;ll need a new token class for Facebook to identify facebook logins.</p>
<p>The code in the authenticate method in the FacebookLoginServlet will be moved to the FacebookRealm class, and the FacebookLoginServlet will just create a Facebook token and call SecurityUtils.getSubject().login(token).</p>
<p>So we end up with a FacebookRealm class like this</p>
<pre class="brush: java; title: ; notranslate">

package uk.co.mrdw.shiro.facebook;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import uk.co.mrdw.shiroexp.servlets.FacebookProperties;

public class FacebookRealm extends AuthorizingRealm {

private static final Properties props = new FacebookProperties().getProperties();
private static final String APP_SECRET = props.get(&quot;fbAppSecret&quot;).toString();
private static final String APP_ID = props.get(&quot;fbAppId&quot;).toString();
private static final String REDIRECT_URL = props.get(&quot;fbLoginRedirectURL&quot;).toString();

@Override
public boolean supports(AuthenticationToken token) {
if (token instanceof FacebookToken) {
return true;
}
return false;
}

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return new FacebookAuthorizationInfo();
}

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
FacebookToken facebookToken = (FacebookToken) token;

// do all the facebook gubbins
if (facebookToken.getCode() != null &amp;&amp; facebookToken.getCode().trim().length() &gt; 0) {
URL authUrl;
try {
authUrl = new URL(&quot;https://graph.facebook.com/oauth/access_token?&quot; + &quot;client_id=&quot; + APP_ID
+ &quot;&amp;redirect_uri=&quot; + REDIRECT_URL + &quot;&amp;client_secret=&quot; + APP_SECRET + &quot;&amp;code=&quot;
+ facebookToken.getCode());

String authResponse = readURL(authUrl);
System.out.println(authResponse);
String accessToken = getPropsMap(authResponse).get(&quot;access_token&quot;);
URL url = new URL(&quot;https://graph.facebook.com/me?access_token=&quot; + accessToken);
String fbResponse = readURL(url);
FacebookUserDetails fud = new FacebookUserDetails(fbResponse);
return new FacebookAuthenticationInfo(fud, this.getName());
} catch (MalformedURLException e1) {
e1.printStackTrace();
throw new AuthenticationException(e1);
} catch (IOException ioe) {
ioe.printStackTrace();
throw new AuthenticationException(ioe);
} catch (Throwable e) {
e.printStackTrace();
}
}
return null;
}

// ------------------------------------------------------------
// STUFF here should be in a more generic place TODO
// ------------------------------------------------------------

private String readURL(URL url) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = url.openStream();
int r;
while ((r = is.read()) != -1) {
baos.write(r);
}
return new String(baos.toByteArray());
}

private Map&lt;String, String&gt; getPropsMap(String someString) {
String[] pairs = someString.split(&quot;&amp;&quot;);
Map&lt;String, String&gt; props = new HashMap&lt;String, String&gt;();
for (String propPair : pairs) {
String[] pair = propPair.split(&quot;=&quot;);
props.put(pair[0], pair[1]);
}
return props;
}
}

</pre>
<p>I have also added some getters to the FacebookUserDetails class &#8211; just extracting data from the json String it&#8217;s created with, will be refined as required in the future.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;pre&gt;
package uk.co.mrdw.shiro.facebook;

import org.json.JSONException;
import org.json.JSONObject;

/**
* Simple class for holding data relating to a facebook user
*
* @author Mike
*
*/
public class FacebookUserDetails {
private String id;
private String firstName;
private String lastName;
private String email;
// jsonString Expected to be something like this
// {
// &quot;education&quot;: [{
// &quot;school&quot;: {
// &quot;id&quot;: &quot;123456789012345&quot;,
// &quot;name&quot;: &quot;University of Sheffield&quot;
// },
// &quot;type&quot;: &quot;Graduate School&quot;,
// &quot;with&quot;: [{
// &quot;id&quot;: &quot;123456789&quot;,
// &quot;name&quot;: &quot;Daffy Duck&quot;
// }]
// }],
// &quot;first_name&quot;: &quot;Mike&quot;,
// &quot;id&quot;: &quot;121212121&quot;,
// &quot;last_name&quot;: &quot;Warren&quot;,
// &quot;link&quot;:
// &quot;http://www.facebook.com/profile.php?id=121212121&quot;,
// &quot;locale&quot;: &quot;en_US&quot;,
// &quot;name&quot;: &quot;Mike Warren&quot;,
// &quot;updated_time&quot;: &quot;2011-08-15T14:51:05+0000&quot;,
// &quot;verified&quot;: true
// }
private String jsonString;

public FacebookUserDetails(String fbResponse){
jsonString = fbResponse;
JSONObject respjson;
try {
respjson = new JSONObject(fbResponse);
this.id = respjson.getString(&quot;id&quot;);
this.firstName = respjson.has(&quot;first_name&quot;) ? respjson.getString(&quot;first_name&quot;) : &quot; no name&quot; + id;
this.lastName = respjson.has(&quot;last_name&quot;) ? respjson.getString(&quot;last_name&quot;) : &quot;&quot;;
this.email = respjson.has(&quot;email&quot;) ? respjson.getString(&quot;email&quot;) : &quot;-no email-&quot;;
} catch (JSONException e) {
System.out.println( &quot;fbResponse:&quot;+fbResponse );
e.printStackTrace();
throw new RuntimeException(e);
}

}

public String toString(){
return jsonString;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}
}

</pre>
<p>The CredentialsMatcher class shouldn&#8217;t need to do anything, as Facebook is doing the credentials matching for us.</p>
<pre class="brush: plain; title: ; notranslate">
package uk.co.mrdw.shiro.facebook;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;

public class FacebookCredentialsMatcher implements CredentialsMatcher {

/**
* Just confirms that token is the right type - credentials checking is done by facebook OAuth
*/
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
if(info instanceof FacebookAuthenticationInfo){
return true;
}
return false;
}

}

</pre>
<p>create a facebook token class, will just be used to hold the &#8220;code&#8221; provided by Facebook</p>
<pre class="brush: plain; title: ; notranslate">
package uk.co.mrdw.shiro.facebook;

import org.apache.shiro.authc.AuthenticationToken;

public class FacebookToken implements AuthenticationToken {

private static final long serialVersionUID = 1L;
private String code;

public FacebookToken(String code){
this.code = code;
}

@Override
public Object getPrincipal() {
return null;// not known - facebook does the login
}

@Override
public Object getCredentials() {
return null;// credentials handled by facebook - we don't need them
}

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}
}
</pre>
<p>And a FacebookAuthenticationInfo class</p>
<pre class="brush: plain; title: ; notranslate">
package uk.co.mrdw.shiro.facebook;

import java.util.ArrayList;
import java.util.Collection;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;

public class FacebookAuthenticationInfo implements AuthenticationInfo {

private static final long serialVersionUID = 1L;

private PrincipalCollection principalCollection;

public FacebookAuthenticationInfo(FacebookUserDetails facebookUserDetails, String realmName){
Collection&lt;String&gt; principals = new ArrayList&lt;String&gt;();
principals.add(facebookUserDetails.getId());
principals.add(facebookUserDetails.getFirstName()+&quot; &quot;+facebookUserDetails.getLastName()); // Is this appropriate is the name not really a Principal ?
this.principalCollection = new SimplePrincipalCollection(principals, realmName);
}

@Override
public PrincipalCollection getPrincipals() {
return principalCollection;
}

@Override
public Object getCredentials() {
return null;// no credentials required
}
}

</pre>
<p>The FacebookLoginServlet then becomes much simpler &#8211; basically just use&#8217;s Shiro&#8217;s login mechanism.</p>
<pre class="brush: plain; title: ; notranslate">
package uk.co.mrdw.shiroexp.servlets;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;

import uk.co.mrdw.shiro.facebook.FacebookToken;

/**
* Simple Facebook Login Handling, doesn't actually do anything except display page confirming login
* successfull.
*
*
* @author Mike
*
*/
public class FacebookLoginServlet  extends HttpServlet {

private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(&quot;FacebookLoginServlet getting..&quot;);

String code = request.getParameter(&quot;code&quot;);
FacebookToken facebookToken = new FacebookToken(code);
try{
SecurityUtils.getSubject().login(facebookToken);
response.sendRedirect(response.encodeRedirectURL(&quot;index.jsp&quot;));
}
catch(AuthenticationException ae){
throw new ServletException(ae);
}
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
*      response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
System.out.println(&quot;Unexpected doPost ...&quot;);
}
}

</pre>
<p>I&#8217;ve added a few lines to index.jsp, just to give some feedback on the result of the login via facebook</p>
<pre class="brush: plain; title: ; notranslate">
&lt;%@ page import=&quot;org.apache.shiro.SecurityUtils&quot;%&gt;
&lt;%@ page import=&quot;org.apache.shiro.subject.PrincipalCollection&quot;%&gt;

...

&lt;p&gt;Is authenticated? &lt;%= SecurityUtils.getSubject().isAuthenticated() %&gt;&lt;/p&gt;
&lt;p&gt;Principal:&lt;%= SecurityUtils.getSubject().getPrincipal() %&gt;&lt;/p&gt;
&lt;p&gt;Principals:&lt;/p&gt;
&lt;% PrincipalCollection principalCollection = SecurityUtils.getSubject().getPrincipals();
if(principalCollection!=null){
for(Object principal : principalCollection.asList()){
//request.out.println(&quot;&lt;p&gt;&quot;+principal +&quot;&lt;/p&gt;&quot;);
%&gt;&lt;p&gt;&lt;%=principal %&gt;&lt;/p&gt;&lt;%
}
}
%&gt;
</pre>
<p>which ends up with output like this</p>
<pre class="brush: plain; title: ; notranslate">&lt;/pre&gt;
Is authenticated? true

Principal:121212121

Principals:

121212121

Mike Warren
&lt;pre&gt;
</pre>
<p>And that&#8217;s it &#8211; have just tested it and it works, I can login via facebook and get access to the &#8220;secure&#8221; page, get a display of the facebook ID as the principal, and can logout via the standard logout link.<br />
Think I may need to read up on Principals and Roles a bit to see how to integrate shiro authorization capabilities with what I&#8217;ve got, but it may be that this is enough for my currrent needs.</p>
<p>I have a few doubts about whether this is the right way to use Shiro, so may well post a follow up post &#8211; &#8220;Using Shiro properly&#8221; to correct mistakes here.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mrdwnotes.wordpress.com/138/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mrdwnotes.wordpress.com/138/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mrdwnotes.wordpress.com&#038;blog=29808387&#038;post=138&#038;subd=mrdwnotes&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mrdwnotes.wordpress.com/2011/11/28/using-apache-shiro-security-to-allow-login-via-facebook-part-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/fca20f14a7459b3c6df7f1bb2458cfc4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mrmikewarren</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Apache Shiro Security to allow login via Facebook &#8211; part 1</title>
		<link>http://mrdwnotes.wordpress.com/2011/11/28/using-apache-shiro-security-to-allow-login-via-facebook-part-1/</link>
		<comments>http://mrdwnotes.wordpress.com/2011/11/28/using-apache-shiro-security-to-allow-login-via-facebook-part-1/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 12:53:01 +0000</pubDate>
		<dc:creator>mrmikewarren</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://mrdwnotes.wordpress.com/?p=117</guid>
		<description><![CDATA[Background Having got Facebook login working for my message board project in a quick and dirty way I decided to try and switch to using Apache Shiro for my security needs. This should hopefully mean I end up with something a bit more maintainable that could be extended without ending up with a custom made [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mrdwnotes.wordpress.com&#038;blog=29808387&#038;post=117&#038;subd=mrdwnotes&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h2>Background</h2>
<p>Having got Facebook login working for my message board project in a quick and dirty way I decided to try and switch to using Apache Shiro for my security needs. This should hopefully mean I end up with something a bit more maintainable that could be extended without ending up with a custom made mess.</p>
<p>I&#8217;ve now got Shiro working in the message board project, and it has been pretty straighforward to get it running wityh a database tables of users,roles and passwords (encyrpted of course). After looking at the documentation on the Apache Shiro site I&#8217;d recommend the tutorial by Bruce Phillips <a href="http://www.brucephillips.name/blog/index.cfm/2009/4/5/An-Introduction-to-Ki-formerly-JSecurity&#8211;A-Beginners&#8211;Tutorial-Part-1" rel="nofollow">http://www.brucephillips.name/blog/index.cfm/2009/4/5/An-Introduction-to-Ki-formerly-JSecurity&#8211;A-Beginners&#8211;Tutorial-Part-1</a></p>
<p>Next step was to allow login via facebook (hoping to add other logins for twitter, google etc. soon) . I have a rough version of facebook login using Shiro working on my message board, but I&#8217;m not 100% sure about my approach, so rather than steam ahead with what I&#8217;ve done I&#8217;m going to try taking a step back and add facebook login to the tutorial project Bruce Phillips has created. At least then I can use this for demonstrating to others what I&#8217;ve done, which may be useful for anyone else trying something similar, and also have a simple project that I can experiment with without worrying about other distractions.</p>
<p>So bear in mind that this is my first rough stab at Facebook login with Shiro, I&#8217;m new to Shiro and to OAuth/Facebook login, so may well be setting a bad example, if so hopefully I&#8217;ll learn and be able to post a follow up with a better way of doing it. Basically feel free to copy stuff hear, but don&#8217;t blame me if it&#8217;s wrong.</p>
<p>I got some inspiration from Tynamo , which is a Tapestry module for doing exactly this</p>
<p><a title="http://tynamo.org/tynamo-federatedaccounts+guide" href="http://tynamo.org/tynamo-federatedaccounts+guide" target="_blank">http://tynamo.org/tynamo-federatedaccounts+guide</a></p>
<p>which I came accross in the Shiro user forum here</p>
<p><a title="http://shiro-user.582556.n2.nabble.com/Advice-on-Shira-with-FB-Connect-Session-Clustering-Efficiency-td6832777.html" href="http://shiro-user.582556.n2.nabble.com/Advice-on-Shira-with-FB-Connect-Session-Clustering-Efficiency-td6832777.html" target="_blank">http://shiro-user.582556.n2.nabble.com/Advice-on-Shira-with-FB-Connect-Session-Clustering-Efficiency-td6832777.html</a></p>
<h2>Adding Facebook Login to &#8220;Somesecurity&#8221; Tutorial App</h2>
<p>So copied the &#8220;somescurity&#8221; project in Eclipse to a new ShiroFacebook project ( found I had to go to &#8220;project-&gt;properties-&gt;Web Project Settings&#8221; and change the context root).</p>
<h3>Create a Facebook App</h3>
<p>This requires you to have URL where the app will be deployed.</p>
<p>In Facebook  <a title="https://developers.facebook.com/apps" href="https://developers.facebook.com/apps" target="_blank">https://developers.facebook.com/apps</a> select development, and create an App.</p>
<p>First you need to come up with a display name and a namespace for the app.</p>
<p>Then in the Website &#8220;I want to allow people to log into my website using Facebook&#8221; section you need to provide the URL for your app.</p>
<p>You should then have an App ID, and an App Secret for your application &#8211; make a note of these.</p>
<h3>Add Login Via Facebook Link</h3>
<p>Next add a login via facebook link on index.jsp , which will be like this.</p>
<p><a href="https://www.facebook.com/dialog/oauth?client_id=123456789012345&#038;redirect_uri=http://www.somesite.co.uk/shirofb/FacebookLogin" rel="nofollow">https://www.facebook.com/dialog/oauth?client_id=123456789012345&#038;redirect_uri=http://www.somesite.co.uk/shirofb/FacebookLogin</a></p>
<p>Where an &#8220;App ID&#8221; of 123456789012345 and the application will be running at <a href="http://www.somesite.co.uk/shirofb" rel="nofollow">http://www.somesite.co.uk/shirofb</a> .</p>
<h3>Create FacebookLogin Servlet</h3>
<p>Now we need to create a FacebookLogin servlet to handle the redirection from Facebook.</p>
<p>I found this blog post very helpful:</p>
<p><a title="http://www.richardnichols.net/2010/06/implementing-facebook-oauth-2-0-authentication-in-java/" href="http://www.richardnichols.net/2010/06/implementing-facebook-oauth-2-0-authentication-in-java/" target="_blank">http://www.richardnichols.net/2010/06/implementing-facebook-oauth-2-0-authentication-in-java/</a></p>
<p>So from Richard Nichol&#8217;s blog above and reading Facebook documentation I&#8217;ve ended with the follow servlet .</p>
<p>Facebook sends a request to this servlet after a user has clicked on the facebook login link on our index.jsp, this request contains a code which is used in the authenticate method to request an access token from facebook, which can be used to get details (id, name etc. ) of the user who has logged in. The Servlet then just prints out a simple piece of html to display the users details, or an error message.</p>
<pre class="brush: java; title: ; notranslate">
&lt;pre&gt;package uk.co.mrdw.shiroexp.servlets;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Simple Facebook Login Handling, doesn't actually do anything except display page confirming login
* successfull.
*
*
* @author Mike
*
*/
public class FacebookLoginServlet  extends HttpServlet {

private static final long serialVersionUID = 1L;

/**
* Properties will be as follows, but with values for this app.
* fbAppSecret=1a234bc1234d1234e1f123g1234567g1
* fbAppId=123456789012345
* fbLoginRedirectURL=http://www.yoursite.co.uk/shirofb/FacebookLogin
*/
private static final Properties props = new FacebookProperties().getProperties();

private static final String APP_SECRET = props.get(&quot;fbAppSecret&quot;).toString();
private static final String APP_ID = props.get(&quot;fbAppId&quot;).toString();
private static final String REDIRECT_URL = props.get(&quot;fbLoginRedirectURL&quot;).toString();

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(&quot;FacebookLoginServlet getting..&quot;);

FacebookUserDetails fud = authenticate(request, response);

if (fud != null) {
response.getWriter().write(&quot;&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;h1&gt;Facebook Logged In&lt;/h1&gt;&lt;p&gt;&quot;+fud.toString()+&quot;&lt;/p&gt;&lt;/body&gt;&quot;);
response.getWriter().flush();

} else {
try {
System.out.println(&quot;fb log in failed&quot;);
String errorReason = request.getParameter(&quot;error_reason&quot;);
String error = request.getParameter(&quot;error&quot;);
response.getWriter().write(&quot;&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;h1&gt;fb login failed&lt;/h1&gt;&quot; +
&quot; reason:&quot;+errorReason+&quot; error:&quot;+error+&quot;&lt;/body&gt;&quot;);
response.getWriter().flush();

return;
} catch (Exception e) {
e.printStackTrace();
}
}
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
*      response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
System.out.println(&quot;Unexpected doPost ...&quot;);
}

/**
* Makes call to Facebook to get access_token, and then to get id, name etc.
* for the facebook user relating to that token. Returns FacebookUserDetails
* object for that user, or null if unable to complete authentication.
*
* @param request
* @param response
* @param code
* @return FacebookUserDetails
* @throws MalformedURLException
* @throws IOException
*/
private FacebookUserDetails authenticate(HttpServletRequest request, HttpServletResponse response)
throws MalformedURLException, IOException {
FacebookUserDetails fud = null;
String code = request.getParameter(&quot;code&quot;);
if (code != null &amp;&amp; code.trim().length() &gt; 0) {
URL authUrl = new URL(&quot;https://graph.facebook.com/oauth/access_token?&quot; + &quot;client_id=&quot;
+ APP_ID + &quot;&amp;redirect_uri=&quot; + REDIRECT_URL + &quot;&amp;client_secret=&quot;
+ APP_SECRET + &quot;&amp;code=&quot; + code);

String authResponse = readURL(authUrl);
System.out.println(authResponse);

try {
String accessToken = getPropsMap(authResponse).get(&quot;access_token&quot;);
URL url = new URL(&quot;https://graph.facebook.com/me?access_token=&quot; + accessToken);
String fbResponse = readURL(url);

System.out.println(fbResponse);

fud = new FacebookUserDetails(fbResponse);

} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
return fud;
}

private String readURL(URL url) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = url.openStream();
int r;
while ((r = is.read()) != -1) {
baos.write(r);
}
return new String(baos.toByteArray());
}

private Map&lt;String, String&gt; getPropsMap(String someString) {
String[] pairs = someString.split(&quot;&amp;&quot;);
Map&lt;String, String&gt; props = new HashMap&lt;String, String&gt;();
for (String propPair : pairs) {
String[] pair = propPair.split(&quot;=&quot;);
props.put(pair[0], pair[1]);
}
return props;

}

/**
* Simple class for holding data relating to a facebook user
* currentyl just holds jsonString, but could have extra properties added backed by the json
* e.g. id, firstName, lastName, link ,education[], etc.
*
* @author Mike
*
*/
class FacebookUserDetails {

// jsonString Expected to be something like this, although I'm sure it used to include
// email
// {
// &quot;education&quot;: [{
// &quot;school&quot;: {
// &quot;id&quot;: &quot;123456789012345&quot;,
// &quot;name&quot;: &quot;University of Sheffield&quot;
// },
// &quot;type&quot;: &quot;Graduate School&quot;,
// &quot;with&quot;: [{
// &quot;id&quot;: &quot;123456789&quot;,
// &quot;name&quot;: &quot;Daffy Duck&quot;
// }]
// }],
// &quot;first_name&quot;: &quot;Mike&quot;,
// &quot;id&quot;: &quot;121212121&quot;,
// &quot;last_name&quot;: &quot;Warren&quot;,
// &quot;link&quot;:
// &quot;http://www.facebook.com/profile.php?id=121212121&quot;,
// &quot;locale&quot;: &quot;en_US&quot;,
// &quot;name&quot;: &quot;Mike Warren&quot;,
// &quot;updated_time&quot;: &quot;2011-08-15T14:51:05+0000&quot;,
// &quot;verified&quot;: true
// }
private String jsonString;

FacebookUserDetails(String fbResponse){
jsonString = fbResponse;
}

public String toString(){
return jsonString;
}
}

}
</pre>
<p>&#8230; Next Part 2 Making use of Shiro</p>
<p><span id="more-117"></span><!--more--></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mrdwnotes.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mrdwnotes.wordpress.com/117/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mrdwnotes.wordpress.com&#038;blog=29808387&#038;post=117&#038;subd=mrdwnotes&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mrdwnotes.wordpress.com/2011/11/28/using-apache-shiro-security-to-allow-login-via-facebook-part-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/fca20f14a7459b3c6df7f1bb2458cfc4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mrmikewarren</media:title>
		</media:content>
	</item>
	</channel>
</rss>
