Skip to content

Draft Authentication API #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.driver.internal;

import java.net.URI;

import org.neo4j.driver.internal.pool.InternalConnectionPool;
import org.neo4j.driver.internal.spi.ConnectionPool;
import org.neo4j.driver.v1.AuthToken;
import org.neo4j.driver.v1.Config;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.Session;

public class InternalDriver implements Driver
{
private final ConnectionPool connections;
private final URI url;
private final Config config;

public InternalDriver( URI url, AuthToken authToken, Config config )
{
this.url = url;
this.connections = new InternalConnectionPool( config, authToken );
this.config = config;
}

/**
* Establish a session
* @return a session that could be used to run {@link Session#run(String) a statement} or
* {@link Session#beginTransaction() a transaction }.
*/
@Override
public Session session()
{
return new InternalSession( connections.acquire( url ), config.logging().getLog( "session" ) );
}

/**
* Close all the resources assigned to this driver
* @throws Exception any error that might happen when releasing all resources
*/
public void close() throws Exception
{
connections.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.driver.internal.auth;

import java.util.Map;

import org.neo4j.driver.v1.Value;
import org.neo4j.driver.v1.AuthToken;

/**
* A simple common token for authentication schemes that easily convert to
* an auth token map
*/
public class InternalAuthToken implements AuthToken
{
private final Map<String,Value> content;

public InternalAuthToken( Map<String,Value> content )
{
this.content = content;
}

public Map<String, Value> toMap()
{
return content;
}

@Override
public boolean equals( Object o )
{
if ( this == o )
{ return true; }
if ( o == null || getClass() != o.getClass() )
{ return false; }

InternalAuthToken that = (InternalAuthToken) o;

return content != null ? content.equals( that.content ) : that.content == null;

}

@Override
public int hashCode()
{
return content != null ? content.hashCode() : 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public LoggingResponseHandler( Logger logger )
}

@Override
public void handleInitMessage( String clientNameAndVersion )
public void handleInitMessage( String clientNameAndVersion, Map<String,Value> authToken )
{
super.handleInitMessage( clientNameAndVersion );
super.handleInitMessage( clientNameAndVersion, authToken );
logger.debug( "S: [INIT \"%s\"]", clientNameAndVersion );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ public SocketConnection( String host, int port, Config config )
}

@Override
public void init( String clientName )
public void init( String clientName, Map<String,Value> authToken )
{
queueMessage( new InitMessage( clientName ), StreamCollector.NO_OP );
queueMessage( new InitMessage( clientName, authToken ), StreamCollector.NO_OP );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

import org.neo4j.driver.internal.Version;
import org.neo4j.driver.internal.auth.InternalAuthToken;
import org.neo4j.driver.internal.spi.Connection;
import org.neo4j.driver.internal.spi.Connector;
import org.neo4j.driver.v1.Config;
import org.neo4j.driver.v1.Value;
import org.neo4j.driver.v1.AuthToken;
import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.exceptions.ClientException;

public class SocketConnector implements Connector
Expand All @@ -40,11 +45,11 @@ public boolean supports( String scheme )
}

@Override
public Connection connect( URI sessionURI, Config config ) throws ClientException
public Connection connect( URI sessionURI, Config config, AuthToken authToken ) throws ClientException
{
int port = sessionURI.getPort() == -1 ? DEFAULT_PORT : sessionURI.getPort();
SocketConnection conn = new SocketConnection( sessionURI.getHost(), port, config );
conn.init( "bolt-java-driver/" + Version.driverVersion() );
conn.init( "bolt-java-driver/" + Version.driverVersion(), tokenAsMap( authToken ) );
return conn;
}

Expand All @@ -53,4 +58,17 @@ public Collection<String> supportedSchemes()
{
return Collections.singletonList( SCHEME );
}

private Map<String,Value> tokenAsMap( AuthToken token )
{
if( token instanceof InternalAuthToken )
{
return ((InternalAuthToken) token).toMap();
}
else
{
throw new ClientException( "Unknown authentication token, `" + token + "`. Please use one of the supported " +
"tokens from `" + AuthTokens.class.getSimpleName() + "`." );
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public void handlePullAllMessage()
}

@Override
public void handleInitMessage( String clientNameAndVersion )
public void handleInitMessage( String clientNameAndVersion, Map<String,Value> authToken )
{

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
package org.neo4j.driver.internal.messaging;

import java.io.IOException;
import java.util.Map;

import org.neo4j.driver.v1.Value;

import static java.lang.String.format;

Expand All @@ -30,16 +33,18 @@
public class InitMessage implements Message
{
private final String clientNameAndVersion;
private Map<String,Value> authToken;

public InitMessage( String clientNameAndVersion )
public InitMessage( String clientNameAndVersion, Map<String,Value> authToken )
{
this.clientNameAndVersion = clientNameAndVersion;
this.authToken = authToken;
}

@Override
public void dispatch( MessageHandler handler ) throws IOException
{
handler.handleInitMessage( clientNameAndVersion );
handler.handleInitMessage( clientNameAndVersion, authToken );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
public interface MessageHandler
{
// Requests
void handleInitMessage( String clientNameAndVersion ) throws IOException;
void handleInitMessage( String clientNameAndVersion, Map<String,Value> authToken ) throws IOException;

void handleRunMessage( String statement, Map<String,Value> parameters ) throws IOException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.neo4j.driver.internal.InternalRelationship;
import org.neo4j.driver.internal.connector.socket.ChunkedInput;
import org.neo4j.driver.internal.connector.socket.ChunkedOutput;
import org.neo4j.driver.internal.packstream.BufferedChannelOutput;
import org.neo4j.driver.internal.packstream.PackInput;
import org.neo4j.driver.internal.packstream.PackOutput;
import org.neo4j.driver.internal.packstream.PackStream;
Expand Down Expand Up @@ -105,11 +104,6 @@ public static class Writer implements MessageFormat.Writer, MessageHandler
private final PackStream.Packer packer;
private final Runnable onMessageComplete;

public Writer()
{
this( new BufferedChannelOutput( 8192 ), new NoOpRunnable() );
}

/**
* @param output interface to write messages to
* @param onMessageComplete invoked for each message, after it's done writing to the output
Expand All @@ -121,10 +115,11 @@ public Writer( PackOutput output, Runnable onMessageComplete )
}

@Override
public void handleInitMessage( String clientNameAndVersion ) throws IOException
public void handleInitMessage( String clientNameAndVersion, Map<String,Value> authToken ) throws IOException
{
packer.packStructHeader( 1, MSG_INIT );
packer.pack( clientNameAndVersion );
packRawMap( authToken );
onMessageComplete.run();
}

Expand Down Expand Up @@ -445,7 +440,7 @@ private void unpackResetMessage( MessageHandler handler ) throws IOException

private void unpackInitMessage( MessageHandler handler ) throws IOException
{
handler.handleInitMessage( unpacker.unpackString() );
handler.handleInitMessage( unpacker.unpackString(), unpackMap() );
onMessageComplete.run();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.neo4j.driver.internal.spi.Connector;
import org.neo4j.driver.internal.util.Clock;
import org.neo4j.driver.internal.util.Consumer;
import org.neo4j.driver.v1.AuthToken;
import org.neo4j.driver.v1.Config;
import org.neo4j.driver.v1.exceptions.ClientException;

Expand Down Expand Up @@ -65,6 +66,7 @@ public class InternalConnectionPool implements ConnectionPool
*/
private final ValidationStrategy<PooledConnection> connectionValidation;

private final AuthToken authToken;
/**
* Timeout in milliseconds if there are no available sessions.
*/
Expand All @@ -73,13 +75,16 @@ public class InternalConnectionPool implements ConnectionPool
private final Clock clock;
private final Config config;

public InternalConnectionPool( Config config )
public InternalConnectionPool( Config config, AuthToken authToken )
{
this( loadConnectors(), Clock.SYSTEM, config, Long.getLong( "neo4j.driver.acquireSessionTimeout", 30_000 ) );
this( loadConnectors(), Clock.SYSTEM, config, authToken,
Long.getLong( "neo4j.driver.acquireSessionTimeout", 30_000 ) );
}

public InternalConnectionPool( Collection<Connector> conns, Clock clock, Config config, long acquireTimeout )
public InternalConnectionPool( Collection<Connector> conns, Clock clock, Config config,
AuthToken authToken, long acquireTimeout )
{
this.authToken = authToken;
this.acquireSessionTimeout = acquireTimeout;
this.config = config;
this.clock = clock;
Expand Down Expand Up @@ -180,7 +185,7 @@ public PooledConnection allocate( Consumer<PooledConnection> release )
"'" + uri.getScheme() + "' is not a supported transport (in '" +
uri + "', available transports are: " + connectorSchemes() + "." );
}
Connection conn = connector.connect( uri, config );
Connection conn = connector.connect( uri, config, authToken );
return new PooledConnection( conn, release );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ public PooledConnection( Connection delegate, Consumer<PooledConnection> release
}

@Override
public void init( String clientName )
public void init( String clientName, Map<String,Value> authToken )
{
try
{
delegate.init( clientName );
delegate.init( clientName, authToken );
}
catch( RuntimeException e )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ public interface Connection extends AutoCloseable
/**
* Initialize the connection. This must be done before any other action is allowed.
* @param clientName should be the driver name and version: "java-driver/1.0.0"
* @param authToken
*/
void init( String clientName );
void init( String clientName, Map<String,Value> authToken );

/**
* Queue up a run action. The collector will value called with metadata about the stream that will become available
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.net.URI;
import java.util.Collection;

import org.neo4j.driver.v1.AuthToken;
import org.neo4j.driver.v1.Config;
import org.neo4j.driver.v1.exceptions.ClientException;

Expand All @@ -43,9 +44,10 @@ public interface Connector
*
* @param sessionURL a URL identifying a remote session
* @param config a configuration for this connection
* @param authToken
* @return a Connection object
*/
Connection connect( URI sessionURL, Config config ) throws ClientException;
Connection connect( URI sessionURL, Config config, AuthToken authToken ) throws ClientException;

/** List names of supported schemes, used for error messages and similar signaling to end users. */
Collection<String> supportedSchemes();
Expand Down
Loading