Package org.jboss.resteasy.auth.oauth

Source Code of org.jboss.resteasy.auth.oauth.OAuthServlet

package org.jboss.resteasy.auth.oauth;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthMessage;
import net.oauth.OAuthProblemException;
import org.jboss.resteasy.logging.Logger;


/**
* OAuth Http Servlet that handles Request Token creation and exchange for Access Tokens.
* @author Stéphane Épardaud <stef@epardaud.fr>
*/
public class OAuthServlet extends HttpServlet {
  private static final long serialVersionUID = 3083924242786185155L;

  private final static Logger logger = Logger.getLogger(OAuthServlet.class);

  /**
     * Servlet context parameter name for the Consumer Registration URL
     */
    final static String PARAM_CONSUMER_REGISTRATION_URL = "oauth.provider.consumer.registration";
 
  /**
   * Servlet context parameter name for the Request Token distribution URL
   */
  final static String PARAM_REQUEST_TOKEN_URL = "oauth.provider.tokens.request";

  /**
     * Servlet context parameter name for the Request Token authorization URL
     */
    final static String PARAM_TOKEN_AUTHORIZATION_URL = "oauth.provider.tokens.authorization";
 
  /**
   * Servlet context parameter name for the Request Token echange URL
   */
  final static String PARAM_ACCESS_TOKEN_URL = "oauth.provider.tokens.access";
 
  /**
   * Servlet context parameter name for the OAuthProvider class name
   */
  final static String PARAM_PROVIDER_CLASS = "oauth.provider.provider-class";
 
  /**
     * Relative path for the token authorization confirmation URL
     */
    final static String CONSUMER_SCOPES_REGISTRATION_URL = "/consumer/scopes";
 
  /**
     * Relative path for the token authorization confirmation URL
     */
    final static String TOKEN_AUTHORIZATION_CONFIRM_URL = "/authorization/confirm";
   
    /**
     * Default token authorization HTML resource
     */
    final static String DEFAULT_TOKEN_HTML_RESOURCE = "/token_authorization.jsp";
   
    private String requestTokenURL, accessTokenURL, consumerRegistrationURL, authorizationURL;
    private OAuthProvider provider;
  private OAuthValidator validator;
 
  @Override
  public void init(ServletConfig config)
    throws ServletException {
    super.init(config);
    logger.info("Loading OAuth Servlet");
   
    // load the context-parameters
    ServletContext context = config.getServletContext();
    consumerRegistrationURL = context.getInitParameter(PARAM_CONSUMER_REGISTRATION_URL);
        if(consumerRegistrationURL == null)
            consumerRegistrationURL = "/consumer/registration";
   
        authorizationURL = context.getInitParameter(PARAM_TOKEN_AUTHORIZATION_URL);
        if(authorizationURL == null)
            authorizationURL = "/authorization";
       
    requestTokenURL = context.getInitParameter(PARAM_REQUEST_TOKEN_URL);
    if(requestTokenURL == null)
      requestTokenURL = "/requestToken";
    accessTokenURL = context.getInitParameter(PARAM_ACCESS_TOKEN_URL);
    if(accessTokenURL == null)
      accessTokenURL = "/accessToken";

    logger.info("Request token URL: "+ requestTokenURL);
    logger.info("Access token URL: "+ accessTokenURL);
   
    // now load the provider and validator
    provider = OAuthUtils.getOAuthProvider(context);
    validator = OAuthUtils.getValidator(context, provider);
    logger.debug("OAuthServlet loaded");
  }
 
