package com.perforce.workshop.tjuricek.p4oauth.controllers; import com.fasterxml.jackson.databind.ObjectMapper; import com.perforce.workshop.tjuricek.p4oauth.services.AccessTokenResult; import com.perforce.workshop.tjuricek.p4oauth.services.CodeService; import com.perforce.workshop.tjuricek.p4oauth.util.HttpServletRequestHelper; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.function.Function; import java.util.function.Supplier; /** * Handle access token requests. * <p> * See also <a href="http://tools.ietf.org/html/rfc6749#section-4.1.3">rfc6749 section 4.1.3</a> * <p> * TODO Technically, this requires Basic authentication access. */ public class AccessTokenPost implements ControllerMethod { private static final Logger logger = LogManager.getFormatterLogger(AccessTokenPost.class); public static final String ACCESS_TOKEN_PATH = "/grants/token"; private Function<HttpServletRequest, HttpServletRequestHelper> requestWrapper; private Supplier<CodeService> codeServiceSupplier; private ObjectMapper objectMapper; public AccessTokenPost(Function<HttpServletRequest, HttpServletRequestHelper> requestWrapper, Supplier<CodeService> codeServiceSupplier) { this.requestWrapper = requestWrapper; this.codeServiceSupplier = codeServiceSupplier; this.objectMapper = new ObjectMapper(); } @Override public boolean matches(HttpServletRequest baseRequest) { HttpServletRequestHelper request = requestWrapper.apply(baseRequest); return request.pathStartsWith(ACCESS_TOKEN_PATH) && request.hasMethod("POST") && request.paramEquals("grant_type", "authorization_code") && request.paramNotEmpty("code") && request.paramNotEmpty("redirect_uri") && request.paramNotEmpty("client_id"); } @Override public void handle(HttpServletRequest baseRequest, HttpServletResponse response) throws IOException, ServletException { HttpServletRequestHelper request = requestWrapper.apply(baseRequest); String login = getOrSendError(request, "client_id", response); if (login == null) return; String redirectUri = getOrSendError(request, "redirect_uri", response); if (redirectUri == null) return; String code = getOrSendError(request, "code", response); if (code == null) return; // Create access response AccessTokenResult result = codeServiceSupplier.get().createAccessToken(login, redirectUri, code); if (result.hasError()) { logger.warn("unable to create the access token, reason %s", result.getError()); // I'm not sure how much information we should return in the response // here. Just going to return this general error and that's it response.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } setAccessControlAllowOrigin(redirectUri, response); response.setContentType("application/json"); AccessTokenResponse tokenResponse = AccessTokenResponse.create(result.getAccessToken(), result.getPerforceToken()); objectMapper.writeValue(response.getOutputStream(), tokenResponse); } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#3 | 9182 | tjuricek | 0.1.2 Added a password grant workflow | ||
#2 | 9157 | tjuricek | Added basic "authorization code" workflow test. | ||
#1 | 9095 | tjuricek | Added some basic test data and renamed "workspace" to "workshop" in package name | ||
//guest/tjuricek/p4oauth/src/main/java/com/perforce/workspace/tjuricek/p4oauth/controllers/AccessTokenPost.java | |||||
#1 | 9089 | tjuricek |
Moving some code that worked via some manual validation to the workshop. This just implements a basic code authorization grant scheme. Automated tests are forthcoming, awating some gradle plugin work that should sit outside of this project. |