Skip to content

Commit e1021eb

Browse files
committed
Add bearer authentication support
1 parent c11e210 commit e1021eb

File tree

7 files changed

+102
-6
lines changed

7 files changed

+102
-6
lines changed

driver/src/main/java/org/neo4j/driver/AuthTokens.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@
2424
import org.neo4j.driver.internal.security.InternalAuthToken;
2525

2626
import static java.util.Collections.singletonMap;
27+
import static org.neo4j.driver.Values.value;
2728
import static org.neo4j.driver.internal.security.InternalAuthToken.CREDENTIALS_KEY;
2829
import static org.neo4j.driver.internal.security.InternalAuthToken.PARAMETERS_KEY;
2930
import static org.neo4j.driver.internal.security.InternalAuthToken.PRINCIPAL_KEY;
3031
import static org.neo4j.driver.internal.security.InternalAuthToken.REALM_KEY;
3132
import static org.neo4j.driver.internal.security.InternalAuthToken.SCHEME_KEY;
3233
import static org.neo4j.driver.internal.util.Iterables.newHashMapWithSize;
33-
import static org.neo4j.driver.Values.value;
3434

3535
/**
3636
* This is a listing of the various methods of authentication supported by this
@@ -79,13 +79,32 @@ public static AuthToken basic( String username, String password, String realm )
7979
return new InternalAuthToken( map );
8080
}
8181

82+
/**
83+
* The bearer authentication scheme, using a base64 encoded token.
84+
*
85+
* @param token base64 encoded token
86+
* @return an authentication token that can be used to connect to Neo4j
87+
* @throws NullPointerException when token is {@code null}
88+
* @see GraphDatabase#driver(String, AuthToken)
89+
*/
90+
public static AuthToken bearer( String token )
91+
{
92+
Objects.requireNonNull( token, "Token can't be null" );
93+
94+
Map<String,Value> map = newHashMapWithSize( 2 );
95+
map.put( SCHEME_KEY, value( "bearer" ) );
96+
map.put( CREDENTIALS_KEY, value( token ) );
97+
return new InternalAuthToken( map );
98+
}
99+
82100
/**
83101
* The kerberos authentication scheme, using a base64 encoded ticket
102+
*
84103
* @param base64EncodedTicket a base64 encoded service ticket
85104
* @return an authentication token that can be used to connect to Neo4j
105+
* @throws NullPointerException when ticket is {@code null}
86106
* @see GraphDatabase#driver(String, AuthToken)
87107
* @since 1.3
88-
* @throws NullPointerException when ticket is {@code null}
89108
*/
90109
public static AuthToken kerberos( String base64EncodedTicket )
91110
{
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.exceptions;
20+
21+
/**
22+
* The provided token has expired.
23+
* <p>
24+
* The current driver instance is considered invalid. It should not be used anymore. The client must create a new driver instance with a valid token.
25+
* <p>
26+
* Error code: Neo.ClientError.Security.TokenExpired
27+
*/
28+
public class TokenExpiredException extends SecurityException
29+
{
30+
public TokenExpiredException( String code, String message )
31+
{
32+
super( code, message );
33+
}
34+
}

driver/src/main/java/org/neo4j/driver/internal/util/ErrorUtil.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.neo4j.driver.exceptions.Neo4jException;
3333
import org.neo4j.driver.exceptions.ResultConsumedException;
3434
import org.neo4j.driver.exceptions.ServiceUnavailableException;
35+
import org.neo4j.driver.exceptions.TokenExpiredException;
3536
import org.neo4j.driver.exceptions.TransientException;
3637

3738
public final class ErrorUtil
@@ -80,6 +81,10 @@ else if ( code.equalsIgnoreCase( "Neo.ClientError.Security.AuthorizationExpired"
8081
{
8182
return new AuthorizationExpiredException( code, message );
8283
}
84+
else if ( code.equalsIgnoreCase( "Neo.ClientError.Security.TokenExpired" ) )
85+
{
86+
return new TokenExpiredException( code, message );
87+
}
8388
else
8489
{
8590
return new ClientException( code, message );

driver/src/test/java/org/neo4j/driver/AuthTokensTest.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323
import java.util.HashMap;
2424
import java.util.Map;
2525

26-
import org.neo4j.driver.AuthToken;
27-
import org.neo4j.driver.AuthTokens;
28-
import org.neo4j.driver.Value;
2926
import org.neo4j.driver.internal.security.InternalAuthToken;
3027
import org.neo4j.driver.internal.value.ListValue;
3128
import org.neo4j.driver.internal.value.MapValue;
@@ -103,6 +100,22 @@ void customAuthParameters()
103100
assertThat( map.get( "parameters" ), equalTo( (Value) new MapValue( expectedParameters ) ) );
104101
}
105102

103+
@Test
104+
void shouldSupportBearerAuth()
105+
{
106+
// GIVEN
107+
String tokenStr = "token";
108+
109+
// WHEN
110+
InternalAuthToken token = (InternalAuthToken) AuthTokens.bearer( tokenStr );
111+
112+
// THEN
113+
Map<String,Value> map = token.toMap();
114+
assertThat( map.size(), equalTo( 2 ) );
115+
assertThat( map.get( "scheme" ), equalTo( new StringValue( "bearer" ) ) );
116+
assertThat( map.get( "credentials" ), equalTo( new StringValue( tokenStr ) ) );
117+
}
118+
106119
@Test
107120
void basicKerberosAuthWithRealm()
108121
{
@@ -141,6 +154,13 @@ void shouldAllowBasicAuthTokenWithNullRealm()
141154
assertEquals( "password", map.get( "credentials" ).asString() );
142155
}
143156

157+
@Test
158+
void shouldNotAllowBearerAuthTokenWithNullToken()
159+
{
160+
NullPointerException e = assertThrows( NullPointerException.class, () -> AuthTokens.bearer( null ) );
161+
assertEquals( "Token can't be null", e.getMessage() );
162+
}
163+
144164
@Test
145165
void shouldNotAllowKerberosAuthTokenWithNullTicket()
146166
{

driver/src/test/java/org/neo4j/driver/internal/util/ErrorUtilTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.neo4j.driver.exceptions.DatabaseException;
2929
import org.neo4j.driver.exceptions.Neo4jException;
3030
import org.neo4j.driver.exceptions.ServiceUnavailableException;
31+
import org.neo4j.driver.exceptions.TokenExpiredException;
3132
import org.neo4j.driver.exceptions.TransientException;
3233

3334
import static org.hamcrest.Matchers.containsString;
@@ -175,4 +176,17 @@ void shouldCreateAuthorizationExpiredException()
175176
assertEquals( code, error.code() );
176177
assertEquals( message, error.getMessage() );
177178
}
179+
180+
@Test
181+
void shouldCreateTokenExpiredException()
182+
{
183+
String code = "Neo.ClientError.Security.TokenExpired";
184+
String message = "message";
185+
186+
Neo4jException error = newNeo4jError( code, message );
187+
188+
assertThat( error, instanceOf( TokenExpiredException.class ) );
189+
assertEquals( code, error.code() );
190+
assertEquals( message, error.getMessage() );
191+
}
178192
}

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetFeatures.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public class GetFeatures implements TestkitRequest
3939
"AuthorizationExpiredTreatment",
4040
"ConfHint:connection.recv_timeout_seconds",
4141
"Temporary:DriverFetchSize",
42-
"Temporary:DriverMaxTxRetryTime"
42+
"Temporary:DriverMaxTxRetryTime",
43+
"Feature:Auth:Bearer"
4344
) );
4445

4546
private static final Set<String> SYNC_FEATURES = new HashSet<>( Arrays.asList(

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ public TestkitResponse process( TestkitState testkitState )
7575
data.authorizationToken.getTokens().get( "credentials" ),
7676
data.authorizationToken.getTokens().get( "realm" ) );
7777
break;
78+
case "bearer":
79+
authToken = AuthTokens.bearer( data.authorizationToken.getTokens().get( "credentials" ) );
80+
break;
7881
default:
7982
return BackendError.builder()
8083
.data( BackendError

0 commit comments

Comments
 (0)