Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add user session management rest API endpoint #16

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@
</build>

<dependencies>
<dependency>
<groupId>org.wso2.carbon.identity.governance</groupId>
<artifactId>org.wso2.carbon.identity.user.session</artifactId>
<scope>provided</scope>
<version>1.0.1</version>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the version as a property to the parent pom

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved with 78b6e0a

</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Copyright (c) 2018, 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.local.auth.api.endpoint.impl;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils;
import org.wso2.carbon.identity.local.auth.api.endpoint.SessionApiService;
import org.wso2.carbon.identity.local.auth.api.endpoint.dto.AllSessionsDTO;
import org.wso2.carbon.identity.local.auth.api.endpoint.util.AuthAPIEndpointUtil;
import org.wso2.carbon.identity.user.session.exception.SessionManagementClientException;
import org.wso2.carbon.identity.user.session.exception.SessionManagementException;
import org.wso2.carbon.identity.user.session.model.UserSession;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response;

import static org.wso2.carbon.identity.local.auth.api.endpoint.util.AuthAPIEndpointUtil.getSessionManager;
import static org.wso2.carbon.identity.local.auth.api.endpoint.util.AuthAPIEndpointUtil.getSessionResponse;
import static org.wso2.carbon.identity.user.session.constant.SessionConstants.ErrorMessages.ERROR_CODE_NO_AUTH_USER_FOUND;
import static org.wso2.carbon.identity.user.session.constant.SessionConstants.ErrorMessages.ERROR_CODE_SESSION_ID_INVALID;
import static org.wso2.carbon.identity.user.session.constant.SessionConstants.ErrorMessages.ERROR_CODE_UNEXPECTED;
import static org.wso2.carbon.identity.user.session.constant.SessionConstants.ErrorMessages.ERROR_CODE_USER_NOT_AUTHORIZED;

