001package org.apache.archiva.redback.rest.services.interceptors; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 023import org.apache.archiva.redback.authentication.AuthenticationException; 024import org.apache.archiva.redback.authentication.AuthenticationResult; 025import org.apache.archiva.redback.authorization.RedbackAuthorization; 026import org.apache.archiva.redback.integration.filter.authentication.HttpAuthenticationException; 027import org.apache.archiva.redback.integration.filter.authentication.basic.HttpBasicAuthentication; 028import org.apache.archiva.redback.policy.AccountLockedException; 029import org.apache.archiva.redback.policy.MustChangePasswordException; 030import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal; 031import org.apache.archiva.redback.rest.services.RedbackRequestInformation; 032import org.apache.archiva.redback.system.SecuritySession; 033import org.apache.archiva.redback.users.User; 034import org.apache.archiva.redback.users.UserManager; 035import org.apache.archiva.redback.users.UserManagerException; 036import org.apache.archiva.redback.users.UserNotFoundException; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039import org.springframework.stereotype.Service; 040 041import javax.annotation.Priority; 042import javax.inject.Inject; 043import javax.inject.Named; 044import javax.servlet.http.HttpServletRequest; 045import javax.servlet.http.HttpServletResponse; 046import javax.ws.rs.container.ContainerRequestContext; 047import javax.ws.rs.container.ContainerRequestFilter; 048import javax.ws.rs.container.ResourceInfo; 049import javax.ws.rs.core.Context; 050import javax.ws.rs.core.Response; 051import javax.ws.rs.ext.Provider; 052 053/** 054 * This interceptor will check if the user is already logged in the session. 055 * If not ask the redback system to authentication trough BASIC http 056 * If the user is logged the AuthenticationResult will in the cxf message with the key AuthenticationResult.class 057 * 058 * @author Olivier Lamy 059 * @since 1.3 060 */ 061@Service("authenticationInterceptor#rest") 062@Provider 063@Priority( Priorities.AUTHENTICATION ) 064public class AuthenticationInterceptor 065 extends AbstractInterceptor 066 implements ContainerRequestFilter 067{ 068 @Inject 069 @Named(value = "userManager#default") 070 private UserManager userManager; 071 072 @Inject 073 @Named(value = "httpAuthenticator#basic") 074 private HttpBasicAuthentication httpAuthenticator; 075 076 @Context 077 private ResourceInfo resourceInfo; 078 079 private final Logger log = LoggerFactory.getLogger( getClass() ); 080 081 public void filter( ContainerRequestContext containerRequestContext ) 082 { 083 084 // Message message = JAXRSUtils.getCurrentMessage(); 085 086 RedbackAuthorization redbackAuthorization = getRedbackAuthorization( resourceInfo ); 087 if ( redbackAuthorization == null ) 088 { 089 log.warn( "http path {} doesn't contain any informations regarding permissions ", 090 containerRequestContext.getUriInfo().getRequestUri()); 091 // here we failed to authenticate so 403 as there is no detail on karma for this 092 // it must be marked as it's exposed 093 containerRequestContext.abortWith( Response.status( Response.Status.FORBIDDEN ).build() ); 094 return; 095 } 096 HttpServletRequest request = getHttpServletRequest( ); 097 HttpServletResponse response = getHttpServletResponse( ); 098 099 if ( redbackAuthorization.noRestriction() ) 100 { 101 // maybe session exists so put it in threadLocal 102 // some services need the current user if logged 103 SecuritySession securitySession = httpAuthenticator.getSecuritySession( request.getSession( true ) ); 104 105 if ( securitySession != null ) 106 { 107 RedbackRequestInformation redbackRequestInformation = 108 new RedbackRequestInformation( securitySession.getUser(), request.getRemoteAddr() ); 109 RedbackAuthenticationThreadLocal.set( redbackRequestInformation ); 110 } 111 else 112 { 113 // maybe there is some authz in the request so try it but not fail so catch Exception ! 114 try 115 { 116 AuthenticationResult authenticationResult = 117 httpAuthenticator.getAuthenticationResult( request, response ); 118 119 if ( ( authenticationResult == null ) || ( !authenticationResult.isAuthenticated() ) ) 120 { 121 return; 122 } 123 124 User user = authenticationResult.getUser() == null ? userManager.findUser( 125 authenticationResult.getPrincipal() ) : authenticationResult.getUser(); 126 RedbackRequestInformation redbackRequestInformation = 127 new RedbackRequestInformation( user, request.getRemoteAddr() ); 128 129 RedbackAuthenticationThreadLocal.set( redbackRequestInformation ); 130 // message.put( AuthenticationResult.class, authenticationResult ); 131 containerRequestContext.setProperty( AUTHENTICATION_RESULT, authenticationResult ); 132 } 133 catch ( Exception e ) 134 { 135 // ignore here 136 } 137 } 138 return; 139 } 140 141 try 142 { 143 AuthenticationResult authenticationResult = httpAuthenticator.getAuthenticationResult( request, response ); 144 145 if ( ( authenticationResult == null ) || ( !authenticationResult.isAuthenticated() ) ) 146 { 147 throw new HttpAuthenticationException( "You are not authenticated." ); 148 } 149 150 User user = authenticationResult.getUser() == null 151 ? userManager.findUser( authenticationResult.getPrincipal() ) 152 : authenticationResult.getUser(); 153 154 RedbackRequestInformation redbackRequestInformation = 155 new RedbackRequestInformation( user, request.getRemoteAddr() ); 156 157 RedbackAuthenticationThreadLocal.set( redbackRequestInformation ); 158 // message.put( AuthenticationResult.class, authenticationResult ); 159 160 return; 161 } 162 catch ( UserNotFoundException e ) 163 { 164 log.debug( "UserNotFoundException for path {}", containerRequestContext.getUriInfo().getRequestUri() ); 165 } 166 catch ( AccountLockedException e ) 167 { 168 log.debug( "account locked for path {}", containerRequestContext.getUriInfo().getRequestUri() ); 169 } 170 catch ( MustChangePasswordException e ) 171 { 172 log.debug( "must change password for path {}", containerRequestContext.getUriInfo().getRequestUri() ); 173 } 174 catch ( AuthenticationException e ) 175 { 176 log.debug( "failed to authenticate for path {}", containerRequestContext.getUriInfo().getRequestUri() ); 177 } 178 catch ( UserManagerException e ) 179 { 180 log.debug( "UserManagerException: {} for path", e.getMessage(), containerRequestContext.getUriInfo().getRequestUri() ); 181 } 182 containerRequestContext.abortWith( Response.status( Response.Status.FORBIDDEN ).build() ); 183 } 184}