use of org.alfresco.repo.security.authentication.AuthenticationException in project alfresco-remote-api by Alfresco.
the class LocalWebScriptConnectorServiceImpl method executeRequest.
/**
* Executes the specified request, and return the response
*/
public RemoteConnectorResponse executeRequest(RemoteConnectorRequest request) throws IOException, AuthenticationException, RemoteConnectorClientException, RemoteConnectorServerException {
// Convert the request object
RemoteConnectorRequestImpl requestImpl = (RemoteConnectorRequestImpl) request;
Request req = new Request(request.getMethod(), request.getURL());
req.setType(request.getContentType());
if (request.getRequestBody() != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
requestImpl.getRequestBody().writeRequest(baos);
req.setBody(baos.toByteArray());
}
// Log
if (logger.isInfoEnabled())
logger.info("Performing local " + request.getMethod() + " request to " + request.getURL());
// Capture the user details, as they may be changed during the request processing
Authentication fullAuth = AuthenticationUtil.getFullAuthentication();
String runAsUser = AuthenticationUtil.getRunAsUser();
// If they've specified Authentication details in the request, clear our security context
// and switch to that user, to avoid our context confusing the real request
Header authHeader = null;
Map<String, String> headers = new HashMap<String, String>();
for (Header header : request.getRequestHeaders()) {
if (header.getName().equals("Authorization")) {
authHeader = header;
}
headers.put(header.getName(), header.getValue());
}
if (authHeader != null) {
AuthenticationUtil.clearCurrentSecurityContext();
if (logger.isDebugEnabled())
logger.debug("HTTP Authorization found for the request, clearing security context, Auth is " + authHeader);
}
req.setHeaders(headers);
// Execute the request against the WebScript Test Framework
Response resp;
try {
resp = helper.sendRequest(req, -1);
} catch (Exception e) {
throw new AlfrescoRuntimeException("Problem requesting", e);
}
// Reset the user details, now we're done performing the request
AuthenticationUtil.setFullAuthentication(fullAuth);
if (runAsUser != null && !runAsUser.equals(fullAuth.getName())) {
AuthenticationUtil.setRunAsUser(runAsUser);
}
// Log
if (logger.isInfoEnabled())
logger.info("Response to request was " + resp.getStatus() + " - " + resp);
// Check the status for specific typed exceptions
if (resp.getStatus() == Status.STATUS_UNAUTHORIZED) {
throw new AuthenticationException("Not Authorized to access this resource");
}
if (resp.getStatus() == Status.STATUS_FORBIDDEN) {
throw new AuthenticationException("Forbidden to access this resource");
}
// Check for failures where we don't care about the response body
if (resp.getStatus() >= 500 && resp.getStatus() <= 599) {
throw new RemoteConnectorServerException(resp.getStatus(), "(not available)");
}
// Convert the response into our required format
String charset = null;
String contentType = resp.getContentType();
if (contentType != null && contentType.contains("charset=")) {
int splitAt = contentType.indexOf("charset=") + "charset=".length();
charset = contentType.substring(splitAt);
}
InputStream body = new ByteArrayInputStream(resp.getContentAsByteArray());
// TODO Can't easily get the list...
Header[] respHeaders = new Header[0];
RemoteConnectorResponse response = new RemoteConnectorResponseImpl(request, contentType, charset, resp.getStatus(), respHeaders, body);
// If it's a client error, let them know what went wrong
if (resp.getStatus() >= 400 && resp.getStatus() <= 499) {
throw new RemoteConnectorClientException(resp.getStatus(), "(not available)", response);
}
// Otherwise return the response for processing
return response;
}
use of org.alfresco.repo.security.authentication.AuthenticationException in project alfresco-remote-api by Alfresco.
the class RemoteAlfrescoTicketServiceTest method testGetTicket.
/**
* Getting cached and non-cached credentials
*/
public void testGetTicket() throws Exception {
// Run this test initially as the first user
AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE);
// First, try an invalid system
try {
remoteAlfrescoTicketService.getAlfrescoTicket(INVALID_REMOTE_SYSTEM_ID);
fail("Shouldn't work for an invalid system");
} catch (NoSuchSystemException e) {
}
try {
remoteAlfrescoTicketService.refetchAlfrescoTicket(INVALID_REMOTE_SYSTEM_ID);
fail("Shouldn't work for an invalid system");
} catch (NoSuchSystemException e) {
}
// Can't get or refresh if no credentials exist
try {
remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
fail("Shouldn't work when no credentials");
} catch (NoCredentialsFoundException e) {
}
try {
remoteAlfrescoTicketService.refetchAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
fail("Shouldn't work when no credentials");
} catch (NoCredentialsFoundException e) {
}
// Have some stored
remoteAlfrescoTicketService.storeRemoteCredentials(TEST_REMOTE_SYSTEM_ID, USER_ONE, PASSWORD);
// A ticket will now exist
RemoteAlfrescoTicketInfo ticket = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
assertNotNull(ticket);
assertNotNull(ticket.getAsUrlParameters());
// Ask again, will get the same one
RemoteAlfrescoTicketInfo ticket2 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
assertNotNull(ticket2);
assertEquals(ticket.getAsUrlParameters(), ticket2.getAsUrlParameters());
// Force a re-fetch, will get another
RemoteAlfrescoTicketInfo ticket3 = remoteAlfrescoTicketService.refetchAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
assertNotNull(ticket3);
assertNotSame(ticket.getAsUrlParameters(), ticket3.getAsUrlParameters());
// Ask for the ticket again, get the 2nd one again
RemoteAlfrescoTicketInfo ticket4 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
assertNotNull(ticket4);
assertEquals(ticket3.getAsUrlParameters(), ticket4.getAsUrlParameters());
// Zap from the cache, will trigger another to be fetched
ticketsCache.clear();
RemoteAlfrescoTicketInfo ticket5 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
assertNotNull(ticket5);
assertNotSame(ticket.getAsUrlParameters(), ticket5.getAsUrlParameters());
assertNotSame(ticket3.getAsUrlParameters(), ticket5.getAsUrlParameters());
// Change the password so it's no longer valid
PasswordCredentialsInfoImpl creds = (PasswordCredentialsInfoImpl) remoteCredentialsService.getPersonCredentials(TEST_REMOTE_SYSTEM_ID);
assertNotNull(creds);
creds.setRemotePassword("INVALID");
remoteCredentialsService.updateCredentials(creds);
// Currently will be marked as still working
assertEquals(true, creds.getLastAuthenticationSucceeded());
// Get will work, as ticket was previously cached
RemoteAlfrescoTicketInfo ticket6 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
assertNotNull(ticket6);
assertEquals(ticket5.getAsUrlParameters(), ticket6.getAsUrlParameters());
// Re-fetch will fail with authentication error
try {
remoteAlfrescoTicketService.refetchAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
fail("Shouldn't be able to refetch with wrong details");
} catch (AuthenticationException e) {
}
// Now a get will fail too, as the cache will be invalidated
try {
remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
fail("Shouldn't be able to get after refresh with wrong details");
} catch (AuthenticationException e) {
}
// If we check the credentials, will now be marked as failing
creds = (PasswordCredentialsInfoImpl) remoteCredentialsService.getPersonCredentials(TEST_REMOTE_SYSTEM_ID);
assertEquals(false, creds.getLastAuthenticationSucceeded());
// Change the password back to what it should be, and re-get
creds.setRemotePassword(PASSWORD);
remoteCredentialsService.updateCredentials(creds);
RemoteAlfrescoTicketInfo ticket7 = remoteAlfrescoTicketService.getAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
assertNotNull(ticket7);
assertNotSame(ticket.getAsUrlParameters(), ticket7.getAsUrlParameters());
assertNotSame(ticket3.getAsUrlParameters(), ticket7.getAsUrlParameters());
assertNotSame(ticket5.getAsUrlParameters(), ticket7.getAsUrlParameters());
// Should now be marked as working again
creds = (PasswordCredentialsInfoImpl) remoteCredentialsService.getPersonCredentials(TEST_REMOTE_SYSTEM_ID);
assertEquals(true, creds.getLastAuthenticationSucceeded());
// Check that failure can be marked in a read only transaction
creds.setRemotePassword("INVALID");
remoteCredentialsService.updateCredentials(creds);
retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() {
public Void execute() {
try {
remoteAlfrescoTicketService.refetchAlfrescoTicket(TEST_REMOTE_SYSTEM_ID);
fail("Shouldn't be able to refetch with wrong details");
} catch (AuthenticationException e) {
}
return null;
}
}, false, // after MNT-13871, POST api/login webscript now requires read-write transaction
true);
// Check it was still marked as invalid, despite a read only transaction
creds = (PasswordCredentialsInfoImpl) remoteCredentialsService.getPersonCredentials(TEST_REMOTE_SYSTEM_ID);
assertEquals(false, creds.getLastAuthenticationSucceeded());
}
use of org.alfresco.repo.security.authentication.AuthenticationException in project alfresco-remote-api by Alfresco.
the class AuthenticationFilter method doFilter.
// Various services required by NTLM authenticator
/**
* Run the authentication filter
*
* @param context ServletContext
* @param req ServletRequest
* @param resp ServletResponse
* @param chain FilterChain
* @exception ServletException
* @exception IOException
*/
@Override
public void doFilter(ServletContext context, ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
if (logger.isDebugEnabled())
logger.debug("Entering AuthenticationFilter.");
// Assume it's an HTTP request
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpServletResponse httpResp = (HttpServletResponse) resp;
// Get the user details object from the session
SessionUser user = getSessionUser(context, httpReq, httpResp, false);
if (user == null) {
if (logger.isDebugEnabled())
logger.debug("There is no user in the session.");
// Get the authorization header
String authHdr = httpReq.getHeader("Authorization");
if (authHdr != null && authHdr.length() > 5 && authHdr.substring(0, 5).equalsIgnoreCase("BASIC")) {
if (logger.isDebugEnabled())
logger.debug("Basic authentication details present in the header.");
byte[] encodedString = Base64.decodeBase64(authHdr.substring(5).getBytes());
// ALF-13621: Due to browser inconsistencies we have to try a fallback path of encodings
Set<String> attemptedAuths = new HashSet<String>(ENCODINGS.length * 2);
for (String encoding : ENCODINGS) {
CharsetDecoder decoder = Charset.forName(encoding).newDecoder().onMalformedInput(CodingErrorAction.REPORT);
try {
// Attempt to decode using this charset
String basicAuth = decoder.decode(ByteBuffer.wrap(encodedString)).toString();
// It decoded OK but we may already have tried this string.
if (!attemptedAuths.add(basicAuth)) {
// Already tried - no need to try again
continue;
}
String username = null;
String password = null;
// Split the username and password
int pos = basicAuth.indexOf(":");
if (pos != -1) {
username = basicAuth.substring(0, pos);
password = basicAuth.substring(pos + 1);
} else {
username = basicAuth;
password = "";
}
// Go to the repo and authenticate
Authorization auth = new Authorization(username, password);
if (auth.isTicket()) {
authenticationService.validate(auth.getTicket());
} else {
authenticationService.authenticate(username, password.toCharArray());
if (authenticationListener != null) {
authenticationListener.userAuthenticated(new BasicAuthCredentials(username, password));
}
}
user = createUserEnvironment(httpReq.getSession(), authenticationService.getCurrentUserName(), authenticationService.getCurrentTicket(), false);
// Success so break out
break;
} catch (CharacterCodingException e) {
if (logger.isDebugEnabled())
logger.debug("Didn't decode using " + decoder.getClass().getName(), e);
} catch (AuthenticationException ex) {
if (logger.isDebugEnabled())
logger.debug("Authentication error ", ex);
} catch (NoSuchPersonException e) {
if (logger.isDebugEnabled())
logger.debug("There is no such person error ", e);
}
}
} else {
// Check if the request includes an authentication ticket
String ticket = req.getParameter(ARG_TICKET);
if (ticket != null && ticket.length() > 0) {
// PowerPoint bug fix
if (ticket.endsWith(PPT_EXTN)) {
ticket = ticket.substring(0, ticket.length() - PPT_EXTN.length());
}
if (logger.isDebugEnabled())
logger.debug("Logon via ticket from " + req.getRemoteHost() + " (" + req.getRemoteAddr() + ":" + req.getRemotePort() + ")" + " ticket=" + ticket);
// Validate the ticket
authenticationService.validate(ticket);
if (authenticationListener != null) {
authenticationListener.userAuthenticated(new TicketCredentials(ticket));
}
// Need to create the User instance if not already available
String currentUsername = authenticationService.getCurrentUserName();
user = createUserEnvironment(httpReq.getSession(), currentUsername, ticket, false);
}
}
if (user == null) {
if (logger.isDebugEnabled())
logger.debug("No user/ticket, force the client to prompt for logon details.");
httpResp.setHeader("WWW-Authenticate", "BASIC realm=\"Alfresco DAV Server\"");
httpResp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
httpResp.flushBuffer();
return;
}
} else {
if (authenticationListener != null) {
authenticationListener.userAuthenticated(new TicketCredentials(user.getTicket()));
}
}
// Chain other filters
chain.doFilter(req, resp);
}
use of org.alfresco.repo.security.authentication.AuthenticationException in project alfresco-remote-api by Alfresco.
the class BaseAuthenticationFilter method getSessionUser.
/**
* Callback to get the specific impl of the Session User for a filter.
*
* @param servletContext
* the servlet context
* @param httpServletRequest
* the http servlet request
* @param httpServletResponse
* the http servlet response
* @param externalAuth
* has the user been authenticated by SSO?
* @return User from the session
*/
protected SessionUser getSessionUser(ServletContext servletContext, final HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, final boolean externalAuth) {
String userId = null;
// If the remote user mapper is configured, we may be able to map in an externally authenticated user
if (remoteUserMapper != null && (!(remoteUserMapper instanceof ActivateableBean) || ((ActivateableBean) remoteUserMapper).isActive())) {
userId = remoteUserMapper.getRemoteUser(httpServletRequest);
if (getLogger().isDebugEnabled())
getLogger().debug("Found a remote user: " + userId);
}
String sessionAttrib = getUserAttributeName();
HttpSession session = httpServletRequest.getSession();
SessionUser sessionUser = (SessionUser) session.getAttribute(sessionAttrib);
if (sessionUser != null) {
try {
if (getLogger().isDebugEnabled())
getLogger().debug("Found a session user: " + sessionUser.getUserName());
authenticationService.validate(sessionUser.getTicket());
setExternalAuth(session, externalAuth);
} catch (AuthenticationException e) {
if (getLogger().isDebugEnabled())
getLogger().debug("The ticket may have expired or the person could have been removed, invalidating session.", e);
invalidateSession(httpServletRequest);
sessionUser = null;
}
}
if (userId != null) {
if (getLogger().isDebugEnabled())
getLogger().debug("We have a previously-cached user with the wrong identity - replace them.");
if (sessionUser != null && !sessionUser.getUserName().equals(userId)) {
if (getLogger().isDebugEnabled())
getLogger().debug("Removing the session user, invalidating session.");
session.removeAttribute(sessionAttrib);
session.invalidate();
sessionUser = null;
}
if (sessionUser == null) {
// If we have been authenticated by other means, just propagate through the user identity
if (getLogger().isDebugEnabled())
getLogger().debug("Propagating through the user identity: " + userId);
authenticationComponent.setCurrentUser(userId);
session = httpServletRequest.getSession();
try {
sessionUser = createUserEnvironment(session, authenticationService.getCurrentUserName(), authenticationService.getCurrentTicket(), true);
} catch (Throwable e) {
if (getLogger().isDebugEnabled())
getLogger().debug("Error during ticket validation and user creation: " + e.getMessage(), e);
}
}
}
return sessionUser;
}
use of org.alfresco.repo.security.authentication.AuthenticationException in project alfresco-remote-api by Alfresco.
the class BaseKerberosAuthenticationFilter method authenticateRequest.
public boolean authenticateRequest(ServletContext context, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
// Check if there is an authorization header with an SPNEGO security blob
String authHdr = req.getHeader("Authorization");
boolean reqAuth = false;
if (authHdr != null) {
if (authHdr.startsWith("Negotiate"))
reqAuth = true;
else if (authHdr.startsWith("NTLM")) {
if (getLogger().isDebugEnabled())
getLogger().debug("Received NTLM logon from client");
// Restart the authentication
restartLoginChallenge(context, req, resp);
return false;
} else if (isFallbackEnabled()) {
return performFallbackAuthentication(context, req, resp);
}
}
// Check if the user is already authenticated
SessionUser user = getSessionUser(context, req, resp, true);
HttpSession httpSess = req.getSession(true);
if (user == null) {
user = (SessionUser) httpSess.getAttribute("_alfAuthTicket");
// MNT-13191 Opening /alfresco/webdav from a Kerberos-authenticated IE11 browser causes HTTP error 500
if (user != null) {
String userName = user.getUserName();
AuthenticationUtil.setFullyAuthenticatedUser(userName);
}
}
// the next filter
if (user != null && reqAuth == false) {
// Filter validate hook
onValidate(context, req, resp, new TicketCredentials(user.getTicket()));
if (getLogger().isDebugEnabled())
getLogger().debug("Authentication not required (user), chaining ...");
return true;
}
// Check if the login page is being accessed, do not intercept the login page
if (checkLoginPage(req, resp)) {
if (getLogger().isDebugEnabled())
getLogger().debug("Login page requested, chaining ...");
return true;
}
if (authHdr == null) {
if (allowsTicketLogons()) {
if (checkForTicketParameter(context, req, resp)) {
// Filter validate hook
if (getLogger().isDebugEnabled())
getLogger().debug("Authenticated with a ticket parameter.");
if (user == null) {
user = (SessionUser) httpSess.getAttribute(getUserAttributeName());
}
onValidate(context, req, resp, new TicketCredentials(user.getTicket()));
return true;
}
}
if (getLogger().isDebugEnabled())
getLogger().debug("New Kerberos auth request from " + req.getRemoteHost() + " (" + req.getRemoteAddr() + ":" + req.getRemotePort() + ")");
// Send back a request for SPNEGO authentication
logonStartAgain(context, req, resp, true);
return false;
} else {
// Decode the received SPNEGO blob and validate
final byte[] spnegoByts = Base64.decodeBase64(authHdr.substring(10).getBytes());
if (isNTLMSSPBlob(spnegoByts, 0)) {
if (getLogger().isDebugEnabled())
getLogger().debug("Client sent an NTLMSSP security blob");
// Restart the authentication
restartLoginChallenge(context, req, resp);
return false;
}
// Check the received SPNEGO token type
int tokType = -1;
try {
tokType = SPNEGO.checkTokenType(spnegoByts, 0, spnegoByts.length);
} catch (IOException ex) {
}
if (tokType == SPNEGO.NegTokenInit) {
// Parse the SPNEGO security blob to get the Kerberos ticket
NegTokenInit negToken = new NegTokenInit();
try {
// Decode the security blob
negToken.decode(spnegoByts, 0, spnegoByts.length);
// Determine the authentication mechanism the client is using and logon
String oidStr = null;
if (negToken.numberOfOids() > 0)
oidStr = negToken.getOidAt(0).toString();
if (oidStr != null && (oidStr.equals(OID.ID_MSKERBEROS5) || oidStr.equals(OID.ID_KERBEROS5))) {
try {
NegTokenTarg negTokenTarg = doKerberosLogon(negToken, req, resp, httpSess);
if (negTokenTarg != null) {
// Allow the user to access the requested page
onValidate(context, req, resp, new KerberosCredentials(negToken, negTokenTarg));
if (getLogger().isDebugEnabled())
getLogger().debug("Authenticated through Kerberos.");
return true;
} else {
// Send back a request for SPNEGO authentication
if (getLogger().isDebugEnabled())
getLogger().debug("Failed SPNEGO authentication.");
restartLoginChallenge(context, req, resp);
return false;
}
} catch (AuthenticationException ex) {
// max user limit
if (getLogger().isDebugEnabled())
getLogger().debug("Validate failed.", ex);
onValidateFailed(context, req, resp, httpSess, new TicketCredentials(user.getTicket()));
return false;
}
} else {
if (getLogger().isDebugEnabled())
getLogger().debug("Unsupported SPNEGO mechanism " + oidStr);
// Try again!
restartLoginChallenge(context, req, resp);
}
} catch (IOException ex) {
if (getLogger().isDebugEnabled())
getLogger().debug(ex);
}
} else {
if (getLogger().isDebugEnabled())
getLogger().debug("Unknown SPNEGO token type");
// Send back a request for SPNEGO authentication
restartLoginChallenge(context, req, resp);
}
}
return false;
}
Aggregations