/* *Copyright (c) 2005-2013, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * *WSO2 Inc. licenses this file to you under the Apache License, *Version 2.0 (the "License"); you may not use this file except *in compliance with the License. *You may obtain a copy of the License at * *http://www.apache.org/licenses/LICENSE-2.0 * *Unless required by applicable law or agreed to in writing, *software distributed under the License is distributed on an *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *KIND, either express or implied. See the License for the *specific language governing permissions and limitations *under the License. */ package org.wso2.carbon.identity.oauth.ui; import org.apache.axis2.context.ConfigurationContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.owasp.encoder.Encode; import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.oauth.common.OAuthConstants; import org.wso2.carbon.identity.oauth.stub.OAuthServiceAuthenticationException; import org.wso2.carbon.identity.oauth.stub.types.Parameters; import org.wso2.carbon.identity.oauth.ui.client.OAuthServiceClient; import org.wso2.carbon.identity.oauth.ui.internal.OAuthUIServiceComponentHolder; import org.wso2.carbon.ui.CarbonUIUtil; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.net.URLDecoder; public class OAuthServlet extends HttpServlet { /** * */ private static final long serialVersionUID = -7309826651165509449L; private static final Log log = LogFactory.getLog(OAuthServlet.class); /* * (non-Javadoc) * * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String requestType = req.getPathInfo(); Parameters params = populateOauthConsumerData(req); Parameters token = null; String oauthToken = null; String oauthTokenSecret = null; String oauthCallbackConfirmed = null; try { String backendServerURL = CarbonUIUtil.getServerURL(OAuthUIServiceComponentHolder.getInstance().getServerConfigurationService()); ConfigurationContext configContext = OAuthUIServiceComponentHolder.getInstance().getConfigurationContextService().getServerConfigContext(); OAuthServiceClient client = new OAuthServiceClient(backendServerURL, configContext); if (requestType.indexOf(OAuthConstants.OAuth10AEndpoints.REQUEST_TOKEN_URL) > -1) { // To obtain a Request Token, the Consumer sends an HTTP request to the Service // Provider's Request Token URL. The Service Provider documentation specifies the // HTTP method for this request, and HTTP POST is RECOMMENDED.The Service Provider // verifies the signature and Consumer Key. If successful, it generates a Request // Token and Token Secret and returns them to the Consumer in the HTTP response body // as defined in Service Provider Response Parameters. The Service Provider MUST // ensure the Request Token cannot be exchanged for an Access Token until the User // successfully grants access in Obtaining User Authorization. String reqToken = null; PrintWriter out = resp.getWriter(); token = client.getOauthRequestToken(params); oauthToken = token.getOauthToken(); oauthTokenSecret = token.getOauthTokenSecret(); oauthCallbackConfirmed = "true"; reqToken = OAuthConstants.OAUTH_TOKEN + "=" + Encode.forUriComponent(oauthToken) + "&" + OAuthConstants.OAUTH_TOKEN_SECRET + "=" + Encode.forUriComponent(oauthTokenSecret) + "&" + OAuthConstants.OAUTH_CALLBACK_CONFIRMED + "=" + Encode.forUriComponent(oauthCallbackConfirmed); out.write(reqToken); out.close(); resp.setStatus(200); } else if (requestType.indexOf(OAuthConstants.OAuth10AEndpoints.AUTHORIZE_TOKEN_URL) > -1) { // In order for the Consumer to be able to exchange the Request Token for an Access // Token, the Consumer MUST obtain approval from the User by directing the User to // the Service Provider. The Consumer constructs an HTTP GET request to the Service // Provider's User Authorization URL. String userName = req.getParameter("oauth_user_name"); String password = req.getParameter("oauth_user_password"); String tokenFromSession = (String) req.getSession().getAttribute("oauth_req_token"); if (userName == null || password == null || tokenFromSession == null) { Parameters metadata = client.getScope(params.getOauthToken()); req.getSession().setAttribute("oauth_req_token", params.getOauthToken()); req.getSession().setAttribute("oauth_scope", metadata.getScope()); req.getSession().setAttribute("oauth_app_name", metadata.getAppName()); resp.sendRedirect(IdentityUtil.getServerURL("/carbon/oauth/oauth-login.jsp", false, true)); } } else if (requestType.indexOf(OAuthConstants.OAuth10AEndpoints.ACCESS_TOKEN_URL) > -1) { // The Request Token and Token Secret MUST be exchanged for an Access Token and // Token Secret. // To request an Access Token, the Consumer makes an HTTP request to the Service // Provider's Access Token URL. The Service Provider documentation specifies the // HTTP method for this request, and HTTP POST is RECOMMENDED. The request MUST be // signed per Signing Requests. String accessToken = null; PrintWriter out = resp.getWriter(); token = client.getAccessToken(params); accessToken = OAuthConstants.OAUTH_TOKEN + "=" + Encode.forUriComponent(token.getOauthToken()) + "&" + OAuthConstants.OAUTH_TOKEN_SECRET + "=" + Encode.forUriComponent(token.getOauthTokenSecret()); out.write(accessToken); out.close(); resp.setStatus(200); } } catch (OAuthServiceAuthenticationException e) { log.debug(e); resp.setStatus(401); resp.setHeader("WWW-Authenticate", "Basic realm=\"WSO2 IS\""); } catch (Exception e) { log.error(e); resp.setStatus(400); } } /* * Populates the Parameters object from the OAuth authorization header or query string. */ private Parameters populateOauthConsumerData(HttpServletRequest request) { String authHeader = null; Parameters params = null; String splitChar = ","; boolean noAuthorizationHeader = false; authHeader = request.getHeader("Authorization"); params = new Parameters(); if (authHeader == null) { noAuthorizationHeader = true; // No Authorization header available. authHeader = request.getQueryString(); splitChar = "&"; } StringBuilder nonAuthParams = new StringBuilder(); if (authHeader != null) { if (authHeader.startsWith("OAuth ") || authHeader.startsWith("oauth ")) { authHeader = authHeader.substring(authHeader.indexOf("o")); } String[] headers = authHeader.split(splitChar); if (headers != null && headers.length > 0) { for (int i = 0; i < headers.length; i++) { String[] elements = headers[i].split("="); if (elements != null && elements.length > 0) { if (OAuthConstants.OAuth10AParams.OAUTH_CONSUMER_KEY.equals(elements[0].trim())) { params.setOauthConsumerKey(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAuth10AParams.OAUTH_NONCE.equals(elements[0].trim())) { params.setOauthNonce(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAuth10AParams.OAUTH_SIGNATURE.equals(elements[0].trim())) { params.setOauthSignature(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAuth10AParams.OAUTH_SIGNATURE_METHOD.equals(elements[0].trim())) { params.setOauthSignatureMethod(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAuth10AParams.OAUTH_TIMESTAMP.equals(elements[0].trim())) { params.setOauthTimeStamp(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAuth10AParams.OAUTH_CALLBACK.equals(elements[0].trim())) { params.setOauthCallback(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAuth10AParams.SCOPE.equals(elements[0].trim())) { params.setScope(removeLeadingAndTrailingQuatation(elements[1].trim())); } else if (OAuthConstants.OAuth10AParams.OAUTH_DISPLAY_NAME.equals(elements[0].trim())) { params.setDisplayName(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAUTH_TOKEN.equals(elements[0].trim())) { params.setOauthToken(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAUTH_VERIFIER.equals(elements[0].trim())) { params.setOauthTokenVerifier(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAUTH_TOKEN_SECRET.equals(elements[0].trim())) { params.setOauthTokenSecret(removeLeadingAndTrailingQuatation(elements[1] .trim())); } else if (OAuthConstants.OAuth10AParams.OAUTH_VERSION.equals(elements[0].trim())) { params.setVersion(removeLeadingAndTrailingQuatation(elements[1].trim())); } else { nonAuthParams.append(elements[0].trim() + "=" + removeLeadingAndTrailingQuatation(elements[1].trim()) + "&"); } } } } } String nonOauthParamStr = nonAuthParams.toString(); if (!noAuthorizationHeader) { nonOauthParamStr = request.getQueryString() + "&"; } String scope = request.getParameter(OAuthConstants.OAuth10AParams.SCOPE); if (scope != null) { params.setScope(scope); } params.setHttpMethod(request.getMethod()); if (nonOauthParamStr.length() > 1) { params.setBaseString(request.getRequestURL().toString() + "?" + nonOauthParamStr.substring(0, nonOauthParamStr.length() - 1)); } else { params.setBaseString(request.getRequestURL().toString()); } return params; } private String removeLeadingAndTrailingQuatation(String base) { String result = base; if (base.startsWith("\"") || base.endsWith("\"")) { result = base.replace("\"", ""); } result = URLDecoder.decode(result); return result.trim(); } }