/**************************************************************************************************
* Copyright (c) 2014 Dennis Fischer. *
* All rights reserved. This program and the accompanying materials *
* are made available under the terms of the GNU Public License v3.0+ *
* which accompanies this distribution, and is available at *
* http://www.gnu.org/licenses/gpl.html *
* *
* Contributors: Dennis Fischer *
**************************************************************************************************/
package de.chaosfisch.google.account;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import de.chaosfisch.google.GDATAConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
public abstract class AbstractAccountService implements IAccountService {
private static final int SC_OK = 200;
private final HashMap<Account, Token> authtokens = new HashMap<>(3);
private static final String REFRESH_TOKEN_URL = "https://accounts.google.com/o/oauth2/token";
private static final String TOKEN_TEST_URL = "https://www.googleapis.com/youtube/v3/activities?part=id&mine=true&maxResults=0";
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAccountService.class);
private Token getAuthToken(final Account account) throws AuthenticationException {
return getAuthToken(account, false);
}
private Token getAuthToken(final Account account, final boolean uncached) throws AuthenticationException {
if (uncached || !authtokens.containsKey(account) || !authtokens.get(account).isValid()) {
authtokens.put(account, _receiveToken(account));
}
return authtokens.get(account);
}
private Token _receiveToken(final Account account) throws AuthenticationException {
try {
final HttpResponse<JsonNode> response = Unirest.post(REFRESH_TOKEN_URL)
.header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8;")
.field("grant_type", "refresh_token")
.field("client_id", GDATAConfig.CLIENT_ID)
.field("client_secret", GDATAConfig.CLIENT_SECRET)
.field("refresh_token", account.getRefreshToken())
.asJson();
if (SC_OK != response.getCode()) {
throw new AuthenticationInvalidException(response.getCode());
}
return new Token(response.getBody().getObject().getString("access_token"), response.getBody().getObject().getInt("expires_in"));
} catch (final Exception e) {
throw new AuthenticationException(e);
}
}
@Override
public Authentication getAuthentication(final Account account) {
try {
return new Authentication(getAuthToken(account).getToken());
} catch (final Exception e) {
LOGGER.error("Auth invalid", e);
return new Authentication();
}
}
@Override
public String getRefreshToken(final String code) throws AuthenticationException {
try {
final HttpResponse<JsonNode> response = Unirest.post(REFRESH_TOKEN_URL)
.header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8;")
.field("grant_type", "authorization_code")
.field("client_id", GDATAConfig.CLIENT_ID)
.field("client_secret", GDATAConfig.CLIENT_SECRET)
.field("redirect_uri", GDATAConfig.REDIRECT_URI)
.field("code", code)
.asJson();
if (SC_OK != response.getCode()) {
throw new AuthenticationInvalidException(response.getCode());
}
return response.getBody().getObject().getString("refresh_token");
} catch (final Exception e) {
throw new AuthenticationException(e);
}
}
@Override
public boolean verifyAccount(final Account account) {
try {
getAuthToken(account, true);
_testExtended(account);
return true;
} catch (AuthenticationException | UnirestException e) {
return false;
}
}
private void _testExtended(final Account account) throws AuthenticationException, UnirestException {
final HttpResponse<String> response = Unirest.get(TOKEN_TEST_URL)
.header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8;")
.header("Authorization", getAuthentication(account).getHeader())
.asString();
if (SC_OK != response.getCode()) {
throw new AuthenticationException(String.format("Code %d during token test;\n%s", response.getCode(), response.getBody()));
}
}
}