  @Override
  protected void service(HttpServletRequest req,
      HttpServletResponse resp)
  throws ServletException,
  IOException{
    String pathInfo = req.getPathInfo();
    logger.debug("Serving "+pathInfo);
    logger.debug("Query "+req.getQueryString());
    if(pathInfo.equals(requestTokenURL))
      serveRequestToken(req, resp);
    else if(pathInfo.equals(accessTokenURL))
      serveAccessToken(req, resp);
    else if(pathInfo.equals(consumerRegistrationURL))
            serveConsumerRegistration(req, resp);
    else if(pathInfo.equals(authorizationURL))
            serveTokenAuthorization(req, resp);
    else if(pathInfo.startsWith(TOKEN_AUTHORIZATION_CONFIRM_URL))
        serveTokenAuthorizationConfirmation(req, resp);
    else if(pathInfo.startsWith(CONSUMER_SCOPES_REGISTRATION_URL))
            serveConsumerScopesRegistrationRequest(req, resp);
    else
      resp.sendError(HttpURLConnection.HTTP_NOT_FOUND);
  }

  private void serveRequestToken(HttpServletRequest req,
      HttpServletResponse resp) throws IOException {
    logger.debug("Request token");
    OAuthMessage message = OAuthUtils.readMessage(req);
    try{
      // require some parameters
      message.requireParameters(OAuth.OAUTH_CONSUMER_KEY,
          OAuth.OAUTH_SIGNATURE_METHOD,
          OAuth.OAUTH_SIGNATURE,
          OAuth.OAUTH_TIMESTAMP,
          OAuth.OAUTH_NONCE);
      logger.debug("Parameters present");

      String consumerKey = message.getParameter(OAuth.OAUTH_CONSUMER_KEY);
      // load the OAuth Consumer
      org.jboss.resteasy.auth.oauth.OAuthConsumer consumer = provider.getConsumer(consumerKey);
     
      // create some structures for net.oauth
      OAuthConsumer _consumer = new OAuthConsumer(null, consumerKey, consumer.getSecret(), null);
      OAuthAccessor accessor = new OAuthAccessor(_consumer);
     
      // validate the message
      validator.validateMessage(message, accessor, null);

      // create a new Request Token
      String callbackURI = message.getParameter(OAuth.OAUTH_CALLBACK);
      if (callbackURI != null && consumer.getConnectURI() != null
              && !callbackURI.startsWith(consumer.getConnectURI())) {
          throw new OAuthException(400, "Wrong callback URI");
      }
      OAuthToken token = provider.makeRequestToken(consumerKey,
                                  callbackURI,
                                  req.getParameterValues("xoauth_scope"),
                                  req.getParameterValues("xoauth_permission"));

      // send the Token information to the Client
      OAuthUtils.sendValues(resp, OAuth.OAUTH_TOKEN, token.getToken(),OAuth.OAUTH_TOKEN_SECRET, token.getSecret(), OAuthUtils.OAUTH_CALLBACK_CONFIRMED_PARAM, "true");
      resp.setStatus(HttpURLConnection.HTTP_OK);
      logger.debug("All OK");

    } catch (OAuthException x) {
      OAuthUtils.makeErrorResponse(resp, x.getMessage(), x.getHttpCode(), provider);
    } catch (OAuthProblemException x) {
      OAuthUtils.makeErrorResponse(resp, x.getProblem(), OAuthUtils.getHttpCode(x), provider);
    } catch (Exception x) {
      logger.error("Exception ", x);
      OAuthUtils.makeErrorResponse(resp, x.getMessage(), HttpURLConnection.HTTP_INTERNAL_ERROR, provider);
    }
  }


