/** * Check that the verifier is valid for the current message * * @author Jack Hsu */ public void validateVerifier(OAuthMessage message) throws IOException, OAuthException { String consumerKey = message.getConsumerKey(); String requestToken = message.getParameter(OAuth.OAUTH_TOKEN); String key = consumerKey + ":" + requestToken; String verifier = message.getParameter(OAuth.OAUTH_VERIFIER); if (verifier == null || !verifier.equals(VERIFIERS.get(key))) { throw new OAuthProblemException(OAuth.Problems.PARAMETER_REJECTED); } else { // Remove verifier so it can't be used again VERIFIERS.remove(key); } }
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { OAuthConsumer consumer = null; try { final OAuthMessage requestMessage = OAuthServlet.getMessage(request, null); requestMessage.requireParameters("consumer"); final String consumerName = requestMessage.getParameter("consumer"); consumer = CookieConsumer.getConsumer(consumerName, null); final CookieMap cookies = new CookieMap(request, response); final OAuthAccessor accessor = CookieConsumer.newAccessor(consumer, cookies); final String expectedToken = accessor.requestToken; String requestToken = requestMessage.getParameter(OAuth.OAUTH_TOKEN); if (requestToken == null || requestToken.length() <= 0) { log.warning(request.getMethod() + " " + OAuthServlet.getRequestURL(request)); requestToken = expectedToken; if (requestToken == null) { OAuthProblemException problem = new OAuthProblemException(OAuth.Problems.PARAMETER_ABSENT); problem.setParameter(OAuth.Problems.OAUTH_PARAMETERS_ABSENT, OAuth.OAUTH_TOKEN); throw problem; } } else if (!requestToken.equals(expectedToken)) { OAuthProblemException problem = new OAuthProblemException("token_rejected"); problem.setParameter("oauth_rejected_token", requestToken); problem.setParameter("oauth_expected_token", expectedToken); throw problem; } List<OAuth.Parameter> parameters = null; String verifier = requestMessage.getParameter(OAuth.OAUTH_VERIFIER); if (verifier != null) { parameters = OAuth.newList(OAuth.OAUTH_VERIFIER, verifier); } OAuthMessage result = CookieConsumer.CLIENT.getAccessToken(accessor, null, parameters); if (accessor.accessToken != null) { String returnTo = requestMessage.getParameter("returnTo"); if (returnTo == null) { returnTo = request.getContextPath(); // home page } cookies.remove(consumerName + ".requestToken"); cookies.put(consumerName + ".accessToken", accessor.accessToken); cookies.put(consumerName + ".tokenSecret", accessor.tokenSecret); throw new RedirectException(returnTo); } OAuthProblemException problem = new OAuthProblemException(OAuth.Problems.PARAMETER_ABSENT); problem.setParameter(OAuth.Problems.OAUTH_PARAMETERS_ABSENT, OAuth.OAUTH_TOKEN); problem.getParameters().putAll(result.getDump()); throw problem; } catch (Exception e) { CookieConsumer.handleException(e, request, response, consumer); } }
public static String getParameter(OAuthMessage requestMessage, String key) { try { return StringUtils.trim(requestMessage.getParameter(key)); } catch (IOException e) { return null; } }
public String generateVerifier(OAuthAccessor accessor, OAuthMessage message) throws IOException { String consumerKey = accessor.consumer.consumerKey; String requestToken = message.getParameter(OAuth.OAUTH_TOKEN); String key = consumerKey + ":" + requestToken; String verifier = String.format("%08d", RANDOM_NUMBER.nextInt(99999999)); VERIFIERS.put(key, verifier); return verifier; }
/** * Throw an exception if the timestamp is out of range or the nonce has been validated previously. */ protected void validateTimestampAndNonce(OAuthMessage message) throws IOException, OAuthProblemException { message.requireParameters(OAuth.OAUTH_TIMESTAMP, OAuth.OAUTH_NONCE); long timestamp = Long.parseLong(message.getParameter(OAuth.OAUTH_TIMESTAMP)); long now = currentTimeMsec(); validateTimestamp(message, timestamp, now); validateNonce(message, timestamp, now); }
protected void validateVersion(OAuthMessage message) throws OAuthException, IOException { String versionString = message.getParameter(OAuth.OAUTH_VERSION); if (versionString != null) { double version = Double.parseDouble(versionString); if (version < minVersion || maxVersion < version) { OAuthProblemException problem = new OAuthProblemException(OAuth.Problems.VERSION_REJECTED); problem.setParameter( OAuth.Problems.OAUTH_ACCEPTABLE_VERSIONS, minVersion + "-" + maxVersion); throw problem; } } }
// Hand out a request token if the consumer key and secret are valid private void createRequestToken( HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, OAuthException, URISyntaxException { OAuthMessage requestMessage = OAuthServlet.getMessage(servletRequest, null); String consumerKey = requestMessage.getConsumerKey(); if (consumerKey == null) { OAuthProblemException e = new OAuthProblemException(OAuth.Problems.PARAMETER_ABSENT); e.setParameter(OAuth.Problems.OAUTH_PARAMETERS_ABSENT, OAuth.OAUTH_CONSUMER_KEY); throw e; } OAuthConsumer consumer = dataStore.getConsumer(consumerKey); if (consumer == null) throw new OAuthProblemException(OAuth.Problems.CONSUMER_KEY_UNKNOWN); OAuthAccessor accessor = new OAuthAccessor(consumer); VALIDATOR.validateMessage(requestMessage, accessor); String callback = null; if (enableSignedCallbacks) { callback = requestMessage.getParameter(OAuth.OAUTH_CALLBACK); } if (callback == null && !enableOAuth10) { OAuthProblemException e = new OAuthProblemException(OAuth.Problems.PARAMETER_ABSENT); e.setParameter(OAuth.Problems.OAUTH_PARAMETERS_ABSENT, OAuth.OAUTH_CALLBACK); throw e; } // generate request_token and secret OAuthEntry entry = dataStore.generateRequestToken( consumerKey, requestMessage.getParameter(OAuth.OAUTH_VERSION), callback); List<Parameter> responseParams = OAuth.newList(OAuth.OAUTH_TOKEN, entry.token, OAuth.OAUTH_TOKEN_SECRET, entry.tokenSecret); if (callback != null) { responseParams.add(new Parameter(OAuthConstants.OAUTH_CALLBACK_CONFIRMED, "true")); } sendResponse(servletResponse, responseParams); }
/** * Throw an exception if the nonce has been validated previously. * * @return the earliest point in time at which a call to releaseGarbage will actually release some * garbage, or null to indicate there's nothing currently stored that will become garbage in * future. */ protected Date validateNonce(OAuthMessage message, long timestamp, long currentTimeMsec) throws IOException, OAuthProblemException { UsedNonce nonce = new UsedNonce( timestamp, message.getParameter(OAuth.OAUTH_NONCE), message.getConsumerKey(), message.getToken()); /* * The OAuth standard requires the token to be omitted from the stored * nonce. But I include it, to harmonize with a Consumer that generates * nonces using several independent computers, each with its own token. */ boolean valid = false; synchronized (usedNonces) { valid = usedNonces.add(nonce); } if (!valid) { throw new OAuthProblemException(OAuth.Problems.NONCE_USED); } return removeOldNonces(currentTimeMsec); }
// Hand out an access token if the consumer key and secret are valid and the user authorized // the requestToken private void createAccessToken( HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws ServletException, IOException, OAuthException, URISyntaxException { OAuthMessage requestMessage = OAuthServlet.getMessage(servletRequest, null); OAuthEntry entry = getValidatedEntry(requestMessage); if (entry == null) throw new OAuthProblemException(OAuth.Problems.TOKEN_REJECTED); if (entry.callbackToken != null) { // We're using the fixed protocol String clientCallbackToken = requestMessage.getParameter(OAuthConstants.OAUTH_VERIFIER); if (!entry.callbackToken.equals(clientCallbackToken)) { dataStore.disableToken(entry); servletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "This token is not authorized"); return; } } else if (!entry.authorized) { // Old protocol. Catch consumers trying to convert a token to one that's not authorized dataStore.disableToken(entry); servletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "This token is not authorized"); return; } // turn request token into access token OAuthEntry accessEntry = dataStore.convertToAccessToken(entry); sendResponse( servletResponse, OAuth.newList( OAuth.OAUTH_TOKEN, accessEntry.token, OAuth.OAUTH_TOKEN_SECRET, accessEntry.tokenSecret, "user_id", entry.userId)); }
///////////////////// // deal with authorization request private void authorizeRequestToken( HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws ServletException, IOException, OAuthException, URISyntaxException { OAuthMessage requestMessage = OAuthServlet.getMessage(servletRequest, null); if (requestMessage.getToken() == null) { // MALFORMED REQUEST servletResponse.sendError( HttpServletResponse.SC_BAD_REQUEST, "Authentication token not found"); return; } OAuthEntry entry = dataStore.getEntry(requestMessage.getToken()); if (entry == null) { servletResponse.sendError(HttpServletResponse.SC_NOT_FOUND, "OAuth Entry not found"); return; } OAuthConsumer consumer = dataStore.getConsumer(entry.consumerKey); // Extremely rare case where consumer dissappears if (consumer == null) { servletResponse.sendError(HttpServletResponse.SC_NOT_FOUND, "consumer for entry not found"); return; } // A flag to deal with protocol flaws in OAuth/1.0 Boolean securityThreat_2009_1 = !entry.callbackUrlSigned; // Check for a callback in the oauth entry String callback = entry.callbackUrl; if (callback == null) { // see if there's a callback in the url params callback = requestMessage.getParameter(OAuth.OAUTH_CALLBACK); } if (callback == null) { // see if the consumer has a callback callback = consumer.callbackURL; } // The token is disabled if you try to convert to an access token prior to authorization if (entry.type == OAuthEntry.Type.DISABLED) { servletResponse.sendError( HttpServletResponse.SC_FORBIDDEN, "This token is disabled, please reinitate login"); return; } // Redirect to a UI flow if the token is not authorized if (!entry.authorized) { // TBD -- need to decode encrypted payload somehow.. if (this.oauthAuthorizeAction.startsWith("http")) { // Redirect to authorization page with params // Supply standard set of params // TBD } else { // Use internal forward to a jsp page servletRequest.setAttribute("OAUTH_DATASTORE", dataStore); servletRequest.setAttribute("OAUTH_ENTRY", entry); servletRequest.setAttribute("CALLBACK", callback); servletRequest.setAttribute("TOKEN", entry.token); servletRequest.setAttribute("CONSUMER", consumer); servletRequest.setAttribute("SECURITY_THREAT_2009_1", securityThreat_2009_1); servletRequest .getRequestDispatcher(oauthAuthorizeAction) .forward(servletRequest, servletResponse); } return; } // If we're here then the entry has been authorized // redirect to callback if (callback == null || "oob".equals(callback)) { // consumer did not specify a callback servletResponse.setContentType("text/plain"); PrintWriter out = servletResponse.getWriter(); out.write("Token successfully authorized.\n"); if (entry.callbackToken != null) { // Usability fail. out.write("Please enter code " + entry.callbackToken + " at the consumer."); } } else { callback = OAuth.addParameters(callback, OAuth.OAUTH_TOKEN, entry.token); // Add user_id to the callback callback = OAuth.addParameters(callback, "user_id", entry.userId); if (entry.callbackToken != null) { callback = OAuth.addParameters(callback, OAuthConstants.OAUTH_VERIFIER, entry.callbackToken); } servletResponse.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); servletResponse.setHeader("Location", callback); } }