blob: d1bd2121f430ccc086c44798045c000ebf6481f7 [file] [log] [blame]
/*******************************************************************************
* 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.ofbiz.ws.rs.security.auth;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.service.ModelService;
import org.apache.ofbiz.webapp.control.JWTManager;
import org.apache.ofbiz.ws.rs.common.AuthenticationScheme;
import org.apache.ofbiz.ws.rs.security.Secured;
import org.apache.ofbiz.ws.rs.util.RestApiUtil;
/**
* Api Security
*/
@Secured
@Provider
public class APIAuthFilter implements ContainerRequestFilter {
private static final String MODULE = APIAuthFilter.class.getName();
@Context
private ResourceInfo resourceInfo;
@Context
private HttpServletRequest httpRequest;
@Context
private ServletContext servletContext;
private static final String REALM = "OFBiz";
/**
*/
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
Delegator delegator = (Delegator) servletContext.getAttribute("delegator");
if (!isTokenBasedAuthentication(authorizationHeader)) {
abortWithUnauthorized(requestContext, false, "Unauthorized: Access is denied due to invalid or absent Authorization header.");
return;
}
String jwtToken = JWTManager.getHeaderAuthBearerToken(httpRequest);
Map<String, Object> claims = JWTManager.validateToken(jwtToken, JWTManager.getJWTKey(delegator));
if (claims.containsKey(ModelService.ERROR_MESSAGE)) {
abortWithUnauthorized(requestContext, true, "Unauthorized: " + (String) claims.get(ModelService.ERROR_MESSAGE));
} else {
GenericValue userLogin = extractUserLoginFromJwtClaim(delegator, claims);
httpRequest.setAttribute("userLogin", userLogin);
}
}
/**
* @param authorizationHeader
* @return
*/
private boolean isTokenBasedAuthentication(String authorizationHeader) {
return authorizationHeader != null
&& authorizationHeader.toLowerCase().startsWith(AuthenticationScheme.BEARER.getScheme().toLowerCase() + " ");
}
/**
* @param requestContext
*/
private void abortWithUnauthorized(ContainerRequestContext requestContext, boolean isAuthHeaderPresent, String message) {
if (!isAuthHeaderPresent) {
requestContext.abortWith(
RestApiUtil.errorBuilder(Response.Status.UNAUTHORIZED.getStatusCode(), Response.Status.UNAUTHORIZED.getReasonPhrase(), message)
.header(HttpHeaders.WWW_AUTHENTICATE, AuthenticationScheme.BEARER.getScheme() + " realm=\"" + REALM + "\"").build());
} else {
requestContext
.abortWith(RestApiUtil.error(Response.Status.UNAUTHORIZED.getStatusCode(), Response.Status.UNAUTHORIZED.getReasonPhrase(), message));
}
}
private GenericValue extractUserLoginFromJwtClaim(Delegator delegator, Map<String, Object> claims) {
String userLoginId = (String) claims.get("userLoginId");
if (UtilValidate.isEmpty(userLoginId)) {
Debug.logWarning("No userLoginId found in the JWT token.", MODULE);
return null;
}
GenericValue userLogin = null;
try {
userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginId).queryOne();
if (UtilValidate.isEmpty(userLogin)) {
Debug.logWarning("There was a problem with the JWT token. Could not find provided userLogin " + userLoginId, MODULE);
}
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to get UserLogin information from JWT Token: " + e.getMessage(), MODULE);
}
return userLogin;
}
}