Updated Branches: refs/heads/master bf48fbcd0 -> dac3417d7
implementing session based authentication/authorization. backend bits done. todo : authenticate the frontend using carbon user-store Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/dac3417d Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/dac3417d Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/dac3417d Branch: refs/heads/master Commit: dac3417d713f385b759ad3af3a4c3e95cf9b13a7 Parents: bf48fbc Author: Pradeep Fernando <[email protected]> Authored: Sun Feb 2 17:04:59 2014 +0530 Committer: Pradeep Fernando <[email protected]> Committed: Sun Feb 2 17:04:59 2014 +0530 ---------------------------------------------------------------------- .../console/controllers/login.jag | 66 ++++++++------- .../console/controllers/loginSubmit.jag | 25 ++++++ .../console/controllers/router.jag | 4 +- .../console/jaggery.conf | 4 + .../modules/security/security.provider.js | 1 - .../console/themes/theme1/partials/login.hbs | 8 +- .../console/util/utility.jag | 51 ++++++++---- .../org/apache/stratos/rest/endpoint/Utils.java | 13 ++- .../endpoint/context/AuthenticationContext.java | 38 +++++++++ ...tractAuthenticationAuthorizationHandler.java | 4 +- .../CookieBasedAuthenticationHandler.java | 87 ++++++++++++++++++++ .../rest/endpoint/handlers/OAuthHandler.java | 2 + .../handlers/StratosAuthenticationHandler.java | 5 +- .../handlers/StratosAuthorizingHandler.java | 27 +++--- .../endpoint/services/AuthenticationAdmin.java | 67 +++++++++++++++ .../rest/endpoint/services/StratosAdmin.java | 31 +++++-- .../main/webapp/stratos/WEB-INF/cxf-servlet.xml | 6 +- 17 files changed, 363 insertions(+), 76 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.manager.console/console/controllers/login.jag ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.manager.console/console/controllers/login.jag b/components/org.apache.stratos.manager.console/console/controllers/login.jag index a45ab4e..ca4d54c 100755 --- a/components/org.apache.stratos.manager.console/console/controllers/login.jag +++ b/components/org.apache.stratos.manager.console/console/controllers/login.jag @@ -1,37 +1,45 @@ <% (function(){ - var dataConfig = require('/config/console.json'), - sso = require("sso"), - process = require("process"), - sessionId = session.getId(), - requestURI, - requestedPage = request.getParameter("requestedPage"), - relayState = '/console',log = new Log(); - log.info(dataConfig.ssoConfiguration.issuer); - var encodedSAMLAuthRequest = sso.client.getEncodedSAMLAuthRequest(dataConfig.ssoConfiguration.issuer); - postUrl = "https://" + process.getProperty('carbon.local.ip') + ":" + "9443"; - log.info(postUrl); + var log = new Log("controllers.login.jag"); + var dataConfig = require('/config/console.json'); + if(!dataConfig.ssoConfiguration.enabled){ + request.getMappedPath = function() { + return '/login.jag'; // setting path for caramel framework + }; + include('/login.jag'); + } else { + var sso = require("sso"), + process = require("process"), + sessionId = session.getId(), + requestURI, + requestedPage = request.getParameter("requestedPage"), + relayState = '/console',log = new Log(); + log.debug(dataConfig.ssoConfiguration.issuer); + var encodedSAMLAuthRequest = sso.client.getEncodedSAMLAuthRequest(dataConfig.ssoConfiguration.issuer); + postUrl = "https://" + process.getProperty('carbon.local.ip') + ":" + "9443"; + log.debug(postUrl); - if (!session.get("Loged")) { - %> + if (!session.get("Loged")) { + %> - <div> + <div> - <p>You are now being redirected to Identity Server. If the - redirection fails, please click on the button below.</p> - <form method="post" action="<%=postUrl%>/samlsso"> - <p> - <input type="hidden" name="SAMLRequest" value="<%= encodedSAMLAuthRequest %>"/> - <input type="hidden" name="RelayState" value="<%= relayState %>"/> - <input type="hidden" name="SSOAuthSessionID" value="<%= sessionId %>"/> - <button type="submit">Redirect manually</button> - </p> - </form> - </div> - <script type = "text/javascript" > - document.forms[0].submit(); - </script> - <% + <p>You are now being redirected to Identity Server. If the + redirection fails, please click on the button below.</p> + <form method="post" action="<%=postUrl%>/samlsso"> + <p> + <input type="hidden" name="SAMLRequest" value="<%= encodedSAMLAuthRequest %>"/> + <input type="hidden" name="RelayState" value="<%= relayState %>"/> + <input type="hidden" name="SSOAuthSessionID" value="<%= sessionId %>"/> + <button type="submit">Redirect manually</button> + </p> + </form> + </div> + <script type = "text/javascript" > + document.forms[0].submit(); + </script> + <% + } } }()); %> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.manager.console/console/controllers/loginSubmit.jag ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.manager.console/console/controllers/loginSubmit.jag b/components/org.apache.stratos.manager.console/console/controllers/loginSubmit.jag new file mode 100644 index 0000000..4cd11c3 --- /dev/null +++ b/components/org.apache.stratos.manager.console/console/controllers/loginSubmit.jag @@ -0,0 +1,25 @@ +<% +(function(){ + var log = new Log("controller.credentialSubmit"); + var utils = require('/util/utility.jag'); + var username = request.getParameter("username").trim(); + var password = request.getParameter("password"); // not trimming the password + log.info("username/password submitted"); + log.info(username); + log.info(password); + //authenticate with carbon usr-store + + + //call the authentication rest-endpoint and get the JSESSION_ID + var response = utils.consoleAppUtil.getSessionCookie(username,password); + log.info(response.data.Success.sessionId); + //TODO: handle the error scenario + //save the JSESSION_ID in current console.session. + var jSessionId = response.data.Success.sessionId; + session.put("JSESSIONID",jSessionId); + require('console').server.current(session,username); + //redirect + response.sendRedirect(request.getContextPath()); + +}()); +%> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.manager.console/console/controllers/router.jag ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.manager.console/console/controllers/router.jag b/components/org.apache.stratos.manager.console/console/controllers/router.jag index 50a3c4e..baa7832 100755 --- a/components/org.apache.stratos.manager.console/console/controllers/router.jag +++ b/components/org.apache.stratos.manager.console/console/controllers/router.jag @@ -13,14 +13,14 @@ var sm=securityModule.cached(); //This will short circuit the handling of the requests - //var passed=sm.check(session); + var passed=sm.check(session); //var tenantDomain = session.get("TENANT_DOMAIN"); //var roleArray = session.get("ROLE_ARRAY"); // comment out the above and uncomment below code bits for testing. It removes authentication/authorization // of the app. - var passed=true; + //var passed=true; var tenantDomain = "carbon.super"; var roleArray = ["admin","Internal/Everyone"]; http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.manager.console/console/jaggery.conf ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.manager.console/console/jaggery.conf b/components/org.apache.stratos.manager.console/console/jaggery.conf index 80b8f8f..d742b11 100644 --- a/components/org.apache.stratos.manager.console/console/jaggery.conf +++ b/components/org.apache.stratos.manager.console/console/jaggery.conf @@ -3,6 +3,10 @@ "logLevel": "info", "urlMappings":[ { + "url":"/loginSubmit", + "path":"/controllers/loginSubmit.jag" + }, + { "url":"/acs", "path":"/controllers/acs.jag" }, http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.manager.console/console/modules/security/security.provider.js ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.manager.console/console/modules/security/security.provider.js b/components/org.apache.stratos.manager.console/console/modules/security/security.provider.js index b21b4ac..6877312 100644 --- a/components/org.apache.stratos.manager.console/console/modules/security/security.provider.js +++ b/components/org.apache.stratos.manager.console/console/modules/security/security.provider.js @@ -7,7 +7,6 @@ var securityModule = function () { - var LOGGED_IN_USER = 'LOGGED_IN_USER'; var log=new Log('security.provider'); /* http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.manager.console/console/themes/theme1/partials/login.hbs ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.manager.console/console/themes/theme1/partials/login.hbs b/components/org.apache.stratos.manager.console/console/themes/theme1/partials/login.hbs index e6cf4a2..5857e5c 100644 --- a/components/org.apache.stratos.manager.console/console/themes/theme1/partials/login.hbs +++ b/components/org.apache.stratos.manager.console/console/themes/theme1/partials/login.hbs @@ -5,16 +5,16 @@ <div class="login-box"> <div class="login-box-top"> <h2 class="login-sub-title">Login to create cartridges</h2> - <form> + <form method="post" action="{{url "/loginSubmit"}}"> <div class="username-wrapper"> - <input class="input-username" type="text" placeholder="Email" /> + <input name="username" class="input-username" type="text" placeholder="Email" /> </div> <div class="password-wrapper"> - <input class="input-password" type="text" placeholder="Password" /> + <input name="password" class="input-password" type="text" placeholder="Password" /> </div> <div class="login-button-wrapper"> - <button class="btn btn-primary login-button" type="button">Sign In</button> + <button class="btn btn-primary login-button" type="submit">Sign In</button> </div> </form> </div> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.manager.console/console/util/utility.jag ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.manager.console/console/util/utility.jag b/components/org.apache.stratos.manager.console/console/util/utility.jag index 43e8f7e..a883585 100644 --- a/components/org.apache.stratos.manager.console/console/util/utility.jag +++ b/components/org.apache.stratos.manager.console/console/util/utility.jag @@ -160,20 +160,31 @@ consoleAppUtil = new function(){ } return configStatus; }; + + this.getRequestHeaders = function(ssoEnabled){ + var requestHeaders; + if(ssoEnabled){ + var accessToken = this.getAccessTokenFromSession(); + requestHeaders = { + "Authorization": "Bearer "+accessToken, + "Content-Type": "application/json" + }; + }else{ + requestHeaders = { + "Content-Type": "application/json", + "Cookie": "JSESSIONID="+session.get("JSESSIONID") + }; + } + return requestHeaders; + }; + // refactor sendRecive and send method. duplicate code... this.sendReceive = function(httpMethod,urlPostFix,data){ var config = require('/config/console.js').config(); var backendServerURL = config.backendServerConfiguration.url; // getting the access token from the session. var endpoint = backendServerURL + urlPostFix; - //var endpoint = "http://localhost:9000/stratos/admin" + urlPostFix; - - var accessToken = this.getAccessTokenFromSession(); - // the header values are constant - var headers = { - "Authorization": "Bearer "+accessToken, - "Content-Type": "application/json" - }; + var headers = this.getRequestHeaders(config.ssoConfiguration.enabled); var type = "json"; // response format var response; switch (httpMethod){ @@ -201,12 +212,7 @@ consoleAppUtil = new function(){ var backendServerURL = config.backendServerConfiguration.url; // getting the access token from the session. var endpoint = backendServerURL + urlPostFix; - var accessToken = this.getAccessTokenFromSession(); - // the header values are constant - var headers = { - "Authorization": "Bearer "+accessToken, - "Content-Type": "application/json" - }; + var headers = this.getRequestHeaders(config.ssoConfiguration.enabled); var type = "json"; // response format var response; switch (httpMethod){ @@ -247,10 +253,27 @@ consoleAppUtil = new function(){ return response; }; + this.getSessionCookie = function(userName, password){ + var config = require('/config/console.js').config(); + var backendServerURL = config.backendServerConfiguration.url; + var endpoint = backendServerURL + "/cookie"; + var sso = require("sso"); //TODO: get rid of this... + var basicAuthToken = sso.client.b64encode(userName + ":" + password); + var headers = { + "Authorization": "Basic "+basicAuthToken, + "Content-Type": "application/json" + }; + var response = get(endpoint,{},headers,"json"); + log.info(stringify(response)); + return response; + }; + this.getAccessTokenFromSession = function(){ return session.get("access_token"); }; + + }; http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/Utils.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/Utils.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/Utils.java index 638fb63..c702e16 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/Utils.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/Utils.java @@ -22,7 +22,7 @@ public class Utils { public static String buildMessage(int errorCode, String errorMessage) { String jsonResponse = "{\"Error\":{" + " \"errorCode\": \" " + errorCode + "\"," + - " \"errorMessage\": \" " + errorMessage + "\"," + + " \"errorMessage\": \" " + errorMessage + "\"" + "}" + "}"; return jsonResponse; @@ -31,7 +31,16 @@ public class Utils { public static String buildMessage(String errorMessage) { String jsonResponse = "{\"Error\":{" + " \"errorCode\": \" " + -1234 + "\"," + - " \"errorMessage\": \" " + errorMessage + "\"," + + " \"errorMessage\": \" " + errorMessage + "\"" + + "}" + + "}"; + return jsonResponse; + } + + + public static String buildAuthenticationSuccessMessage(String jSessionId) { + String jsonResponse = "{\"Success\":{" + + " \"sessionId\": \"" + jSessionId + "\"" + "}" + "}"; return jsonResponse; http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/context/AuthenticationContext.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/context/AuthenticationContext.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/context/AuthenticationContext.java new file mode 100644 index 0000000..a5cab41 --- /dev/null +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/context/AuthenticationContext.java @@ -0,0 +1,38 @@ +package org.apache.stratos.rest.endpoint.context;/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. + */ + +public class AuthenticationContext { + // maintaining the authenticated state in threadLocal. We want to skip subsequent authentication handlers + // once a request get authenticated by a handler. + private static final ThreadLocal<Boolean> authenticated = new ThreadLocal<Boolean>(){ + @Override + protected Boolean initialValue() { + return false; + } + }; + + + public static boolean isAthenticated(){ + return authenticated.get(); + } + + public static void setAuthenticated(boolean isAuthenticated){ + authenticated.set(isAuthenticated); + } +} http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/AbstractAuthenticationAuthorizationHandler.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/AbstractAuthenticationAuthorizationHandler.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/AbstractAuthenticationAuthorizationHandler.java index 4c0d274..de6d083 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/AbstractAuthenticationAuthorizationHandler.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/AbstractAuthenticationAuthorizationHandler.java @@ -20,6 +20,7 @@ import org.apache.cxf.jaxrs.ext.RequestHandler; import org.apache.cxf.jaxrs.impl.HttpHeadersImpl; import org.apache.cxf.jaxrs.model.ClassResourceInfo; import org.apache.cxf.message.Message; +import org.apache.stratos.rest.endpoint.context.AuthenticationContext; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; @@ -33,7 +34,8 @@ public abstract class AbstractAuthenticationAuthorizationHandler implements Requ public Response handleRequest(Message message, ClassResourceInfo classResourceInfo) { HttpHeaders headers = new HttpHeadersImpl(message); List<String> authHeader = headers.getRequestHeader(HttpHeaders.AUTHORIZATION); - if(authHeader != null && authHeader.size() > 0 && canHandle(authHeader.get(0).trim().split(" ")[0])){ + if(!AuthenticationContext.isAthenticated() && authHeader != null && authHeader.size() > 0 && + canHandle(authHeader.get(0).trim().split(" ")[0])){ return handle(message,classResourceInfo); } // give the control to the next handler http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CookieBasedAuthenticationHandler.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CookieBasedAuthenticationHandler.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CookieBasedAuthenticationHandler.java new file mode 100644 index 0000000..9ddf5fe --- /dev/null +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CookieBasedAuthenticationHandler.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.stratos.rest.endpoint.handlers; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.cxf.jaxrs.ext.MessageContext; +import org.apache.cxf.jaxrs.ext.RequestHandler; +import org.apache.cxf.jaxrs.impl.HttpHeadersImpl; +import org.apache.cxf.jaxrs.model.ClassResourceInfo; +import org.apache.cxf.message.Message; +import org.apache.stratos.rest.endpoint.Utils; +import org.apache.stratos.rest.endpoint.context.AuthenticationContext; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import sun.security.krb5.internal.crypto.crc32; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; +/* +* authenticate an incoming request using the session availability. Session is first established using the +* basic auth authentication. This handler will be the last to get executed in the current handler chain. Hence failure +* too provide a session would result in an authentication failure. +* */ +public class CookieBasedAuthenticationHandler implements RequestHandler { + private Log log = LogFactory.getLog(CookieBasedAuthenticationHandler.class); + + public Response handleRequest(Message message, ClassResourceInfo classResourceInfo) { + if(AuthenticationContext.isAthenticated()){ + return null; + } + + HttpServletRequest httpServletRequest = (HttpServletRequest)message.get("HTTP.REQUEST"); + HttpSession httpSession = httpServletRequest.getSession(false); + if(httpSession != null && isUserLoggedIn(httpSession)){ // if sesion is avaialble + String userName = (String)httpSession.getAttribute("userName"); + String tenantDomain = (String)httpSession.getAttribute("tenantDomain"); + int tenantId = (Integer)httpSession.getAttribute("tenantId"); + // the following will get used by the authorization handler.. + PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + carbonContext.setUsername(userName); + carbonContext.setTenantDomain(tenantDomain); + carbonContext.setTenantId(tenantId); + + AuthenticationContext.setAuthenticated(true); + return null; + + } + return Response.status(Response.Status.FORBIDDEN). + type(MediaType.APPLICATION_JSON).entity(Utils.buildMessage("The endpoint requires authentication")).build(); + } + + /* + * if the userName and tenantDomain is present in the session, we conclude this as an authenticated session. + * Thos params get set by the AuthenticationAdmin endpoint. + * */ + private boolean isUserLoggedIn(HttpSession httpSession){ + String userName = (String)httpSession.getAttribute("userName"); + String tenantDomain = (String)httpSession.getAttribute("tenantDomain"); + Integer tenantId = (Integer)httpSession.getAttribute("tenantId"); + if(userName != null && tenantDomain!=null && tenantId!=null) { + return true; + } + return false; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/OAuthHandler.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/OAuthHandler.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/OAuthHandler.java index ce7524f..74c0bc8 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/OAuthHandler.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/OAuthHandler.java @@ -24,6 +24,7 @@ import org.apache.cxf.jaxrs.ext.RequestHandler; import org.apache.cxf.jaxrs.impl.HttpHeadersImpl; import org.apache.cxf.jaxrs.model.ClassResourceInfo; import org.apache.cxf.message.Message; +import org.apache.stratos.rest.endpoint.context.AuthenticationContext; import org.apache.stratos.rest.endpoint.oauth2.ValidationServiceClient; import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO; @@ -78,6 +79,7 @@ public class OAuthHandler extends AbstractAuthenticationAuthorizationHandler { log.error("Error while validating access token", e); return Response.status(Response.Status.FORBIDDEN).build(); } + AuthenticationContext.setAuthenticated(true); return null; } } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java index b9da59c..f8f0bc2 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java @@ -27,6 +27,7 @@ import org.apache.cxf.message.Message; import org.apache.cxf.security.SecurityContext; import org.apache.stratos.rest.endpoint.ServiceHolder; import org.apache.stratos.rest.endpoint.Utils; +import org.apache.stratos.rest.endpoint.context.AuthenticationContext; import org.apache.stratos.rest.endpoint.exception.RestAPIException; import org.apache.stratos.rest.endpoint.security.StratosSecurityContext; import org.wso2.carbon.context.PrivilegedCarbonContext; @@ -97,7 +98,9 @@ public class StratosAuthenticationHandler extends AbstractAuthenticationAuthoriz //populate the secuirtyContext of authenticated user SecurityContext securityContext = new StratosSecurityContext(username); message.put(SecurityContext.class, securityContext); - // let request to continue + + // set the authenticated flag and let the request to continue + AuthenticationContext.setAuthenticated(true); return null; } else { log.warn("unable to authenticate the request"); http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java index d9a044d..a7e5f09 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java @@ -26,7 +26,6 @@ import org.apache.cxf.interceptor.security.AccessDeniedException; import org.apache.cxf.jaxrs.ext.RequestHandler; import org.apache.cxf.jaxrs.model.ClassResourceInfo; import org.apache.cxf.message.Message; -import org.apache.cxf.security.SecurityContext; import org.apache.cxf.service.Service; import org.apache.cxf.service.model.BindingOperationInfo; import org.apache.stratos.rest.endpoint.Utils; @@ -48,7 +47,7 @@ import java.util.*; * details using annotations present in the service bean. This particular implementation is inspired * by the {@link org.apache.cxf.jaxrs.security.SimpleAuthorizingFilter} */ -public class StratosAuthorizingHandler extends AbstractAuthenticationAuthorizationHandler { +public class StratosAuthorizingHandler implements RequestHandler { private Log log = LogFactory.getLog(StratosAuthorizingHandler.class); private static String SUPPORTED_AUTHENTICATION_TYPE = "Basic"; @@ -66,17 +65,18 @@ public class StratosAuthorizingHandler extends AbstractAuthenticationAuthorizati "equals", "toString", "hashCode"})); } - public boolean canHandle(String authHeaderPrefix){ - return SUPPORTED_AUTHENTICATION_TYPE.equals(authHeaderPrefix); - } - public Response handle(Message message, ClassResourceInfo resourceClass) { + + public Response handleRequest(Message message, ClassResourceInfo resourceClass) { try { - SecurityContext securityContext = message.get(SecurityContext.class); - Method method = getTargetMethod(message); - if (!authorize(securityContext, method)) { - log.warn("User :"+ securityContext.getUserPrincipal().getName() + "trying to perform unauthrorized action" + - " against the resource :"+ method); + + String userName = CarbonContext.getThreadLocalCarbonContext().getUsername(); + String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + Method targetMethod = getTargetMethod(message); + if (!authorize(userName,tenantDomain,tenantId,targetMethod)) { + log.warn("User :"+ userName + "trying to perform unauthrorized action" + + " against the resource :"+ targetMethod); return Response.status(Response.Status.FORBIDDEN).type(MediaType.APPLICATION_JSON). entity(Utils.buildMessage("The user does not have required permissions to " + "perform this operation")).build(); @@ -90,15 +90,12 @@ public class StratosAuthorizingHandler extends AbstractAuthenticationAuthorizati } } - private boolean authorize(SecurityContext securityContext, Method targetMethod) throws Exception{ + private boolean authorize(String userName, String tenantDomain,int tenantId, Method targetMethod) throws Exception{ // first we try to see whether this is a super.tenant only operation - String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); - int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); if (superTenantServiceSet.contains(targetMethod.getName()) && !isCurrentUserSuperTenant(tenantDomain, tenantId)) { return false; } // authorize using permissionString given as annotation in the service class - String userName = securityContext.getUserPrincipal().getName(); String permissionString = authorizationActionMap.get(targetMethod.getName()); // get the authorization manager for this tenant.. http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/AuthenticationAdmin.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/AuthenticationAdmin.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/AuthenticationAdmin.java new file mode 100644 index 0000000..7a2fd3d --- /dev/null +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/AuthenticationAdmin.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.stratos.rest.endpoint.services; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.stratos.rest.endpoint.Utils; +import org.apache.stratos.rest.endpoint.annotation.AuthorizationAction; +import org.wso2.carbon.context.PrivilegedCarbonContext; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("/auth/") +public class AuthenticationAdmin extends AbstractAdmin { + Log log = LogFactory.getLog(AuthenticationAdmin.class); + // TODO: investigate on the thread safety of this apprach... + @Context + HttpServletRequest httpServletRequest; + + + /* + This method gets called by the client who are interested in using session mechanism to authenticate themselves in + subsequent calls. This method call get authenticated by the basic authenticator. + Once the authenticated call received, the method creates a session. + + */ + @GET + @Path("/cookie") + @Produces("application/json") + @Consumes("application/json") + @AuthorizationAction("/permission/protected/manage/monitor/tenants") + public Response getCookie(){ + HttpSession httpSession = httpServletRequest.getSession(true);//create session if not found + PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + httpSession.setAttribute("userName",carbonContext.getUsername()); + httpSession.setAttribute("tenantDomain",carbonContext.getTenantDomain()); + httpSession.setAttribute("tenantId",carbonContext.getTenantId()); + + String sessionId = httpSession.getId(); + return Response.ok().header("WWW-Authenticate", "Basic").type(MediaType.APPLICATION_JSON). + entity(Utils.buildAuthenticationSuccessMessage(sessionId)).build(); + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java index 82f40c1..f86f8a9 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java @@ -28,6 +28,7 @@ import org.apache.stratos.manager.dto.Cartridge; import org.apache.stratos.manager.dto.SubscriptionInfo; import org.apache.stratos.manager.exception.ADCException; import org.apache.stratos.rest.endpoint.ServiceHolder; +import org.apache.stratos.rest.endpoint.Utils; import org.apache.stratos.rest.endpoint.annotation.AuthorizationAction; import org.apache.stratos.rest.endpoint.annotation.SuperTenantService; import org.apache.stratos.rest.endpoint.bean.CartridgeInfoBean; @@ -51,7 +52,12 @@ import org.wso2.carbon.user.core.tenant.Tenant; import org.wso2.carbon.user.core.tenant.TenantManager; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -59,16 +65,31 @@ import java.util.UUID; @Path("/admin/") public class StratosAdmin extends AbstractAdmin { private static Log log = LogFactory.getLog(StratosAdmin.class); + @Context + HttpServletRequest httpServletRequest; - @POST - @Path("/init") + + /* + This method gets called by the client who are interested in using session mechanism to authenticate themselves in + subsequent calls. This method call get authenticated by the basic authenticator. + Once the authenticated call received, the method creates a session. + + */ + @GET + @Path("/cookie") @Produces("application/json") @Consumes("application/json") @AuthorizationAction("/permission/protected/manage/monitor/tenants") - public void initialize () - throws RestAPIException { + public Response getCookie(){ + HttpSession httpSession = httpServletRequest.getSession(true);//create session if not found + PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + httpSession.setAttribute("userName",carbonContext.getUsername()); + httpSession.setAttribute("tenantDomain",carbonContext.getTenantDomain()); + httpSession.setAttribute("tenantId",carbonContext.getTenantId()); - //login + String sessionId = httpSession.getId(); + return Response.ok().header("WWW-Authenticate", "Basic").type(MediaType.APPLICATION_JSON). + entity(Utils.buildAuthenticationSuccessMessage(sessionId)).build(); } @POST http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/dac3417d/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml b/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml index 873bbbc..22a9ca3 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml +++ b/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml @@ -33,14 +33,16 @@ <jaxrs:providers> <ref bean="jsonProvider"/> <ref bean="exceptionHandler"/> - <ref bean="authenticationFilter"/> + <ref bean="basicAuthenticationFilter"/> + <ref bean="sessionAuthenticationFilter"/> <ref bean="authorizationFilter"/> <ref bean="OAuthFilter"/> </jaxrs:providers> </jaxrs:server> <bean id="stratosRestEndpointBean" class="org.apache.stratos.rest.endpoint.services.StratosAdmin"/> - <bean id="authenticationFilter" class="org.apache.stratos.rest.endpoint.handlers.StratosAuthenticationHandler"/> + <bean id="basicAuthenticationFilter" class="org.apache.stratos.rest.endpoint.handlers.StratosAuthenticationHandler"/> + <bean id="sessionAuthenticationFilter" class="org.apache.stratos.rest.endpoint.handlers.CookieBasedAuthenticationHandler"/> <bean id="authorizationFilter" class="org.apache.stratos.rest.endpoint.handlers.StratosAuthorizingHandler"> <property name="securedObject" ref="stratosRestEndpointBean"/> </bean>
