package fi.otavanopisto.muikku.plugins.oauth; import java.io.IOException; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; import org.apache.commons.lang3.math.NumberUtils; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.map.ObjectMapper; import org.scribe.builder.api.Api; import org.scribe.builder.api.FacebookApi; import org.scribe.model.OAuthRequest; import org.scribe.model.Response; import org.scribe.model.Token; import org.scribe.model.Verb; import org.scribe.model.Verifier; import org.scribe.oauth.OAuthService; import fi.otavanopisto.muikku.auth.AuthenticationProvider; import fi.otavanopisto.muikku.auth.AuthenticationResult; import fi.otavanopisto.muikku.auth.OAuthAuthenticationStrategy; import fi.otavanopisto.muikku.model.security.AuthSource; import fi.otavanopisto.muikku.session.SessionController; public class FacebookAuthenticationStrategy extends OAuthAuthenticationStrategy implements AuthenticationProvider { @Inject private Logger logger; @Inject private SessionController sessionController; public FacebookAuthenticationStrategy() { super("email"); } @Override protected String getApiKey(AuthSource authSource) { return getAuthSourceSetting(authSource, "oauth.facebook.apiKey"); } @Override protected String getApiSecret(AuthSource authSource) { return getAuthSourceSetting(authSource, "oauth.facebook.apiSecret"); } @Override protected String getOAuthCallbackURL(AuthSource authSource) { return getAuthSourceSetting(authSource, "oauth.facebook.callbackUrl"); } @Override public String getName() { return "facebookoauth"; } @Override public String getDescription() { return "Facebook"; } @Override protected Api getApi() { return new FacebookApi(); } @Override protected AuthenticationResult processResponse(AuthSource authSource, Map<String, String[]> requestParameters, OAuthService service, String[] requestedScopes) { ObjectMapper objectMapper = new ObjectMapper(); String verifier = getFirstRequestParameter(requestParameters, "code"); Verifier v = new Verifier(verifier); Token accessToken = service.getAccessToken(null, v); FacebookUser meObject = null; OAuthRequest request = new OAuthRequest(Verb.GET, "https://graph.facebook.com/me"); service.signRequest(accessToken, request); Response response = request.send(); try { meObject = objectMapper.readValue(response.getBody(), FacebookUser.class); } catch (IOException e) { logger.log(Level.SEVERE, "Logging in failed because of a JSON parsing exception", e); return new AuthenticationResult(AuthenticationResult.Status.ERROR); } Integer expiresIn = extractExpires(accessToken); Date expires = null; if (expiresIn != null) { Calendar calendar = new GregorianCalendar(); calendar.setTime(new Date()); calendar.add(Calendar.SECOND, expiresIn); expires = calendar.getTime(); sessionController.addOAuthAccessToken("facebook", expires, accessToken.getToken(), null); } if (meObject != null) return processLogin(authSource, requestParameters, meObject.getId(), Arrays.asList(meObject.getEmail()), meObject.getFirstName(), meObject.getLastName()); else { return new AuthenticationResult(AuthenticationResult.Status.GRANT); } } private Integer extractExpires(Token accessToken) { try { Pattern pattern = Pattern.compile("expires=[0-9]*"); Matcher matcher = pattern.matcher(accessToken.getRawResponse()); if (matcher.find()) { String[] split = matcher.group().split("="); if (split.length == 2) return NumberUtils.createInteger(split[1]); } return null; } catch (Exception e) { return null; } } @JsonIgnoreProperties(ignoreUnknown = true) @SuppressWarnings ("unused") private static class FacebookUser { public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } 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 getLink() { return link; } public void setLink(String link) { this.link = link; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Locale getLocale() { return locale; } public void setLocale(Locale locale) { this.locale = locale; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } private String id; private String name; @JsonProperty ("first_name") private String firstName; @JsonProperty ("last_name") private String lastName; private String link; private String username; private String gender; private Locale locale; private String email; } }