Beispiel #1
0
  /**
   * アクセストークンを取得します. OAuthサービスプロバイダに認証コードを送信して、 認証済みリクエストトークンを交換してアクセストークンを取得します.
   *
   * @param verifier 認証コード
   * @param requestToken 認証済みリクエストトークン
   * @param tokenSecret トークンシークレット
   */
  public void getAccessToken(String verifier, String requestToken, String tokenSecret) {
    // OAuthコンシューマを作成
    OAuthConsumer consumer = new OAuthConsumer(callbackUrl, consumerKey, consumerSecret, provider);

    // OAuthのアクセサーを作成
    accessor = new OAuthAccessor(consumer);
    accessor.requestToken = requestToken;
    accessor.tokenSecret = tokenSecret;

    try {
      // アクセスコードをパラメータで渡す
      Map<String, Object> parameters = new HashMap<String, Object>();
      parameters.put(OAuth.OAUTH_VERIFIER, verifier);

      // アクセストークンを取得する
      OAuthMessage response = client.getAccessToken(accessor, null, parameters.entrySet());
      response.requireParameters(OAuth.OAUTH_TOKEN, OAuth.OAUTH_TOKEN_SECRET);
      System.out.println(OAuth.OAUTH_TOKEN + "(AccessToken): " + accessor.accessToken);
      System.out.println(OAuth.OAUTH_TOKEN_SECRET + ": " + accessor.tokenSecret);
    } catch (IOException e) {
      e.printStackTrace();
    } catch (OAuthException e) {
      e.printStackTrace();
    } catch (URISyntaxException e) {
      e.printStackTrace();
    }
  }
 /**
  * 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);
 }
 /**
  * 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);
   }
 }
  @Test
  public void testGetTemporaryCredentialsURIQuery() throws Exception {
    Map<String, String> parameters = new HashMap<String, String>();
    parameters.put(OAuth.OAUTH_CALLBACK, OAuthTestUtils.CALLBACK);

    // check all parameter transmissions
    for (ParameterStyle style : ParameterStyle.values()) {
      // for all signing methods
      for (String signMethod : OAuthTestUtils.SIGN_METHOD) {
        LOG.log(
            Level.INFO,
            "Preparing request with parameter style: {0} and signature method: {1}",
            new String[] {style.toString(), signMethod});

        parameters.put(OAuth.OAUTH_SIGNATURE_METHOD, signMethod);
        parameters.put(OAuth.OAUTH_NONCE, UUID.randomUUID().toString());
        parameters.put(OAuth.OAUTH_TIMESTAMP, String.valueOf(System.currentTimeMillis() / 1000));
        parameters.put(OAuth.OAUTH_CONSUMER_KEY, OAuthTestUtils.CLIENT_ID);
        OAuthMessage message = invokeRequestToken(parameters, style, OAuthServer.PORT);

        // test response ok
        boolean isFormEncoded = OAuth.isFormEncoded(message.getBodyType());
        Assert.assertTrue(isFormEncoded);

        List<OAuth.Parameter> responseParams = OAuthTestUtils.getResponseParams(message);

        String wwwHeader = message.getHeader("Authenticate");
        Assert.assertNull(wwwHeader);

        String callbacConf =
            OAuthTestUtils.findOAuthParameter(responseParams, OAuth.OAUTH_CALLBACK_CONFIRMED)
                .getValue();
        Assert.assertEquals("true", callbacConf);

        String oauthToken =
            OAuthTestUtils.findOAuthParameter(responseParams, OAuth.OAUTH_TOKEN).getKey();
        Assert.assertFalse(StringUtils.isEmpty(oauthToken));

        String tokenSecret =
            OAuthTestUtils.findOAuthParameter(responseParams, OAuth.OAUTH_TOKEN_SECRET).getKey();
        Assert.assertFalse(StringUtils.isEmpty(tokenSecret));

        // test wrong client id
        parameters.put(OAuth.OAUTH_CONSUMER_KEY, "wrong");
        message = invokeRequestToken(parameters, style, OAuthServer.PORT);
        String response = message.getHeader("oauth_problem");
        Assert.assertEquals(OAuth.Problems.CONSUMER_KEY_UNKNOWN, response);
      }
    }
  }
 private HttpResponse makeOAuthProblemReport(String code, String text, int rc) throws IOException {
   if (vagueErrors) {
     return new HttpResponseBuilder()
         .setHttpStatusCode(rc)
         .setResponseString("some vague error")
         .create();
   }
   OAuthMessage msg = new OAuthMessage(null, null, null);
   msg.addParameter("oauth_problem", code);
   msg.addParameter("oauth_problem_advice", text);
   return new HttpResponseBuilder()
       .setHttpStatusCode(rc)
       .addHeader("WWW-Authenticate", msg.getAuthorizationHeader("realm"))
       .create();
 }
 public static String getParameter(OAuthMessage requestMessage, String key) {
   try {
     return StringUtils.trim(requestMessage.getParameter(key));
   } catch (IOException e) {
     return null;
   }
 }
 /** Throw an exception if any SINGLE_PARAMETERS occur repeatedly. */
 protected void checkSingleParameters(OAuthMessage message) throws IOException, OAuthException {
   // Check for repeated oauth_ parameters:
   boolean repeated = false;
   Map<String, Collection<String>> nameToValues = new HashMap<String, Collection<String>>();
   for (Map.Entry<String, String> parameter : message.getParameters()) {
     String name = parameter.getKey();
     if (SINGLE_PARAMETERS.contains(name)) {
       Collection<String> values = nameToValues.get(name);
       if (values == null) {
         values = new ArrayList<String>();
         nameToValues.put(name, values);
       } else {
         repeated = true;
       }
       values.add(parameter.getValue());
     }
   }
   if (repeated) {
     Collection<OAuth.Parameter> rejected = new ArrayList<OAuth.Parameter>();
     for (Map.Entry<String, Collection<String>> p : nameToValues.entrySet()) {
       String name = p.getKey();
       Collection<String> values = p.getValue();
       if (values.size() > 1) {
         for (String value : values) {
           rejected.add(new OAuth.Parameter(name, value));
         }
       }
     }
     OAuthProblemException problem = new OAuthProblemException(OAuth.Problems.PARAMETER_REJECTED);
     problem.setParameter(OAuth.Problems.OAUTH_PARAMETERS_REJECTED, OAuth.formEncode(rejected));
     throw problem;
   }
 }
  protected SecurityToken verifyMessage(OAuthMessage message) throws OAuthProblemException {
    OAuthEntry entry = getOAuthEntry(message);
    OAuthConsumer authConsumer = getConsumer(message);

    OAuthAccessor accessor = new OAuthAccessor(authConsumer);

    if (entry != null) {
      accessor.tokenSecret = entry.tokenSecret;
      accessor.accessToken = entry.token;
    }

    try {
      message.validateMessage(accessor, new SimpleOAuthValidator());
    } catch (OAuthProblemException e) {
      throw e;
    } catch (OAuthException e) {
      OAuthProblemException ope = new OAuthProblemException(OAuth.Problems.SIGNATURE_INVALID);
      ope.setParameter(OAuth.Problems.OAUTH_PROBLEM_ADVICE, e.getMessage());
      throw ope;
    } catch (IOException e) {
      OAuthProblemException ope = new OAuthProblemException(OAuth.Problems.SIGNATURE_INVALID);
      ope.setParameter(OAuth.Problems.OAUTH_PROBLEM_ADVICE, e.getMessage());
      throw ope;
    } catch (URISyntaxException e) {
      OAuthProblemException ope = new OAuthProblemException(OAuth.Problems.SIGNATURE_INVALID);
      ope.setParameter(OAuth.Problems.OAUTH_PROBLEM_ADVICE, e.getMessage());
      throw ope;
    }
    return getTokenFromVerifiedRequest(message, entry, authConsumer);
  }
 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;
 }
