Skip to content

Commit

Permalink
Fix http auth tests
Browse files Browse the repository at this point in the history
- Create AuthToken test util
  • Loading branch information
henriknyman committed Oct 3, 2018
1 parent be15127 commit 4d4ecdf
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 27 deletions.
Expand Up @@ -21,9 +21,7 @@


import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;


import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Map;


import org.neo4j.bolt.messaging.Neo4jPack.Unpacker; import org.neo4j.bolt.messaging.Neo4jPack.Unpacker;
import org.neo4j.bolt.messaging.RequestMessage; import org.neo4j.bolt.messaging.RequestMessage;
Expand All @@ -33,13 +31,13 @@
import org.neo4j.bolt.v1.messaging.request.InitMessage; import org.neo4j.bolt.v1.messaging.request.InitMessage;
import org.neo4j.bolt.v1.packstream.PackedInputArray; import org.neo4j.bolt.v1.packstream.PackedInputArray;
import org.neo4j.kernel.api.security.AuthToken; import org.neo4j.kernel.api.security.AuthToken;
import org.neo4j.string.UTF8;


import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.neo4j.bolt.v1.messaging.util.MessageMatchers.serialize; import static org.neo4j.bolt.v1.messaging.util.MessageMatchers.serialize;
import static org.neo4j.helpers.collection.MapUtil.map; import static org.neo4j.helpers.collection.MapUtil.map;
import static org.neo4j.test.AuthTokenUtil.assertAuthTokenMatches;