  private void serveAccessToken(HttpServletRequest req,
      HttpServletResponse resp) throws IOException {
    logger.debug("Access token");
    OAuthMessage message = OAuthUtils.readMessage(req);
    try{
      // request some parameters
      message.requireParameters(OAuth.OAUTH_CONSUMER_KEY,
          OAuth.OAUTH_TOKEN,
          OAuth.OAUTH_SIGNATURE_METHOD,
          OAuth.OAUTH_SIGNATURE,
          OAuth.OAUTH_TIMESTAMP,
          OAuth.OAUTH_NONCE,
          OAuthUtils.OAUTH_VERIFIER_PARAM);

      logger.debug("Parameters present");
     
      // load some parameters
      String consumerKey = message.getParameter(OAuth.OAUTH_CONSUMER_KEY);
      String requestTokenString = message.getParameter(OAuth.OAUTH_TOKEN);
      String verifier = message.getParameter(OAuth.OAUTH_VERIFIER);
     
      // get the Request Token to exchange
      OAuthToken requestToken = provider.getRequestToken(consumerKey, requestTokenString);
     
      // build some structures for net.oauth
      OAuthConsumer consumer = new OAuthConsumer(null, consumerKey, requestToken.getConsumer().getSecret(), null);
      OAuthAccessor accessor = new OAuthAccessor(consumer);
      accessor.requestToken = requestTokenString;
      accessor.tokenSecret = requestToken.getSecret();

      // verify the message signature
      validator.validateMessage(message, accessor, requestToken);

      // exchange the Request Token
      OAuthToken tokens = provider.makeAccessToken(consumerKey, requestTokenString, verifier);

      // send the Access Token
      OAuthUtils.sendValues(resp, OAuth.OAUTH_TOKEN, tokens.getToken(),OAuth.OAUTH_TOKEN_SECRET, tokens.getSecret());
      resp.setStatus(HttpURLConnection.HTTP_OK);
      logger.debug("All OK");

    } catch (OAuthException x) {
      OAuthUtils.makeErrorResponse(resp, x.getMessage(), x.getHttpCode(), provider);
    } catch (OAuthProblemException x) {
      OAuthUtils.makeErrorResponse(resp, x.getProblem(), OAuthUtils.getHttpCode(x), provider);
    } catch (Exception x) {
      logger.error("Exception ", x);
      OAuthUtils.makeErrorResponse(resp, x.getMessage(), HttpURLConnection.HTTP_INTERNAL_ERROR, provider);
    }
  }
 
