updated libraries

updated to JUNIT5
This commit is contained in:
Joern Muehlencord
2019-07-12 15:07:13 +02:00
parent 3ae4dba8fe
commit 24dc927ab7
57 changed files with 1196 additions and 1083 deletions

View File

@@ -163,8 +163,9 @@ public class ApiKeyService implements Serializable {
@Transactional
@Lock(LockType.WRITE)
public ApiKeyObject createNewApiKey(String userName, short expirationInMinutes) throws ApiKeyException {
if ((password == null || issuer == null) || (userName == null)) {
LOGGER.error("password, issuer or username not set in, please validate configuration");
if (password == null || issuer == null || userName == null) {
String hint = "password, issuer or username not set in, please validate configuration";
throw new ApiKeyException(hint);
}
Date now = DateUtil.getCurrentTimeInUTC();
ZonedDateTime issuedOn = ZonedDateTime.ofInstant(now.toInstant(), ZoneId.of("UTC"));

View File

@@ -15,7 +15,6 @@
*/
package de.muehlencord.shared.account.business.config.boundary;
import de.muehlencord.shared.db.ControllerException;
import de.muehlencord.shared.account.business.account.entity.Account;
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
@@ -23,6 +22,7 @@ import de.muehlencord.shared.account.business.config.entity.ConfigEntity;
import de.muehlencord.shared.account.business.config.entity.ConfigEntityPK;
import de.muehlencord.shared.account.business.config.entity.ConfigException;
import de.muehlencord.shared.account.util.AccountPU;
import de.muehlencord.shared.db.ControllerException;
import java.io.Serializable;
import java.util.List;
import java.util.Optional;
@@ -37,6 +37,7 @@ import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.Transactional;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -121,7 +122,7 @@ public class ConfigService implements Serializable {
// if config value is not found null has been returned
// in this case the value to return is the defaultValue
if (configValue == null) {
if (StringUtils.isEmpty(configValue)) {
configValue = defaultValue;
}

View File

@@ -15,10 +15,10 @@
*/
package de.muehlencord.shared.account.business.instance.boundary;
import de.muehlencord.shared.db.ControllerException;
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
import de.muehlencord.shared.account.business.config.entity.ConfigException;
import de.muehlencord.shared.db.ControllerException;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Initialized;

View File

@@ -1,202 +1,201 @@
/*
* Copyright 2018 joern.muehlencord.
*
* Licensed 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 de.muehlencord.shared.account.presentation;
import de.muehlencord.shared.account.business.account.control.AccountControl;
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
import de.muehlencord.shared.jeeutil.FacesUtil;
import java.io.IOException;
import java.io.Serializable;
import javax.ejb.EJB;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author joern.muehlencord
*/
@Named(value = "loginView")
@ViewScoped
public class LoginView implements Serializable {
private static final long serialVersionUID = -1164860380769648432L;
@EJB
private AccountControl accountService;
private String username = null;
private String password = null;
private boolean rememberMe = false;
private String resetPasswordToken = null;
private static final Logger LOGGER = LoggerFactory.getLogger(LoginView.class.getName());
public void authenticate() {
// Example using most common scenario of username/password pair:
UsernamePasswordToken token = new UsernamePasswordToken(getUsername(), getPassword());
// "Remember Me" built-in:
token.setRememberMe(rememberMe);
Subject currentUser = SecurityUtils.getSubject();
LOGGER.info("Trying to login user {}", username);
try {
currentUser.login(token);
LOGGER.info("User {} logged in", username);
// user logged in, update account entity
AccountEntity account = accountService.getAccountEntity(username, true);
accountService.updateLogin(account);
// redirect to home
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ServletResponse servletResponse = (ServletResponse) ec.getResponse();
String fallbackUrl = "/web/index.xhtml"; // TODO make configurable
// ec.redirect(url);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("redirecting to {}, fallbackUrl={}", servletResponse.toString(), fallbackUrl);
}
WebUtils.redirectToSavedRequest((ServletRequest) ec.getRequest(), servletResponse, fallbackUrl);
} catch (IOException | AuthenticationException ex) {
// Could catch a subclass of AuthenticationException if you like
String hint = "Error while authenticating user " + username;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(hint, ex);
}
if (ex.getMessage() != null) {
hint += "Reason: " + ex.getMessage();
} else {
hint += "Reason: " + ex.toString();
}
if ((ex.getCause() != null) && (ex.getCause().getMessage() != null)) {
hint += "Rootcause: " + ex.getMessage();
LOGGER.error(hint);
}
FacesUtil.addGlobalErrorMessage("Login failed", hint);
AccountEntity account = accountService.getAccountEntity(username, false);
if (account != null) {
accountService.addLoginError(account);
}
} finally {
token.clear();
}
}
public void logout() {
Subject currentUser = SecurityUtils.getSubject();
try {
currentUser.logout();
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
// ensure faces session is invalidated so beans are destroyed
ec.invalidateSession();
// check if redirect shall be executed
// default setting is yes to /login.xhtml
// can be overwritten using parameters
// de.muehlencord.shared.account.loginview.executeredirect boolean true/false
// de.muehlencord.shared.account.loginview.redirecttarget path to redirect to (without external context, will be added automatically)
String executeRedirectString = ec.getInitParameter("de.muehlencord.shared.account.loginview.executeredirect");
boolean executeRedirect = true;
if (executeRedirectString != null) {
executeRedirect = Boolean.parseBoolean(executeRedirectString);
}
String redirectTarget = ec.getInitParameter("de.muehlencord.shared.account.loginview.redirecttarget");
if ((redirectTarget == null) || (redirectTarget.equals(""))) {
redirectTarget = "/login.xhtml";
}
if (executeRedirect) {
String url = ec.getRequestContextPath() + redirectTarget;
ec.redirect(url);
}
} catch (Exception e) {
LOGGER.warn(e.toString());
}
}
public String executePasswordReset() {
boolean passwordResetted = accountService.resetPassword(username, password, resetPasswordToken);
if (passwordResetted) {
// TODO add email notification on updated user account
FacesUtil.addGlobalInfoMessage("Password resetted", null);
return login();
} else {
// TODO add email notificaton on failed password reset
FacesUtil.addGlobalErrorMessage("Password reset failed", null);
return login();
}
}
/* **** naviation rules **** */
public String login() {
return "/login.xhtml"; // TODO make configurable
}
/* *** getter / setter */
public String getUsername() {
return username;
}
public void setUsername(String un) {
this.username = un;
}
public String getPassword() {
return password;
}
public void setPassword(String pw) {
this.password = pw;
}
public boolean isRememberMe() {
return rememberMe;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
public String getResetPasswordToken() {
return resetPasswordToken;
}
public void setResetPasswordToken(String resetPasswordToken) {
this.resetPasswordToken = resetPasswordToken;
}
}
/*
* Copyright 2018 joern.muehlencord.
*
* Licensed 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 de.muehlencord.shared.account.presentation;
import de.muehlencord.shared.account.business.account.control.AccountControl;
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
import de.muehlencord.shared.jeeutil.FacesUtil;
import java.io.IOException;
import java.io.Serializable;
import javax.ejb.EJB;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author joern.muehlencord
*/
@Named(value = "loginView")
@ViewScoped
public class LoginView implements Serializable {
private static final long serialVersionUID = -1164860380769648432L;
@EJB
private AccountControl accountService;
private String username = null;
private String password = null;
private boolean rememberMe = false;
private String resetPasswordToken = null;
private static final Logger LOGGER = LoggerFactory.getLogger(LoginView.class.getName());
public void authenticate() {
// Example using most common scenario of username/password pair:
UsernamePasswordToken token = new UsernamePasswordToken(getUsername(), getPassword());
// "Remember Me" built-in:
token.setRememberMe(rememberMe);
Subject currentUser = SecurityUtils.getSubject();
LOGGER.info("Trying to login user {}", username);
try {
currentUser.login(token);
LOGGER.info("User {} logged in", username);
// user logged in, update account entity
AccountEntity account = accountService.getAccountEntity(username, true);
accountService.updateLogin(account);
// redirect to home
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ServletResponse servletResponse = (ServletResponse) ec.getResponse();
String fallbackUrl = "/web/index.xhtml"; // TODO make configurable
// ec.redirect(url);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("redirecting to {}, fallbackUrl={}", servletResponse.toString(), fallbackUrl);
}
WebUtils.redirectToSavedRequest((ServletRequest) ec.getRequest(), servletResponse, fallbackUrl);
} catch (IOException | AuthenticationException ex) {
// Could catch a subclass of AuthenticationException if you like
String hint = "Error while authenticating user " + username;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(hint, ex);
}
if (ex.getMessage() != null) {
hint += "Reason: " + ex.getMessage();
} else {
hint += "Reason: " + ex.toString();
}
if ((ex.getCause() != null) && (ex.getCause().getMessage() != null)) {
hint += "Rootcause: " + ex.getMessage();
LOGGER.error(hint);
}
FacesUtil.addGlobalErrorMessage("Login failed", hint);
AccountEntity account = accountService.getAccountEntity(username, false);
if (account != null) {
accountService.addLoginError(account);
}
} finally {
token.clear();
}
}
public void logout() {
Subject currentUser = SecurityUtils.getSubject();
try {
currentUser.logout();
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
// ensure faces session is invalidated so beans are destroyed
ec.invalidateSession();
// check if redirect shall be executed
// default setting is yes to /login.xhtml
// can be overwritten using parameters
// de.muehlencord.shared.account.loginview.executeredirect boolean true/false
// de.muehlencord.shared.account.loginview.redirecttarget path to redirect to (without external context, will be added automatically)
String executeRedirectString = ec.getInitParameter("de.muehlencord.shared.account.loginview.executeredirect");
boolean executeRedirect = true;
if (executeRedirectString != null) {
executeRedirect = Boolean.parseBoolean(executeRedirectString);
}
String redirectTarget = ec.getInitParameter("de.muehlencord.shared.account.loginview.redirecttarget");
if ((redirectTarget == null) || (redirectTarget.equals(""))) {
redirectTarget = "/login.xhtml";
}
if (executeRedirect) {
String url = ec.getRequestContextPath() + redirectTarget;
ec.redirect(url);
}
} catch (Exception e) {
LOGGER.warn(e.toString());
}
}
public String executePasswordReset() {
boolean passwordResetted = accountService.resetPassword(username, password, resetPasswordToken);
if (passwordResetted) {
// TODO add email notification on updated user account
FacesUtil.addGlobalInfoMessage("Password resetted", null);
return login();
} else {
// TODO add email notificaton on failed password reset
FacesUtil.addGlobalErrorMessage("Password reset failed", null);
return login();
}
}
/* **** naviation rules **** */
public String login() {
return "/login.xhtml"; // TODO make configurable
}
/* *** getter / setter */
public String getUsername() {
return username;
}
public void setUsername(String un) {
this.username = un;
}
public String getPassword() {
return password;
}
public void setPassword(String pw) {
this.password = pw;
}
public boolean isRememberMe() {
return rememberMe;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
public String getResetPasswordToken() {
return resetPasswordToken;
}
public void setResetPasswordToken(String resetPasswordToken) {
this.resetPasswordToken = resetPasswordToken;
}
}

View File

@@ -1,172 +1,169 @@
/*
* Copyright 2018 joern.muehlencord.
*
* Licensed 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 de.muehlencord.shared.account.shiro.filter;
import java.io.IOException;
import java.io.StringReader;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.LoggerFactory;
import de.muehlencord.shared.account.business.account.boundary.ApiKeyService;
import de.muehlencord.shared.account.business.account.entity.JWTObject;
import de.muehlencord.shared.account.shiro.token.JWTAuthenticationToken;
import de.muehlencord.shared.account.util.AccountSecurityException;
import de.muehlencord.shared.jeeutil.restexfw.APIException;
/**
*
* @author Joern Muehlencord <joern at muehlencord.de>
*/
public final class JWTAuthenticationFilter extends AuthenticatingFilter {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
protected static final String AUTHORIZATION_HEADER = "Authorization"; // NOI18N
protected static final String USERNAME = "username"; // NOI18N
protected static final String PASSWORD = "password"; // NOI18N
private final ApiKeyService apiKeyService = lookupApiKeyServiceBean();
public JWTAuthenticationFilter() {
// FIXME - logging in via JWTAuthenticationFilter does not yet work. Need to set login to anonymous to execute login in rest service
setLoginUrl("/rest/account/login");
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
boolean loggedIn = false;
if (isLoginRequest(request, response) || isLoggedAttempt(request, response)) {
loggedIn = executeLogin(request, response);
}
if (!loggedIn) {
HttpServletResponse httpResponse = WebUtils.toHttp(response);
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
return loggedIn;
}
@Override
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
if (isLoginRequest(request, response)) {
String json = IOUtils.toString(request.getInputStream(), "UTF-8"); // FIXME - check charset in request
if (json != null && !json.isEmpty()) {
try (JsonReader jr = Json.createReader(new StringReader(json))) {
JsonObject object = jr.readObject();
String username = object.getString(USERNAME);
String password = object.getString(PASSWORD);
return new UsernamePasswordToken(username, password);
}
}
}
if (isLoggedAttempt(request, response)) {
String jwtToken = getAuthzHeader(request);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("found jwtToke in header = {}", jwtToken);
}
if (jwtToken != null) {
JWTObject jwtObject = apiKeyService.getJWTObject(jwtToken);
return new JWTAuthenticationToken(jwtObject.getUserName(), jwtToken);
}
}
return new UsernamePasswordToken();
}
private boolean isLoggedAttempt(ServletRequest request, ServletResponse response) {
String authzHeader = getAuthzHeader(request);
return authzHeader != null;
}
private String getAuthzHeader(ServletRequest request) {
HttpServletRequest httpRequest = WebUtils.toHttp(request);
return httpRequest.getHeader(AUTHORIZATION_HEADER);
}
/**
* Overwrite cleanup to ensure no exception is thrown if an
* AccountSecurityException / APIException is raised during login. As long
* as the user is not logged in JERSEYs ExceptionMapper and intercepor
* classes are overruled by Shiro.
*
* @param request the incoming request
* @param response the response to return
* @param existing the raised exception
* @throws ServletException may be thrown by AuthenticatingFilter.cleanup if
* existing is not a AccountSecurityException
* @throws IOException may be thrown by AuthenticatingFilter.cleanup if
* existing is not a AccountSecurityException
*/
@Override
protected void cleanup(ServletRequest request, ServletResponse response, Exception existing) throws ServletException, IOException {
if ((existing != null) && (existing.getClass().isAssignableFrom(AccountSecurityException.class))) {
HttpServletResponse httpResponse = WebUtils.toHttp(response);
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
} else if ((existing != null) && (existing.getClass().isAssignableFrom(APIException.class))) {
APIException apiException = (APIException) existing;
HttpServletResponse httpResponse = WebUtils.toHttp(response);
httpResponse.setStatus(apiException.getHttpResponse().getStatus());
httpResponse.addHeader(APIException.HTTP_HEADER_X_ERROR, apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ERROR));
httpResponse.addHeader(APIException.HTTP_HEADER_X_ERROR_CODE, apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ERROR_CODE));
if (apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ROOT_CAUSE) != null) {
httpResponse.addHeader(APIException.HTTP_HEADER_X_ROOT_CAUSE, apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ROOT_CAUSE));
}
} else {
super.cleanup(request, response, existing);
}
}
// TODO - can this be injected?
private ApiKeyService lookupApiKeyServiceBean() {
try {
Context c = new InitialContext();
return (ApiKeyService) c.lookup("java:module/ApiKeyService"); // NOI18N
} catch (NamingException ex) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(ex.toString(), ex);
} else {
LOGGER.error(ex.toString());
}
throw new RuntimeException(ex);
}
}
}
/*
* Copyright 2018 joern.muehlencord.
*
* Licensed 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 de.muehlencord.shared.account.shiro.filter;
import de.muehlencord.shared.account.business.account.boundary.ApiKeyService;
import de.muehlencord.shared.account.business.account.entity.JWTObject;
import de.muehlencord.shared.account.shiro.token.JWTAuthenticationToken;
import de.muehlencord.shared.account.util.AccountSecurityException;
import de.muehlencord.shared.jeeutil.restexfw.APIException;
import java.io.IOException;
import java.io.StringReader;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.LoggerFactory;
/**
*
* @author Joern Muehlencord <joern at muehlencord.de>
*/
public final class JWTAuthenticationFilter extends AuthenticatingFilter {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
protected static final String AUTHORIZATION_HEADER = "Authorization"; // NOI18N
protected static final String USERNAME = "username"; // NOI18N
protected static final String PASSWORD = "password"; // NOI18N
private final ApiKeyService apiKeyService = lookupApiKeyServiceBean();
public JWTAuthenticationFilter() {
// FIXME - logging in via JWTAuthenticationFilter does not yet work. Need to set login to anonymous to execute login in rest service
setLoginUrl("/rest/account/login");
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
boolean loggedIn = false;
if (isLoginRequest(request, response) || isLoggedAttempt(request, response)) {
loggedIn = executeLogin(request, response);
}
if (!loggedIn) {
HttpServletResponse httpResponse = WebUtils.toHttp(response);
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
return loggedIn;
}
@Override
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
if (isLoginRequest(request, response)) {
String json = IOUtils.toString(request.getInputStream(), "UTF-8"); // FIXME - check charset in request
if (json != null && !json.isEmpty()) {
try (JsonReader jr = Json.createReader(new StringReader(json))) {
JsonObject object = jr.readObject();
String username = object.getString(USERNAME);
String password = object.getString(PASSWORD);
return new UsernamePasswordToken(username, password);
}
}
}
if (isLoggedAttempt(request, response)) {
String jwtToken = getAuthzHeader(request);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("found jwtToke in header = {}", jwtToken);
}
if (jwtToken != null) {
JWTObject jwtObject = apiKeyService.getJWTObject(jwtToken);
return new JWTAuthenticationToken(jwtObject.getUserName(), jwtToken);
}
}
return new UsernamePasswordToken();
}
private boolean isLoggedAttempt(ServletRequest request, ServletResponse response) {
String authzHeader = getAuthzHeader(request);
return authzHeader != null;
}
private String getAuthzHeader(ServletRequest request) {
HttpServletRequest httpRequest = WebUtils.toHttp(request);
return httpRequest.getHeader(AUTHORIZATION_HEADER);
}
/**
* Overwrite cleanup to ensure no exception is thrown if an
* AccountSecurityException / APIException is raised during login. As long
* as the user is not logged in JERSEYs ExceptionMapper and intercepor
* classes are overruled by Shiro.
*
* @param request the incoming request
* @param response the response to return
* @param existing the raised exception
* @throws ServletException may be thrown by AuthenticatingFilter.cleanup if
* existing is not a AccountSecurityException
* @throws IOException may be thrown by AuthenticatingFilter.cleanup if
* existing is not a AccountSecurityException
*/
@Override
protected void cleanup(ServletRequest request, ServletResponse response, Exception existing) throws ServletException, IOException {
if ((existing != null) && (existing.getClass().isAssignableFrom(AccountSecurityException.class))) {
HttpServletResponse httpResponse = WebUtils.toHttp(response);
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
} else if ((existing != null) && (existing.getClass().isAssignableFrom(APIException.class))) {
APIException apiException = (APIException) existing;
HttpServletResponse httpResponse = WebUtils.toHttp(response);
httpResponse.setStatus(apiException.getHttpResponse().getStatus());
httpResponse.addHeader(APIException.HTTP_HEADER_X_ERROR, apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ERROR));
httpResponse.addHeader(APIException.HTTP_HEADER_X_ERROR_CODE, apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ERROR_CODE));
if (apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ROOT_CAUSE) != null) {
httpResponse.addHeader(APIException.HTTP_HEADER_X_ROOT_CAUSE, apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ROOT_CAUSE));
}
} else {
super.cleanup(request, response, existing);
}
}
// TODO - can this be injected?
private ApiKeyService lookupApiKeyServiceBean() {
try {
Context c = new InitialContext();
return (ApiKeyService) c.lookup("java:module/ApiKeyService"); // NOI18N
} catch (NamingException ex) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(ex.toString(), ex);
} else {
LOGGER.error(ex.toString());
}
throw new RuntimeException(ex);
}
}
}