class InitMessageDecoderTest class InitMessageDecoderTest
{ {
Expand Down Expand Up @@ -184,22 +182,4 @@ private static void assertInitMessageMatches( InitMessage expected, RequestMessa
assertEquals( expected.userAgent(), ((InitMessage) actual).userAgent() ); assertEquals( expected.userAgent(), ((InitMessage) actual).userAgent() );
assertAuthTokenMatches( expected.authToken(), ((InitMessage) actual).authToken() ); assertAuthTokenMatches( expected.authToken(), ((InitMessage) actual).authToken() );
} }

private static void assertAuthTokenMatches( Map<String,Object> expected, Map<String,Object> actual )
{
assertEquals( expected.keySet(), actual.keySet() );
expected.forEach( ( key, expectedValue ) ->
{
Object actualValue = actual.get( key );
if ( AuthToken.containsSensitiveInformation( key ) )
{
byte[] expectedByteArray = expectedValue != null ? UTF8.encode( (String) expectedValue ) : null;
Arrays.equals( expectedByteArray, (byte[]) actualValue );
}
else
{
assertEquals( expectedValue, actualValue );
}
} );
}
} }
121 changes: 121 additions & 0 deletions community/kernel/src/test/java/org/neo4j/test/AuthTokenUtil.java
@@ -0,0 +1,121 @@
/*
* Copyright (c) 2002-2018 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.test;

import org.mockito.ArgumentMatcher;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;

import org.neo4j.kernel.api.security.AuthToken;
import org.neo4j.string.UTF8;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress;

public class AuthTokenUtil
{
public static boolean matches( Map<String,Object> expected, Map<String,Object> actual )
{
if ( expected == null || actual == null )
{
return expected == actual;
}

if ( expected.size() != actual.size() )
{
return false;
}

for ( Map.Entry<String,Object> expectedEntry : expected.entrySet() )
{
String key = expectedEntry.getKey();
Object expectedValue = expectedEntry.getValue();
Object actualValue = actual.get( key );
if ( AuthToken.containsSensitiveInformation( key ) )
{
byte[] expectedByteArray = expectedValue instanceof byte[] ? (byte[]) expectedValue :
expectedValue != null ? UTF8.encode( (String) expectedValue ) : null;
if ( !Arrays.equals( expectedByteArray, (byte[]) actualValue ) )
{
return false;
}
}
else if ( expectedValue == null ^ actualValue == null )
{
return false;
}
else if ( !expectedValue.equals( actualValue ) )
{
return false;
}
}
return true;
}

public static void assertAuthTokenMatches( Map<String,Object> expected, Map<String,Object> actual )
{
assertFalse( expected == null ^ actual == null );
assertEquals( expected.keySet(), actual.keySet() );
expected.forEach( ( key, expectedValue ) ->
{
Object actualValue = actual.get( key );
if ( AuthToken.containsSensitiveInformation( key ) )
{
byte[] expectedByteArray = expectedValue != null ? UTF8.encode( (String) expectedValue ) : null;
assertTrue( Arrays.equals( expectedByteArray, (byte[]) actualValue ) );
}
else
{
assertEquals( expectedValue, actualValue );
}
} );
}

public static class AuthTokenArgumentMatcher implements ArgumentMatcher<Map<String,Object>>, Serializable
{

private Map<String,Object> wanted;

public AuthTokenArgumentMatcher( Map<String,Object> authToken )
{
this.wanted = authToken;
}

public boolean matches( Map<String,Object> actual )
{
return AuthTokenUtil.matches( wanted, actual );
}

public String toString()
{
return "authTokenMatcher(" + wanted + ")";
}
}

public static Map<String,Object> authTokenMatcher( Map<String,Object> authToken )
{
mockingProgress().getArgumentMatcherStorage().reportMatcher( new AuthTokenArgumentMatcher( authToken ) );
return null;
}
}
Expand Up @@ -24,7 +24,6 @@
import org.junit.Test; import org.junit.Test;


import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
Expand Down Expand Up @@ -53,6 +52,7 @@
import static org.neo4j.internal.kernel.api.security.LoginContext.AUTH_DISABLED; import static org.neo4j.internal.kernel.api.security.LoginContext.AUTH_DISABLED;
import static org.neo4j.logging.AssertableLogProvider.inLog; import static org.neo4j.logging.AssertableLogProvider.inLog;
import static org.neo4j.server.security.auth.SecurityTestUtils.authToken; import static org.neo4j.server.security.auth.SecurityTestUtils.authToken;
import static org.neo4j.test.AuthTokenUtil.authTokenMatcher;


public class AuthorizationFilterTest public class AuthorizationFilterTest
{ {
Expand Down Expand Up @@ -176,7 +176,7 @@ public void shouldNotAuthorizeInvalidCredentials() throws Exception
when( servletRequest.getContextPath() ).thenReturn( "/db/data" ); when( servletRequest.getContextPath() ).thenReturn( "/db/data" );
when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials ); when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials );
when( servletRequest.getRemoteAddr() ).thenReturn( "remote_ip_address" ); when( servletRequest.getRemoteAddr() ).thenReturn( "remote_ip_address" );
when( authManager.login( authToken( "foo", "bar" ) ) ).thenReturn( loginContext ); when( authManager.login( authTokenMatcher( authToken( "foo", "bar" ) ) ) ).thenReturn( loginContext );
when( loginContext.subject() ).thenReturn( authSubject ); when( loginContext.subject() ).thenReturn( authSubject );
when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.FAILURE ); when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.FAILURE );


Expand Down Expand Up @@ -206,7 +206,7 @@ public void shouldAuthorizeWhenPasswordChangeRequiredForWhitelistedPath() throws
when( servletRequest.getMethod() ).thenReturn( "GET" ); when( servletRequest.getMethod() ).thenReturn( "GET" );
when( servletRequest.getContextPath() ).thenReturn( "/user/foo" ); when( servletRequest.getContextPath() ).thenReturn( "/user/foo" );
when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials ); when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials );
when( authManager.login( authToken( "foo", "bar" ) ) ).thenReturn( loginContext ); when( authManager.login( authTokenMatcher( authToken( "foo", "bar" ) ) ) ).thenReturn( loginContext );
when( loginContext.subject() ).thenReturn( authSubject ); when( loginContext.subject() ).thenReturn( authSubject );
when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.PASSWORD_CHANGE_REQUIRED ); when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.PASSWORD_CHANGE_REQUIRED );


Expand All @@ -231,7 +231,7 @@ public void shouldNotAuthorizeWhenPasswordChangeRequired() throws Exception
when( servletRequest.getRequestURL() ).thenReturn( new StringBuffer( "http://bar.baz:7474/db/data/" ) ); when( servletRequest.getRequestURL() ).thenReturn( new StringBuffer( "http://bar.baz:7474/db/data/" ) );
when( servletRequest.getRequestURI() ).thenReturn( "/db/data/" ); when( servletRequest.getRequestURI() ).thenReturn( "/db/data/" );
when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials ); when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials );
when( authManager.login( authToken( "foo", "bar" ) ) ).thenReturn( loginContext ); when( authManager.login( authTokenMatcher( authToken( "foo", "bar" ) ) ) ).thenReturn( loginContext );
when( loginContext.subject() ).thenReturn( authSubject ); when( loginContext.subject() ).thenReturn( authSubject );
when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.PASSWORD_CHANGE_REQUIRED ); when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.PASSWORD_CHANGE_REQUIRED );


Expand Down Expand Up @@ -261,7 +261,7 @@ public void shouldNotAuthorizeWhenTooManyAttemptsMade() throws Exception
when( servletRequest.getMethod() ).thenReturn( "GET" ); when( servletRequest.getMethod() ).thenReturn( "GET" );
when( servletRequest.getContextPath() ).thenReturn( "/db/data" ); when( servletRequest.getContextPath() ).thenReturn( "/db/data" );
when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials ); when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials );
when( authManager.login( authToken( "foo", "bar" ) ) ).thenReturn( loginContext ); when( authManager.login( authTokenMatcher( authToken( "foo", "bar" ) ) ) ).thenReturn( loginContext );
when( loginContext.subject() ).thenReturn( authSubject ); when( loginContext.subject() ).thenReturn( authSubject );
when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.TOO_MANY_ATTEMPTS ); when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.TOO_MANY_ATTEMPTS );


Expand Down Expand Up @@ -290,7 +290,7 @@ public void shouldAuthorizeWhenValidCredentialsSupplied() throws Exception
when( servletRequest.getMethod() ).thenReturn( "GET" ); when( servletRequest.getMethod() ).thenReturn( "GET" );
when( servletRequest.getContextPath() ).thenReturn( "/db/data" ); when( servletRequest.getContextPath() ).thenReturn( "/db/data" );
when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials ); when( servletRequest.getHeader( HttpHeaders.AUTHORIZATION ) ).thenReturn( "BASIC " + credentials );
when( authManager.login( authToken( "foo", "bar" ) ) ).thenReturn( loginContext ); when( authManager.login( authTokenMatcher( authToken( "foo", "bar" ) ) ) ).thenReturn( loginContext );
when( loginContext.subject() ).thenReturn( authSubject ); when( loginContext.subject() ).thenReturn( authSubject );
when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.SUCCESS ); when( authSubject.getAuthenticationResult() ).thenReturn( AuthenticationResult.SUCCESS );


Expand Down

0 comments on commit 4d4ecdf

Please sign in to comment.