package org.jboss.resteasy.skeleton.key.servlet; import org.jboss.resteasy.plugins.server.servlet.ServletUtil; import org.jboss.resteasy.skeleton.key.AbstractOAuthClient; import org.jboss.resteasy.skeleton.key.i18n.Messages; import org.jboss.resteasy.spi.ResteasyUriInfo; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.BadRequestException; import javax.ws.rs.InternalServerErrorException; import javax.ws.rs.core.UriBuilder; import java.io.IOException; import java.net.URI; /** * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @version $Revision: 1 $ */ public class ServletOAuthClient extends AbstractOAuthClient { /** * Start the process of obtaining an access token by redirecting the browser * to the authentication server * * * * @param relativePath path relative to context root you want auth server to redirect back to * @param request * @param response * @throws IOException */ public void redirectRelative(String relativePath, HttpServletRequest request, HttpServletResponse response) throws IOException { ResteasyUriInfo uriInfo = ServletUtil.extractUriInfo(request, null); String redirect = uriInfo.getBaseUriBuilder().path(relativePath).toTemplate(); redirect(redirect, request, response); } /** * Start the process of obtaining an access token by redirecting the browser * to the authentication server * * @param redirectUri full URI you want auth server to redirect back to * @param request * @param response * @throws IOException */ public void redirect(String redirectUri, HttpServletRequest request, HttpServletResponse response) throws IOException { String state = getStateCode(); URI url = UriBuilder.fromUri(authUrl) .queryParam("client_id", clientId) .queryParam("redirect_uri", redirectUri) .queryParam("state", state) .build(); String cookiePath = request.getContextPath(); if (cookiePath.equals("")) cookiePath = "/"; Cookie cookie = new Cookie(stateCookieName, state); cookie.setSecure(true); cookie.setPath(cookiePath); response.addCookie(cookie); response.sendRedirect(url.toString()); } protected String getCookieValue(String name, HttpServletRequest request) { if (request.getCookies() == null) return null; for (Cookie cookie : request.getCookies()) { if (cookie.getName().equals(name)) return cookie.getValue(); } return null; } protected String getCode(HttpServletRequest request) { String query = request.getQueryString(); if (query == null) return null; String[] params = query.split("&"); for (String param : params) { int eq = param.indexOf('='); if (eq == -1) continue; String name = param.substring(0, eq); if (!name.equals("code")) continue; return param.substring(eq + 1); } return null; } /** * Obtain the code parameter from the url after being redirected back from the auth-server. Then * do an authenticated request back to the auth-server to turn the access code into an access token. * * @param request * @return * @throws BadRequestException * @throws InternalServerErrorException */ public String getBearerToken(HttpServletRequest request) throws BadRequestException, InternalServerErrorException { String error = request.getParameter("error"); if (error != null) throw new BadRequestException(new Exception(Messages.MESSAGES.oAuthError(error))); String redirectUri = request.getRequestURL().append("?").append(request.getQueryString()).toString(); String stateCookie = getCookieValue(stateCookieName, request); if (stateCookie == null) throw new BadRequestException(new Exception(Messages.MESSAGES.stateCookieNotSet())); // we can call get parameter as this should be a redirect String state = request.getParameter("state"); String code = request.getParameter("code"); if (state == null) throw new BadRequestException(new Exception(Messages.MESSAGES.stateParameterWasNull())); if (!state.equals(stateCookie)) { throw new BadRequestException(new Exception(Messages.MESSAGES.stateParameterInvalid())); } if (code == null) throw new BadRequestException(new Exception(Messages.MESSAGES.codeParameterWasNull())); return resolveBearerToken(redirectUri, code); } }