Skip to content

Instantly share code, notes, and snippets.

@shin1ogawa
Last active December 16, 2015 20:49
Show Gist options
  • Save shin1ogawa/5494912 to your computer and use it in GitHub Desktop.
Save shin1ogawa/5494912 to your computer and use it in GitHub Desktop.
package com.shin1ogawa.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.codehaus.jackson.map.ObjectMapper;
import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.util.StringUtil;
import com.google.common.io.ByteStreams;
public class IndexController extends Controller {
static final String CLIENT_ID = ""; // FIXME
static final String CLIENT_SECRET = ""; // FIXME
static final String PROJECT_ID = ""; // FIXME
static final String PATH = "/";
static final String CHARCTER_ENCODING = "utf-8";
static final String SCOPES = "https://www.googleapis.com/auth/glass.timeline"
+ " https://www.googleapis.com/auth/glass.location"
+ " https://www.googleapis.com/auth/userinfo.profile";
@Override
protected Navigation run() throws Exception {
String refreshToken = loadRefreshTokenFromCookie();
if (StringUtil.isEmpty(refreshToken) == false) {
return doSomething(refreshToken);
} else {
String authorizationCode = request.getParameter("code");
if (StringUtil.isEmpty(authorizationCode)) {
return redirectToRetrieveAuthorizationCode();
} else {
return retrieveToken(authorizationCode);
}
}
}
Navigation doSomething(String refreshToken) throws IOException {
String accessToken = Util.refreshAccessToken(CLIENT_ID, CLIENT_SECRET,
refreshToken);
// mirror API list timeline を実行する
// https://developers.google.com/glass/v1/reference/timeline/list
URL url = new URL("https://www.googleapis.com/mirror/v1/timeline");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", "Bearer " + accessToken);
byte[] bytes = ByteStreams.toByteArray(connection.getInputStream());
String responseAsString = new String(bytes, CHARCTER_ENCODING);
saveRefreshTokenAsCookie(refreshToken);
response.setContentType("text/plain");
response.setCharacterEncoding(CHARCTER_ENCODING);
PrintWriter writer = response.getWriter();
writer.println("refreshToken=" + refreshToken);
writer.println("refreshed accessToken=" + accessToken);
writer.println();
writer.print(responseAsString);
writer.println();
response.flushBuffer();
return null;
}
Navigation retrieveToken(String authorizationCode) throws IOException {
Map<String, String> tokens = Util.getTokensWithAuthorizationCode(
request, authorizationCode);
String refreshToken = tokens.get("refresh_token");
saveRefreshTokenAsCookie(refreshToken);
return new Navigation(PATH, true);
}
Navigation redirectToRetrieveAuthorizationCode()
throws UnsupportedEncodingException {
String redirectURI = Util.buildRedirectURIForOAuth2(request,
IndexController.PATH);
String redirectTo = new StringBuilder(
"https://accounts.google.com/o/oauth2/auth?")
.append("response_type=code").append("&client_id=")
.append(URLEncoder.encode(CLIENT_ID, CHARCTER_ENCODING))
.append("&redirect_uri=").append(redirectURI).append("&scope=")
.append(URLEncoder.encode(SCOPES, CHARCTER_ENCODING))
.append("&access_type=offline&approval_prompt=force")
.toString();
return redirect(redirectTo);
}
String loadRefreshTokenFromCookie() {
String refreshToken = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("refresh_token".equals(cookie.getName()) == false) {
continue;
}
refreshToken = cookie.getValue();
}
}
return refreshToken;
}
void saveRefreshTokenAsCookie(String refreshToken) {
Cookie cookie = new Cookie("refresh_token", refreshToken);
response.addCookie(cookie);
}
static class Util {
static String refreshAccessToken(String clientId, String clientSecret,
String refreshToken) throws IOException {
// パラメータを組み立てる
StringBuilder b = new StringBuilder();
b.append("&client_id=")
.append(URLEncoder.encode(clientId, "utf-8"));
b.append("&client_secret=").append(
URLEncoder.encode(clientSecret, "utf-8"));
b.append("&refresh_token=").append(
URLEncoder.encode(refreshToken, "utf-8"));
b.append("&grant_type=refresh_token");
byte[] payload = b.toString().getBytes();
// POST メソッドでリクエストする
HttpURLConnection c = (HttpURLConnection) new URL(
"https://accounts.google.com/o/oauth2/token")
.openConnection();
c.setRequestMethod("POST");
c.setDoOutput(true);
c.setRequestProperty("Content-Length",
String.valueOf(payload.length));
c.getOutputStream().write(payload);
c.getOutputStream().flush();
@SuppressWarnings("unchecked")
Map<String, Object> map = new ObjectMapper().readValue(
c.getInputStream(), Map.class);
return (String) map.get("access_token");
}
static Map<String, String> getTokensWithAuthorizationCode(
HttpServletRequest request, String authorizationCode)
throws IOException {
String redirectURI = buildRedirectURIForOAuth2(request,
IndexController.PATH);
String queryString = new StringBuilder().append("&code=")
.append(URLEncoder.encode(authorizationCode, "utf-8"))
.append("&client_id=")
.append(URLEncoder.encode(CLIENT_ID, "utf-8"))
.append("&client_secret=")
.append(URLEncoder.encode(CLIENT_SECRET, "utf-8"))
.append("&redirect_uri=").append(redirectURI)
.append("&grant_type=authorization_code").toString();
byte[] payload = queryString.getBytes("utf-8");
URL url = new URL("https://accounts.google.com/o/oauth2/token");
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length",
String.valueOf(payload.length));
connection.setDoOutput(true);
connection.getOutputStream().write(payload);
connection.getOutputStream().flush();
@SuppressWarnings("unchecked")
Map<String, String> responseAsMap = new ObjectMapper().readValue(
connection.getInputStream(), Map.class);
return responseAsMap;
}
static String buildRedirectURIForOAuth2(HttpServletRequest request,
String path) throws UnsupportedEncodingException {
StringBuilder b = new StringBuilder();
b.append(request.getScheme()).append("://")
.append(request.getServerName());
if (request.getServerPort() != 443 && request.getServerPort() != 80) {
b.append(":").append(request.getServerPort());
}
b.append(path);
String redirectURI = URLEncoder.encode(b.toString(),
CHARCTER_ENCODING);
return redirectURI;
}
}
}
@shin1ogawa
Copy link
Author

Slim3用。Jacksonに依存。
API ConsoleのClientIDのRedirectURIの設定に http://{YOUR-APP-ID}.appspot.com/ を追加する。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment