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.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
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.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.plugins.oauth.scribe.GoogleApi20;
import fi.otavanopisto.muikku.session.SessionController;
public class GoogleAuthenticationStrategy extends OAuthAuthenticationStrategy implements AuthenticationProvider {
@Inject
private Logger logger;
@Inject
private SessionController sessionController;
public GoogleAuthenticationStrategy() {
super("https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile");
}
@Override
protected String getApiKey(AuthSource authSource) {
return getAuthSourceSetting(authSource, "oauth.google.apiKey");
}
@Override
protected String getApiSecret(AuthSource authSource) {
return getAuthSourceSetting(authSource, "oauth.google.apiSecret");
}
@Override
protected String getOAuthCallbackURL(AuthSource authSource) {
return getAuthSourceSetting(authSource, "oauth.google.callbackUrl");
}
@Override
public String getName() {
return "googleoauth";
}
@Override
public String getDescription() {
return "Google";
}
@Override
protected Api getApi() {
return new GoogleApi20();
}
@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);
GoogleAccessToken googleAccessToken;
try {
googleAccessToken = objectMapper.readValue(accessToken.getRawResponse(), GoogleAccessToken.class);
Calendar calendar = new GregorianCalendar();
calendar.setTime(new Date());
calendar.add(Calendar.SECOND, googleAccessToken.getExpiresIn());
Date expires = calendar.getTime();
sessionController.addOAuthAccessToken("google", expires, accessToken.getToken(), null);
} catch (IOException e) {
logger.log(Level.SEVERE, "Token extraction failed a JSON parsing error", e);
return new AuthenticationResult(AuthenticationResult.Status.ERROR);
}
List<String> scopesList = Arrays.asList(requestedScopes);
boolean hasProfileScope = scopesList.contains("https://www.googleapis.com/auth/userinfo.profile");
GoogleUserInfo userInfo = null;
if (hasProfileScope) {
OAuthRequest request = new OAuthRequest(Verb.GET, "https://www.googleapis.com/oauth2/v1/userinfo?alt=json");
service.signRequest(accessToken, request);
Response response = request.send();
try {
userInfo = objectMapper.readValue(response.getBody(), GoogleUserInfo.class);
} catch (IOException e) {
logger.log(Level.SEVERE, "Logging in failed because of a JSON parsing exception", e);
return new AuthenticationResult(AuthenticationResult.Status.ERROR);
}
}
if (userInfo != null)
return processLogin(authSource, requestParameters, userInfo.getId(), Arrays.asList(userInfo.getEmail()), userInfo.getGivenName(), userInfo.getFamilyName());
else {
return new AuthenticationResult(AuthenticationResult.Status.GRANT);
}
}
@SuppressWarnings ("unused")
@JsonIgnoreProperties (ignoreUnknown = true)
private static class GoogleAccessToken {
public Integer getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(Integer expiresIn) {
this.expiresIn = expiresIn;
}
@JsonProperty ("expires_in")
private Integer expiresIn;
}
@SuppressWarnings ("unused")
@JsonIgnoreProperties (ignoreUnknown = true)
private static class GoogleUserInfo {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGivenName() {
return givenName;
}
public void setGivenName(String givenName) {
this.givenName = givenName;
}
public String getFamilyName() {
return familyName;
}
public void setFamilyName(String familyName) {
this.familyName = familyName;
}
public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
private String id;
private String email;
@JsonProperty ("given_name")
private String givenName;
@JsonProperty ("family_name")
private String familyName;
private Locale locale;
}
}