  private void serveConsumerRegistration(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {
        logger.debug("Consumer registration");
       
        try{
            String[] values = req.getParameterValues(OAuth.OAUTH_CONSUMER_KEY);
            if (values == null || values.length != 1) {
                resp.setStatus(HttpURLConnection.HTTP_BAD_REQUEST);
                return;
            }
           
            String consumerKey = URLDecoder.decode(values[0], "UTF-8");
            String displayName = null;
            values = req.getParameterValues("xoauth_consumer_display_name");
            if (values != null && values.length == 1) {
                displayName = URLDecoder.decode(values[0], "UTF-8");
            }
           
            String connectURI = null;
            values = req.getParameterValues("xoauth_consumer_connect_uri");
            if (values != null && values.length == 1) {
                connectURI = URLDecoder.decode(values[0], "UTF-8");
            }
           
            org.jboss.resteasy.auth.oauth.OAuthConsumer consumer =
                provider.registerConsumer(consumerKey, displayName, connectURI);
           
            // send the shared key back to the registered consumer
            OAuthUtils.sendValues(resp, "xoauth_consumer_secret", consumer.getSecret());
            resp.setStatus(HttpURLConnection.HTTP_OK);
            logger.debug("All OK");

        } catch (Exception x) {
            logger.error("Exception ", x);
            OAuthUtils.makeErrorResponse(resp, x.getMessage(), HttpURLConnection.HTTP_INTERNAL_ERROR, provider);
        }
    }
 
  /**
   * Consumer scopes are URIs which the consumer will be able to access directly, by-passing the enduser
   * authorization (aka OAuth 2-leg, as a replacement for Basic Auth)
   *
   * This is strictly an administrative level operation and should be protected at the OAuthServlet level;
   * Typically, it will be a domain administrator who will perform this request on behalf of the
   * consumers.
   *
   * TODO: add serveConsumerScopesRegistrationPage - which will offer a list of registered consumers
   *       to admins; this page will eventually lead to serveConsumerScopesRegistrationRequest
   * TODO: perhaps we may want to introduce a dedicated servlet dedicated to managing consumers
     */
  private void serveConsumerScopesRegistrationRequest(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {
        logger.debug("Consumer registration");
       
        try{
            String[] values = req.getParameterValues(OAuth.OAUTH_CONSUMER_KEY);
            if (values == null || values.length != 1) {
                resp.setStatus(HttpURLConnection.HTTP_BAD_REQUEST);
                return;
            }
           
            String consumerKey = URLDecoder.decode(values[0], "UTF-8");
            String[] scopes = req.getParameterValues("xoauth_scope");
            if (scopes != null) {
                provider.registerConsumerScopes(consumerKey, scopes);
            }
           
            String[] permissions = req.getParameterValues("xoauth_permission");
            if (permissions != null) {
                provider.registerConsumerPermissions(consumerKey, permissions);
            }
           
            resp.setStatus(HttpURLConnection.HTTP_OK);
            logger.debug("All OK");

        } catch (Exception x) {
            logger.error("Exception ", x);
            OAuthUtils.makeErrorResponse(resp, x.getMessage(), HttpURLConnection.HTTP_INTERNAL_ERROR, provider);
        }
    }
 
  private void serveTokenAuthorization(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {
        logger.debug("Consumer token authorization request");
       
        try{
            String[] values = req.getParameterValues(OAuth.OAUTH_TOKEN);
            if (values == null || values.length != 1) {
                resp.setStatus(HttpURLConnection.HTTP_BAD_REQUEST);
                return;
            }
            String requestTokenKey = values[0];
           
            OAuthRequestToken requestToken = provider.getRequestToken(null, requestTokenKey);
            org.jboss.resteasy.auth.oauth.OAuthConsumer consumer = requestToken.getConsumer();
           
            // build the end user authentication and token authorization form
            String acceptHeader = req.getHeader("Accept");
            // TODO : properly check accept values, also support JSON
            String format = acceptHeader == null || acceptHeader.startsWith("application/xml") ? "xml" : "html";
           
            requestEndUserConfirmation(req, resp, consumer, requestToken, format);
           
        } catch (Exception x) {
            logger.error("Exception ", x);
            OAuthUtils.makeErrorResponse(resp, x.getMessage(), HttpURLConnection.HTTP_INTERNAL_ERROR, provider);
        }
    }
 
  private void requestEndUserConfirmation(HttpServletRequest req,
                                          HttpServletResponse resp,
                                          org.jboss.resteasy.auth.oauth.OAuthConsumer consumer,
                                          OAuthRequestToken requestToken,
                                          String format) {
     
      if ("xml".equals(format))
      {
          // TODO : try to get a default XSLT template, if found then use it
          // and only use in code formatting if no template is available
         
            String uri = getAuthorizationConfirmURI(req, requestToken.getToken());
          StringBuilder sb = new StringBuilder();
          sb.append("<tokenAuthorizationRequest xmlns=\"http://org.jboss.com/resteasy/oauth\" ")
              .append("replyTo=\"").append(uri).append("\">");
          sb.append("<consumerId>").append(consumer.getKey()).append("</consumerId>");
          if (consumer.getDisplayName() != null) {
              sb.append("<consumerName>").append(consumer.getDisplayName()).append("</consumerName>");
          }
          if (requestToken.getScopes() != null) {
              sb.append("<scopes>").append(requestToken.getScopes()[0]).append("</scopes>");
          }
          if (requestToken.getPermissions() != null) {
                sb.append("<permissions>").append(requestToken.getPermissions()[0]).append("</permissions>");
            }
          sb.append("</tokenAuthorizationRequest>");
          try {
              resp.getWriter().append(sb.toString());
              resp.setStatus(HttpURLConnection.HTTP_OK);
          } catch (IOException ex) {
              resp.setStatus(HttpURLConnection.HTTP_INTERNAL_ERROR);
          }
      } else if ("html".equals(format)) {
          // TODO : try to get a default XSLT template creating XHTML output, if found then use it
            // and redirect if no template is available
          RequestDispatcher dispatcher = req.getRequestDispatcher(DEFAULT_TOKEN_HTML_RESOURCE);
          if (dispatcher == null) {
              resp.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
              return;
          }
          try {
              req.setAttribute("oauth_consumer_id", consumer.getKey());
              req.setAttribute("oauth_consumer_display", consumer.getDisplayName());
              req.setAttribute("oauth_consumer_scopes", requestToken.getScopes());
              req.setAttribute("oauth_consumer_permissions", requestToken.getPermissions());
              req.setAttribute("oauth_request_token", requestToken.getToken());
              req.setAttribute("oauth_token_confirm_uri", getAuthorizationConfirmURI(req, null));
              dispatcher.forward(req, resp);
          } catch (Exception ex) {
              resp.setStatus(500);
          }
      }
      //else if ("json".equals(format)) {
        //}
  }
 
  public String getAuthorizationConfirmURI(HttpServletRequest req, String tokenKey) {
      String requestURI = req.getRequestURL().toString();
        int index = requestURI.lastIndexOf(authorizationURL);
        String baseURI = requestURI.substring(0, index);
        String uri = baseURI + TOKEN_AUTHORIZATION_CONFIRM_URL;
        if (tokenKey != null)
        {
            uri += ("?" + OAuth.OAUTH_TOKEN + "=" + OAuthUtils.encodeForOAuth(tokenKey));
        }
        return uri;
  }
 
  private void serveTokenAuthorizationConfirmation(HttpServletRequest req,
            HttpServletResponse resp) throws IOException {
        logger.debug("Consumer registration");
       
        try{
            String[] values = req.getParameterValues(OAuth.OAUTH_TOKEN);
            if (values == null || values.length != 1) {
                resp.setStatus(HttpURLConnection.HTTP_BAD_REQUEST);
                return;
            }
            String requestTokenKey = values[0];
           
            OAuthRequestToken requestToken = provider.getRequestToken(null, requestTokenKey);
            org.jboss.resteasy.auth.oauth.OAuthConsumer consumer = requestToken.getConsumer();
           
            values = req.getParameterValues("xoauth_end_user_decision");
            if (values == null || values.length != 1) {
                resp.setStatus(HttpURLConnection.HTTP_BAD_REQUEST);
                return;
            }
           
            boolean authorized = "yes".equals(values[0]) || "true".equals(values[0]);
           
            String callback = requestToken.getCallback();
            if (authorized)
            {
                String verifier = provider.authoriseRequestToken(consumer.getKey(), requestToken.getToken());
               
                if (callback == null) {
                    OAuthUtils.sendValues(resp, OAuth.OAUTH_TOKEN, requestTokenKey, OAuth.OAUTH_VERIFIER, verifier);
                    resp.setStatus(HttpURLConnection.HTTP_OK);
                } else {
                    List<OAuth.Parameter> parameters = new ArrayList<OAuth.Parameter>();
                    parameters.add(new OAuth.Parameter(OAuth.OAUTH_TOKEN, requestTokenKey));
                    parameters.add(new OAuth.Parameter(OAuth.OAUTH_VERIFIER, verifier));
                    String location = OAuth.addParameters(callback, parameters);
                    resp.addHeader("Location", location);
                    resp.setStatus(302);
                }
            }
            else
            {
                // TODO : make sure this response is OAuth compliant
                OAuthUtils.makeErrorResponse(resp, "Token has not been authorized", 503, provider);
            }
           
            logger.debug("All OK");

        } catch (Exception x) {
            logger.error("Exception ", x);
            OAuthUtils.makeErrorResponse(resp, x.getMessage(), HttpURLConnection.HTTP_INTERNAL_ERROR, provider);
        }
    }
}
TOP

Related Classes of org.jboss.resteasy.auth.oauth.OAuthServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.