Upgrading your Neo4J from XXX to 2.2.0–having authorization trouble?

By

Originally posted on: http://geekswithblogs.net/cskardon/archive/2015/03/27/upgrading-your-neo4j-from-xxx-to-2.2.0ndashhaving-authorization-trouble.aspx

I’ve recently upgraded one of my Neo4J dbs from 2.1.7 to 2.2.0, and instantly ran into troubles with the new Authentication that the db now has. You’ll notice it when you first login to your browser (http://localhost:7474/) and get asked for a login name and password. Of course, you can turn off authentication via the settings (conf/neo4-server.properties) by changing the ‘dbms.security.auth_enabled’ value to false, but now we’ve got it, we should use it!

Luckily neo4jclient already allows us to pass in basic auth via the uri, so we can do something like:

var client = new GraphClient(new Uri("http://user:pass@localhost.:7474/db/data"));
client.Connect();

9 times out of 10, that’ll work just fine for you, the problem is if your password has a character in it that the Uri constructor can’t parse – now I’m sure you can escape the character – but I’ve been unable to find out how, so something like:

new Uri(http://user:pass#@localhost.:7474/db/data)

will fail with a ‘UriFormatException: Invalid URI: Invalid port specified.’ message (I’ve added a ‘#’ to the password).

What to do???

Spiffily – the GraphClient has another constructor that takes in an IHttpClient, so we can create our own version that injects the Authorization header into any (and all) requests to the db:

private class HttpClientAuthWrapper : IHttpClient
{
    private readonly AuthenticationHeaderValue _authenticationHeader;
    private readonly HttpClient _client;

    public HttpClientAuthWrapper(string username, string password)
    {
        _client = new HttpClient();
        if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
            return;

        var encoded = Encoding.ASCII.GetBytes(string.Format("{0}:{1}", username, password));
        _authenticationHeader = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(encoded));
    }

    public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
    {
        if(_authenticationHeader != null)
            request.Headers.Authorization = _authenticationHeader;
        return _client.SendAsync(request);
    }
}

Which is used like so:

var client = new GraphClient(
    new Uri("http://localhost.:7474/db/data"), 
    new HttpClientAuthWrapper("user", "pass#")
    );
client.Connect();

All authorized and happy!