Beispiel #10
0
 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);
   }
 }
 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);
 }
 public SecurityToken getSecurityTokenFromRequest(HttpServletRequest request)
     throws InvalidAuthenticationException {
   OAuthMessage message = OAuthServlet.getMessage(request, null);
   if (StringUtils.isEmpty(getParameter(message, OAuth.OAUTH_SIGNATURE))) {
     // Is not an oauth request
     return null;
   }
   String bodyHash = getParameter(message, OAuthConstants.OAUTH_BODY_HASH);
   if (!StringUtils.isEmpty(bodyHash)) {
     verifyBodyHash(request, bodyHash);
   }
   try {
     return verifyMessage(message);
   } catch (OAuthProblemException oauthException) {
     // Legacy body signing is intended for backwards compatability with opensocial clients
     // that assumed they could use the raw request body as a pseudo query param to get
     // body signing. This assumption was born out of the limitations of the OAuth 1.0 spec which
     // states that request bodies are only signed if they are form-encoded. This lead many clients
     // to force a content type of application/x-www-form-urlencoded for xml/json bodies and then
     // hope that receiver decoding of the body didnt have encoding issues. This didn't work out
     // to well so now these clients are required to specify the correct content type. This code
     // lets clients which sign using the old technique to work if they specify the correct content
     // type. This support is deprecated and should be removed later.
     if (allowLegacyBodySigning
         && (StringUtils.isEmpty(request.getContentType())
             || !request.getContentType().contains(OAuth.FORM_ENCODED))) {
       try {
         message.addParameter(readBodyString(request), "");
         return verifyMessage(message);
       } catch (OAuthProblemException ioe) {
         // ignore, let original exception be thrown
       } catch (IOException e) {
         // also ignore;
       }
     }
     throw new InvalidAuthenticationException("OAuth Authentication Failure", oauthException);
   }
 }
 /**
  * Construct an HTTP request from this OAuth message.
  *
  * @param style where to put the OAuth parameters, within the HTTP request
  */
 public static HttpMessage newRequest(OAuthMessage from, ParameterStyle style) throws IOException {
   final boolean isPost = OAuthMessage.POST.equalsIgnoreCase(from.method);
   InputStream body = from.getBodyAsStream();
   if (style == ParameterStyle.BODY && !(isPost && body == null)) {
     style = ParameterStyle.QUERY_STRING;
   }
   String url = from.URL;
   final List<Map.Entry<String, String>> headers =
       new ArrayList<Map.Entry<String, String>>(from.getHeaders());
   switch (style) {
     case QUERY_STRING:
       url = OAuth.addParameters(url, from.getParameters());
       break;
     case BODY:
       {
         byte[] form = OAuth.formEncode(from.getParameters()).getBytes(from.getBodyEncoding());
         headers.add(new OAuth.Parameter(CONTENT_TYPE, OAuth.FORM_ENCODED));
         headers.add(new OAuth.Parameter(CONTENT_LENGTH, form.length + ""));
         body = new ByteArrayInputStream(form);
         break;
       }
     case AUTHORIZATION_HEADER:
       headers.add(new OAuth.Parameter("Authorization", from.getAuthorizationHeader(null)));
       // Find the non-OAuth parameters:
       List<Map.Entry<String, String>> others = from.getParameters();
       if (others != null && !others.isEmpty()) {
         others = new ArrayList<Map.Entry<String, String>>(others);
         for (Iterator<Map.Entry<String, String>> p = others.iterator(); p.hasNext(); ) {
           if (p.next().getKey().startsWith("oauth_")) {
             p.remove();
           }
         }
         // Place the non-OAuth parameters elsewhere in the request:
         if (isPost && body == null) {
           byte[] form = OAuth.formEncode(others).getBytes(from.getBodyEncoding());
           headers.add(new OAuth.Parameter(CONTENT_TYPE, OAuth.FORM_ENCODED));
           headers.add(new OAuth.Parameter(CONTENT_LENGTH, form.length + ""));
           body = new ByteArrayInputStream(form);
         } else {
           url = OAuth.addParameters(url, others);
         }
       }
       break;
   }
   HttpMessage httpRequest = new HttpMessage(from.method, new URL(url), body);
   httpRequest.headers.addAll(headers);
   return httpRequest;
 }
  private OAuthEntry getValidatedEntry(OAuthMessage requestMessage)
      throws IOException, ServletException, OAuthException, URISyntaxException {

    OAuthEntry entry = dataStore.getEntry(requestMessage.getToken());
    if (entry == null) throw new OAuthProblemException(OAuth.Problems.TOKEN_REJECTED);

    if (entry.type != OAuthEntry.Type.REQUEST)
      throw new OAuthProblemException(OAuth.Problems.TOKEN_USED);

    if (entry.isExpired()) throw new OAuthProblemException(OAuth.Problems.TOKEN_EXPIRED);

    // find consumer key, compare with supplied value, if present.

    if (requestMessage.getConsumerKey() == null) {
      OAuthProblemException e = new OAuthProblemException(OAuth.Problems.PARAMETER_ABSENT);
      e.setParameter(OAuth.Problems.OAUTH_PARAMETERS_ABSENT, OAuth.OAUTH_CONSUMER_KEY);
      throw e;
    }

    String consumerKey = entry.consumerKey;
    if (!consumerKey.equals(requestMessage.getConsumerKey()))
      throw new OAuthProblemException(OAuth.Problems.CONSUMER_KEY_REFUSED);

    OAuthConsumer consumer = dataStore.getConsumer(consumerKey);

    if (consumer == null) throw new OAuthProblemException(OAuth.Problems.CONSUMER_KEY_UNKNOWN);

    OAuthAccessor accessor = new OAuthAccessor(consumer);

    accessor.requestToken = entry.token;
    accessor.tokenSecret = entry.tokenSecret;

    VALIDATOR.validateMessage(requestMessage, accessor);

    return entry;
  }
  // 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));
  }
 protected void validateSignature(OAuthMessage message, OAuthAccessor accessor)
     throws OAuthException, IOException, URISyntaxException {
   message.requireParameters(
       OAuth.OAUTH_CONSUMER_KEY, OAuth.OAUTH_SIGNATURE_METHOD, OAuth.OAUTH_SIGNATURE);
   OAuthSignatureMethod.newSigner(message, accessor).validate(message);
 }
  // Loosely based off net.oauth.OAuthServlet, and even more loosely related
  // to the OAuth specification
  private MessageInfo parseMessage(HttpRequest request) {
    MessageInfo info = new MessageInfo();
    info.request = request;
    String method = request.getMethod();
    ParsedUrl parsed = new ParsedUrl(request.getUri().toString());

    List<OAuth.Parameter> params = Lists.newArrayList();
    params.addAll(parsed.getParsedQuery());

    if (!validParamLocations.contains(OAuthParamLocation.URI_QUERY)) {
      // Make sure nothing OAuth related ended up in the query string
      for (OAuth.Parameter p : params) {
        if (p.getKey().contains("oauth_")) {
          throw new RuntimeException("Found unexpected query param " + p.getKey());
        }
      }
    }

    // Parse authorization header
    if (validParamLocations.contains(OAuthParamLocation.AUTH_HEADER)) {
      String aznHeader = request.getHeader("Authorization");
      if (aznHeader != null) {
        info.aznHeader = aznHeader;
        for (OAuth.Parameter p : OAuthMessage.decodeAuthorization(aznHeader)) {
          if (!p.getKey().equalsIgnoreCase("realm")) {
            params.add(p);
          }
        }
      }
    }

    // Parse body
    info.body = request.getPostBodyAsString();
    try {
      info.rawBody = IOUtils.toByteArray(request.getPostBody());
    } catch (IOException e) {
      throw new RuntimeException("Can't read post body bytes", e);
    }
    if (OAuth.isFormEncoded(request.getHeader("Content-Type"))) {
      params.addAll(OAuth.decodeForm(request.getPostBodyAsString()));
      // If we're not configured to pass oauth parameters in the post body, double check
      // that they didn't end up there.
      if (!validParamLocations.contains(OAuthParamLocation.POST_BODY)) {
        if (info.body.contains("oauth_")) {
          throw new RuntimeException("Found unexpected post body data" + info.body);
        }
      }
    }

    // Return the lot
    info.message = new OAuthMessage(method, parsed.getLocation(), params);

    // Check for trusted parameters
    if (checkTrustedParams) {
      if (!"foo".equals(OAuthUtil.getParameter(info.message, "oauth_magic"))) {
        throw new RuntimeException("no oauth_trusted=foo parameter");
      }
      if (!"bar".equals(OAuthUtil.getParameter(info.message, "opensocial_magic"))) {
        throw new RuntimeException("no opensocial_trusted=foo parameter");
      }
      if (!"quux".equals(OAuthUtil.getParameter(info.message, "xoauth_magic"))) {
        throw new RuntimeException("no xoauth_magic=quux parameter");
      }
      trustedParamCount += 3;
    }

    return info;
  }
  /////////////////////
  // 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);
    }
  }
  protected void validate(Map payload, boolean isTrustedConsumer) throws LTIException {
    // check parameters
    String lti_message_type = (String) payload.get(BasicLTIConstants.LTI_MESSAGE_TYPE);
    String lti_version = (String) payload.get(BasicLTIConstants.LTI_VERSION);
    String oauth_consumer_key = (String) payload.get("oauth_consumer_key");
    String resource_link_id = (String) payload.get(BasicLTIConstants.RESOURCE_LINK_ID);
    String user_id = (String) payload.get(BasicLTIConstants.USER_ID);
    String context_id = (String) payload.get(BasicLTIConstants.CONTEXT_ID);

    boolean launch = true;
    if (BasicLTIUtil.equals(lti_message_type, "basic-lti-launch-request")) {
      launch = true;
    } else if (BasicLTIUtil.equals(lti_message_type, "ContentItemSelectionRequest")) {
      launch = false;
    } else {
      throw new LTIException("launch.invalid", "lti_message_type=" + lti_message_type, null);
    }

    if (!BasicLTIUtil.equals(lti_version, "LTI-1p0")) {
      throw new LTIException("launch.invalid", "lti_version=" + lti_version, null);
    }

    if (BasicLTIUtil.isBlank(oauth_consumer_key)) {
      throw new LTIException("launch.missing", "oauth_consumer_key", null);
    }

    if (launch && BasicLTIUtil.isBlank(resource_link_id)) {
      throw new LTIException("launch.missing", "resource_link_id", null);
    }

    if (BasicLTIUtil.isBlank(user_id)) {
      throw new LTIException("launch.missing", "user_id", null);
    }
    if (M_log.isDebugEnabled()) {
      M_log.debug("user_id=" + user_id);
    }

    // check tool_id
    String tool_id = (String) payload.get("tool_id");
    if (tool_id == null) {
      throw new LTIException("launch.tool_id.required", null, null);
    }

    // Trim off the leading slash and any trailing space
    tool_id = tool_id.substring(1).trim();
    if (M_log.isDebugEnabled()) {
      M_log.debug("tool_id=" + tool_id);
    }
    // store modified tool_id back in payload
    payload.put("tool_id", tool_id);
    final String allowedToolsConfig =
        ServerConfigurationService.getString("basiclti.provider.allowedtools", "");

    final String[] allowedTools = allowedToolsConfig.split(":");
    final List<String> allowedToolsList = Arrays.asList(allowedTools);

    if (launch && allowedTools != null && !allowedToolsList.contains(tool_id)) {
      throw new LTIException("launch.tool.notallowed", tool_id, null);
    }
    final Tool toolCheck = ToolManager.getTool(tool_id);
    if (launch && toolCheck == null) {
      throw new LTIException("launch.tool.notfound", tool_id, null);
    }

    // Check for the ext_sakai_provider_eid param. If set, this will contain the eid that we are to
    // use
    // in place of using the user_id parameter
    // WE still need that parameter though, so translate it from the given eid.
    boolean useProvidedEid = false;
    String ext_sakai_provider_eid = (String) payload.get(BasicLTIConstants.EXT_SAKAI_PROVIDER_EID);
    if (BasicLTIUtil.isNotBlank(ext_sakai_provider_eid)) {
      useProvidedEid = true;
      try {
        user_id = UserDirectoryService.getUserId(ext_sakai_provider_eid);
      } catch (Exception e) {
        M_log.error(e.getLocalizedMessage(), e);
        throw new LTIException(
            "launch.provided.eid.invalid", "ext_sakai_provider_eid=" + ext_sakai_provider_eid, e);
      }
    }

    if (M_log.isDebugEnabled()) {
      M_log.debug("ext_sakai_provider_eid=" + ext_sakai_provider_eid);
    }

    // Contextualize the context_id with the OAuth consumer key
    // Also use the resource_link_id for the context_id if we did not get a context_id
    // BLTI-31: if trusted, context_id is required and use the param without modification
    if (BasicLTIUtil.isBlank(context_id)) {
      if (isTrustedConsumer) {
        throw new LTIException("launch.missing", context_id, null);
      } else {
        context_id = "res:" + resource_link_id;
        payload.put(BasicLTIConstants.CONTEXT_ID, context_id);
      }
    }

    // Check if context_id is simply a ~. If so, get the id of that user's My Workspace site
    // and use that to construct the full context_id
    if (BasicLTIUtil.equals(context_id, "~")) {
      if (useProvidedEid) {
        String userSiteId = null;
        try {
          userSiteId = SiteService.getUserSiteId(user_id);
        } catch (Exception e) {
          M_log.warn("Failed to get My Workspace site for user_id:" + user_id);
          M_log.error(e.getLocalizedMessage(), e);
          throw new LTIException("launch.user.site.unknown", "user_id=" + user_id, e);
        }
        context_id = userSiteId;
        payload.put(BasicLTIConstants.CONTEXT_ID, context_id);
      }
    }

    if (M_log.isDebugEnabled()) {
      M_log.debug("context_id=" + context_id);
    }

    // Lookup the secret
    final String configPrefix = "basiclti.provider." + oauth_consumer_key + ".";
    final String oauth_secret = ServerConfigurationService.getString(configPrefix + "secret", null);
    if (oauth_secret == null) {
      throw new LTIException("launch.key.notfound", oauth_consumer_key, null);
    }
    final OAuthMessage oam = (OAuthMessage) payload.get("oauth_message");

    final String forcedURIScheme =
        ServerConfigurationService.getString("basiclti.provider.forcedurischeme", null);

    if (forcedURIScheme != null) {
      try {
        URI testURI = new URI(oam.URL);
        URI newURI = new URI(forcedURIScheme, testURI.getSchemeSpecificPart(), null);
        oam.URL = newURI.toString();
      } catch (URISyntaxException use) {
      }
    }
    final OAuthValidator oav = new SimpleOAuthValidator();
    final OAuthConsumer cons =
        new OAuthConsumer(
            "about:blank#OAuth+CallBack+NotUsed", oauth_consumer_key, oauth_secret, null);

    final OAuthAccessor acc = new OAuthAccessor(cons);

    String base_string = null;
    try {
      base_string = OAuthSignatureMethod.getBaseString(oam);
    } catch (Exception e) {
      M_log.error(e.getLocalizedMessage(), e);
      base_string = null;
    }

    try {
      oav.validateMessage(oam, acc);
    } catch (Exception e) {
      M_log.warn("Provider failed to validate message");
      M_log.warn(e.getLocalizedMessage(), e);
      if (base_string != null) {
        M_log.warn(base_string);
      }
      throw new LTIException("launch.no.validate", context_id, e);
    }

    final Session sess = SessionManager.getCurrentSession();

    if (sess == null) {
      throw new LTIException("launch.no.session", context_id, null);
    }
  }