public class SessionApiServiceImpl extends SessionApiService {

private static final Log log = LogFactory.getLog(SessionApiServiceImpl.class);

@Override
public Response getUserSession(MessageContext context) {
try {
String sessionId = getSessionContextKey(context.getHttpServletRequest());
if (sessionId != null) {
UserSession[] userSessions = getSessionManager().viewSession(sessionId);
AllSessionsDTO sessionResponse = getSessionResponse(userSessions);
return Response.ok().entity(sessionResponse).build();
}
return Response.ok().build();
} catch (SessionManagementClientException e) {
return handleBadRequestResponse(e);
} catch (SessionManagementException e) {
return handleServerErrorResponse(e);
} catch (Throwable throwable) {
return handleUnexpectedServerError(throwable);
}
}

@Override
public Response terminateASession(MessageContext context, String sessionId) {
try {
String currentSessionId = getSessionContextKey(context.getHttpServletRequest());
boolean terminateSession = getSessionManager().terminateASession(currentSessionId, sessionId);
return Response.ok().entity(terminateSession).build();
} catch (SessionManagementClientException e) {
return handleBadRequestResponse(e);
} catch (SessionManagementException e) {
return handleServerErrorResponse(e);
} catch (Throwable throwable) {
return handleUnexpectedServerError(throwable);
}
}

@Override
public Response terminateAllSessions(MessageContext context) {
try {
String sessionId = getSessionContextKey(context.getHttpServletRequest());
boolean terminateSession = getSessionManager().terminateAllSession(sessionId);
return Response.ok().entity(terminateSession).build();
} catch (SessionManagementClientException e) {
return handleBadRequestResponse(e);
} catch (SessionManagementException e) {
return handleServerErrorResponse(e);
} catch (Throwable throwable) {
return handleUnexpectedServerError(throwable);
}
}

/**
* Method to get sessionContextKey from http request.
*
* @param request Http request
* @return SessionContextKey of particular session.
*/
private String getSessionContextKey(HttpServletRequest request) {
String commonAuthCookie;
String sessionContextKey = null;
if (FrameworkUtils.getAuthCookie(request) != null) {
commonAuthCookie = FrameworkUtils.getAuthCookie(request).getValue();
if (commonAuthCookie != null) {
sessionContextKey = DigestUtils.sha256Hex(commonAuthCookie);
}
}
return sessionContextKey;
}

private Response handleBadRequestResponse(SessionManagementClientException e) {

if (isForbiddenError(e)) {
throw AuthAPIEndpointUtil.buildForbiddenException(e.getMessage(), e.getErrorCode(), log, e);
}
if (isNotFoundError(e)) {
throw AuthAPIEndpointUtil.buildNotFoundRequestException(e.getMessage(), e.getErrorCode(), log, e);
}
throw AuthAPIEndpointUtil.buildBadRequestException(e.getMessage(), e.getErrorCode(), log, e);
}

private boolean isForbiddenError(SessionManagementClientException e) {

return ERROR_CODE_NO_AUTH_USER_FOUND.getCode().equals(e.getErrorCode()) ||
ERROR_CODE_USER_NOT_AUTHORIZED.getCode()
.equals(e.getErrorCode());
}

private boolean isNotFoundError(SessionManagementClientException e) {

return ERROR_CODE_SESSION_ID_INVALID.getCode().equals(e.getErrorCode());
}

private Response handleServerErrorResponse(SessionManagementException e) {

throw AuthAPIEndpointUtil.buildInternalServerErrorException(e.getErrorCode(), log, e);
}

private Response handleUnexpectedServerError(Throwable e) {

throw AuthAPIEndpointUtil.buildInternalServerErrorException(ERROR_CODE_UNEXPECTED.getCode(), log, e);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,29 @@

package org.wso2.carbon.identity.local.auth.api.endpoint.util;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.logging.Log;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.local.auth.api.core.AuthManager;
import org.wso2.carbon.identity.local.auth.api.core.exception.AuthAPIClientException;
import org.wso2.carbon.identity.local.auth.api.endpoint.constant.AuthEndpointConstants;
import org.wso2.carbon.identity.local.auth.api.endpoint.dto.AllSessionsDTO;
import org.wso2.carbon.identity.local.auth.api.endpoint.dto.ApplicationDTO;
import org.wso2.carbon.identity.local.auth.api.endpoint.dto.ErrorDTO;
import org.wso2.carbon.identity.local.auth.api.endpoint.dto.SessionDTO;
import org.wso2.carbon.identity.local.auth.api.endpoint.exception.BadRequestException;
import org.wso2.carbon.identity.local.auth.api.endpoint.exception.ClientErrorException;
import org.wso2.carbon.identity.local.auth.api.endpoint.exception.ForbiddenException;
import org.wso2.carbon.identity.local.auth.api.endpoint.exception.InternalServerErrorException;
import org.wso2.carbon.identity.local.auth.api.endpoint.exception.NotAcceptableException;
import org.wso2.carbon.identity.local.auth.api.endpoint.exception.NotFoundException;
import org.wso2.carbon.identity.user.session.constant.SessionConstants;
import org.wso2.carbon.identity.user.session.manager.SessionManager;
import org.wso2.carbon.identity.user.session.model.Application;
import org.wso2.carbon.identity.user.session.model.UserSession;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
Expand All @@ -46,6 +57,52 @@ public static AuthManager getAuthManager() {
null);
}

public static SessionManager getSessionManager() {

return (SessionManager) PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getOSGiService(SessionManager.class, null);
}


public static AllSessionsDTO getSessionResponse(UserSession[] userSessionList) {
AllSessionsDTO initiateAllSessionsDTO = new AllSessionsDTO();

List<SessionDTO> userSessionDTOS = new ArrayList<>();

for (UserSession userSession : userSessionList) {
SessionDTO sessionDTO = new SessionDTO();
sessionDTO.setApplications(getApplicationDTO(userSession.getApplications()));
sessionDTO.setUserAgent(userSession.getUserAgent());
sessionDTO.setIp(userSession.getIp());
sessionDTO.setLoginTime(userSession.getLoginTime());
sessionDTO.setLastAccessTime(userSession.getLastAccessTime());
sessionDTO.setSessionId(DigestUtils.sha256Hex(userSession.getSessionId()));
userSessionDTOS.add(sessionDTO);
}
initiateAllSessionsDTO.setSessions(userSessionDTOS);
return initiateAllSessionsDTO;
}

private static List<ApplicationDTO> getApplicationDTO(Application[] applicationList) {
List<ApplicationDTO> applicationDTOList = new ArrayList<>();

for (Application application : applicationList) {
ApplicationDTO applicationDTO = new ApplicationDTO();
applicationDTO.setApp(application.getAppName());
applicationDTO.setSubject(application.getSubject());
applicationDTOList.add(applicationDTO);
}
return applicationDTOList;
}

private static ErrorDTO getErrorDTO(String message, String description, String code) {

ErrorDTO errorDTO = new ErrorDTO();
errorDTO.setCode(code);
errorDTO.setMessage(message);
errorDTO.setDescription(description);
return errorDTO;
}
/**
* This method is used to create a client exceptions with the known errorCode and message based on error type.
*
Expand Down Expand Up @@ -82,8 +139,8 @@ public static ClientErrorException buildClientErrorException(String description,
* @param e Exception object
* @return BadRequestException with the given errorCode and description.
*/
public static BadRequestException buildBadRequestException(String description, String code, Map<String,String> properties,
Log log, Throwable e) {
public static BadRequestException buildBadRequestException(String description, String code,
Map<String, String> properties, Log log, Throwable e) {

ErrorDTO errorDTO = getErrorDTO(AuthEndpointConstants.STATUS_BAD_REQUEST_MESSAGE_DEFAULT, description, code,
properties);
Expand Down Expand Up @@ -143,7 +200,7 @@ public static InternalServerErrorException buildInternalServerErrorException(Str
return new InternalServerErrorException(errorDTO);
}

private static ErrorDTO getErrorDTO(String message, String description, String code, Map<String,String>
private static ErrorDTO getErrorDTO(String message, String description, String code, Map<String, String>
properties) {
ErrorDTO errorDTO = new ErrorDTO();
errorDTO.setCode(code);
Expand All @@ -164,4 +221,50 @@ private static void logDebug(String message, Log log, Throwable throwable) {
log.debug(message, throwable);
}
}

/**
* This method is used to create a BadRequestException with the known errorCode and message.
*
* @param description Error Message Desription.
* @param code Error Code.
* @return BadRequestException with the given errorCode and description.
*/
public static BadRequestException buildBadRequestException(String description, String code,
Log log, Throwable e) {

ErrorDTO errorDTO = getErrorDTO(SessionConstants.STATUS_BAD_REQUEST_MESSAGE_DEFAULT, description, code);
logDebug(AuthEndpointConstants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, log, e);
return new BadRequestException(errorDTO);
}

/**
* This method is used to create a NotFoundException with the known errorCode and message.
*
* @param description Error Message Description.
* @param code Error Code.
* @return NotFoundException with the given errorCode and description.
*/
public static NotFoundException buildNotFoundRequestException(String description, String code,
Log log, Throwable e) {

ErrorDTO errorDTO = getErrorDTO(SessionConstants.STATUS_BAD_REQUEST_MESSAGE_DEFAULT, description, code);
logDebug(AuthEndpointConstants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, log, e);
return new NotFoundException(errorDTO);
}

/**
* This method is used to create a Forbidden Exception with the known errorCode and message.
*
* @param description Error Message Description.
* @param code Error Code.
* @return ForbiddenException with the given errorCode and description.
*/
public static ForbiddenException buildForbiddenException(String description, String code,
Log log, Throwable e) {

ErrorDTO errorDTO = getErrorDTO(SessionConstants.STATUS_BAD_REQUEST_MESSAGE_DEFAULT, description, code);
logDebug(AuthEndpointConstants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, log, e);
return new ForbiddenException(errorDTO);
}

}
Loading