/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.security.auth.http;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.security.auth.AuthException;
import com.liferay.portal.kernel.security.auth.http.HttpAuthManager;
import com.liferay.portal.kernel.security.auth.http.HttpAuthManagerUtil;
import com.liferay.portal.kernel.security.auth.http.HttpAuthorizationHeader;
import com.liferay.portal.kernel.security.auth.session.AuthenticatedSessionManagerUtil;
import com.liferay.portal.kernel.service.UserLocalServiceUtil;
import com.liferay.portal.kernel.servlet.HttpHeaders;
import com.liferay.portal.kernel.util.Base64;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.HttpUtil;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.UnicodeProperties;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.servlet.filters.secure.NonceUtil;
import com.liferay.portal.util.PortalInstances;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author Tomas Polesovsky
*/
public class HttpAuthManagerImpl implements HttpAuthManager {
@Override
public void generateChallenge(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
HttpAuthorizationHeader httpAuthorizationHeader) {
if (httpServletRequest == null) {
throw new IllegalArgumentException("HTTP servlet request is null");
}
if (httpServletResponse == null) {
throw new IllegalArgumentException("HTTP servlet response is null");
}
if ((httpAuthorizationHeader == null) ||
Validator.isBlank(httpAuthorizationHeader.getScheme())) {
throw new IllegalArgumentException(
"HTTP authorization header scheme is null");
}
String realm = httpAuthorizationHeader.getAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_REALM);
if (Validator.isBlank(realm)) {
httpAuthorizationHeader.setAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_REALM,
Portal.PORTAL_REALM);
}
String scheme = httpAuthorizationHeader.getScheme();
if (StringUtil.equalsIgnoreCase(
scheme, HttpAuthorizationHeader.SCHEME_BASIC)) {
generateBasicChallenge(
httpServletRequest, httpServletResponse,
httpAuthorizationHeader);
}
else if (StringUtil.equalsIgnoreCase(
scheme, HttpAuthorizationHeader.SCHEME_DIGEST)) {
generateDigestChallenge(
httpServletRequest, httpServletResponse,
httpAuthorizationHeader);
}
else {
throw new UnsupportedOperationException("Scheme " + scheme);
}
}
@Override
public long getBasicUserId(HttpServletRequest httpServletRequest)
throws PortalException {
HttpAuthorizationHeader httpAuthorizationHeader =
HttpAuthManagerUtil.parse(httpServletRequest);
if (httpAuthorizationHeader == null) {
return 0;
}
String scheme = httpAuthorizationHeader.getScheme();
if (!StringUtil.equalsIgnoreCase(
scheme, HttpAuthorizationHeader.SCHEME_BASIC)) {
return 0;
}
return getUserId(httpServletRequest, httpAuthorizationHeader);
}
@Override
public long getDigestUserId(HttpServletRequest httpServletRequest)
throws PortalException {
HttpAuthorizationHeader httpAuthorizationHeader =
HttpAuthManagerUtil.parse(httpServletRequest);
if (httpAuthorizationHeader == null) {
return 0;
}
String scheme = httpAuthorizationHeader.getScheme();
if (!StringUtil.equalsIgnoreCase(
scheme, HttpAuthorizationHeader.SCHEME_DIGEST)) {
return 0;
}
return getUserId(httpServletRequest, httpAuthorizationHeader);
}
@Override
public long getUserId(
HttpServletRequest httpServletRequest,
HttpAuthorizationHeader httpAuthorizationHeader)
throws PortalException {
if (httpServletRequest == null) {
throw new IllegalArgumentException("HTTP servlet request is null");
}
if ((httpAuthorizationHeader == null) ||
Validator.isBlank(httpAuthorizationHeader.getScheme())) {
throw new IllegalArgumentException(
"HTTP authorization header scheme is null");
}
String scheme = httpAuthorizationHeader.getScheme();
if (StringUtil.equalsIgnoreCase(
scheme, HttpAuthorizationHeader.SCHEME_BASIC)) {
return getBasicUserId(httpServletRequest, httpAuthorizationHeader);
}
else if (StringUtil.equalsIgnoreCase(
scheme, HttpAuthorizationHeader.SCHEME_DIGEST)) {
return getDigestUserId(httpServletRequest, httpAuthorizationHeader);
}
else {
throw new UnsupportedOperationException("Scheme " + scheme);
}
}
@Override
public HttpAuthorizationHeader parse(
HttpServletRequest httpServletRequest) {
if (httpServletRequest == null) {
throw new IllegalArgumentException("HTTP servlet request is null");
}
String authorization = httpServletRequest.getHeader(
HttpHeaders.AUTHORIZATION);
if (Validator.isBlank(authorization)) {
return null;
}
String[] authorizationParts = authorization.split("\\s");
String scheme = authorizationParts[0];
if (StringUtil.equalsIgnoreCase(
scheme, HttpAuthorizationHeader.SCHEME_BASIC)) {
return parseBasic(
httpServletRequest, authorization, authorizationParts);
}
else if (StringUtil.equalsIgnoreCase(
scheme, HttpAuthorizationHeader.SCHEME_DIGEST)) {
return parseDigest(
httpServletRequest, authorization, authorizationParts);
}
else {
throw new UnsupportedOperationException("Scheme " + scheme);
}
}
protected void generateBasicChallenge(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
HttpAuthorizationHeader httpAuthorizationHeader) {
httpServletResponse.setHeader(
HttpHeaders.WWW_AUTHENTICATE, httpAuthorizationHeader.toString());
httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
protected void generateDigestChallenge(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
HttpAuthorizationHeader httpAuthorizationHeader) {
// Must generate a new nonce for each 401 (RFC2617, 3.2.1)
long companyId = PortalInstances.getCompanyId(httpServletRequest);
String remoteAddress = httpServletRequest.getRemoteAddr();
String nonce = NonceUtil.generate(companyId, remoteAddress);
httpAuthorizationHeader.setAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_NONCE, nonce);
httpServletResponse.setHeader(
HttpHeaders.WWW_AUTHENTICATE, httpAuthorizationHeader.toString());
httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
protected long getBasicUserId(
HttpServletRequest httpServletRequest,
HttpAuthorizationHeader httpAuthorizationHeader)
throws PortalException {
String login = httpAuthorizationHeader.getAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_USERNAME);
String password = httpAuthorizationHeader.getAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_PASSWORD);
// Strip @uid and @sn for backwards compatibility
if (login.endsWith("@uid")) {
int pos = login.indexOf("@uid");
login = login.substring(0, pos);
}
else if (login.endsWith("@sn")) {
int pos = login.indexOf("@sn");
login = login.substring(0, pos);
}
try {
return AuthenticatedSessionManagerUtil.getAuthenticatedUserId(
httpServletRequest, login, password, null);
}
catch (AuthException ae) {
// LPS-52675
if (_log.isDebugEnabled()) {
_log.debug(ae, ae);
}
}
return 0;
}
protected long getDigestUserId(
HttpServletRequest httpServletRequest,
HttpAuthorizationHeader httpAuthorizationHeader)
throws PortalException {
long userId = 0;
String username = httpAuthorizationHeader.getAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_USERNAME);
String realm = httpAuthorizationHeader.getAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_REALM);
String nonce = httpAuthorizationHeader.getAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_NONCE);
String uri = httpAuthorizationHeader.getAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_URI);
String response = httpAuthorizationHeader.getAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_RESPONSE);
if (Validator.isNull(username) || Validator.isNull(realm) ||
Validator.isNull(nonce) || Validator.isNull(uri) ||
Validator.isNull(response)) {
return userId;
}
if (!realm.equals(Portal.PORTAL_REALM) ||
!uri.equals(httpServletRequest.getRequestURI())) {
return userId;
}
if (!NonceUtil.verify(nonce)) {
return userId;
}
long companyId = PortalInstances.getCompanyId(httpServletRequest);
userId = UserLocalServiceUtil.authenticateForDigest(
companyId, username, realm, nonce, httpServletRequest.getMethod(),
uri, response);
return userId;
}
protected HttpAuthorizationHeader parseBasic(
HttpServletRequest httpServletRequest, String authorization,
String[] authorizationParts) {
String credentials = new String(Base64.decode(authorizationParts[1]));
String[] loginAndPassword = StringUtil.split(
credentials, CharPool.COLON);
String login = HttpUtil.decodeURL(loginAndPassword[0].trim());
String password = null;
if (loginAndPassword.length > 1) {
password = loginAndPassword[1].trim();
}
HttpAuthorizationHeader httpAuthorizationHeader =
new HttpAuthorizationHeader(HttpAuthorizationHeader.SCHEME_BASIC);
httpAuthorizationHeader.setAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_USERNAME, login);
httpAuthorizationHeader.setAuthParameter(
HttpAuthorizationHeader.AUTH_PARAMETER_NAME_PASSWORD, password);
return httpAuthorizationHeader;
}
protected HttpAuthorizationHeader parseDigest(
HttpServletRequest httpServletRequest, String authorization,
String[] authorizationHeaderParts) {
HttpAuthorizationHeader httpAuthorizationHeader =
new HttpAuthorizationHeader(HttpAuthorizationHeader.SCHEME_DIGEST);
authorization = authorization.substring(
HttpAuthorizationHeader.SCHEME_DIGEST.length() + 1);
authorization = StringUtil.replace(
authorization, CharPool.COMMA, CharPool.NEW_LINE);
UnicodeProperties authorizationProperties = new UnicodeProperties();
authorizationProperties.fastLoad(authorization);
for (Map.Entry<String, String> authorizationProperty :
authorizationProperties.entrySet()) {
String key = authorizationProperty.getKey();
String value = StringUtil.unquote(
authorizationProperties.getProperty(key));
httpAuthorizationHeader.setAuthParameter(key, value);
}
return httpAuthorizationHeader;
}
private static final Log _log = LogFactoryUtil.getLog(
HttpAuthManagerImpl.class);
}