Caffeinated Simpleton

I spent way more time than I should have yesterday trying to figure out how to authenticate with Phabricator’s conduit service. The goal was pretty simple: turn a Phabricator object key (ie. D1337) into a link with the name as the text. Since I was trying to integrate with hubot running on a heroku instance, I didn’t want to use Arcanist to accomplish this.

As it turns out, how to authenticate with conduit given a user and a certificate is not documented anywhere, so I’m writing it down here for all you fine folks.

Getting a Session Key

The first thing you need to do to be able to make calls to conduit is to connect to conduit. I’ll be using https://secure.phabricator.com/ as the canonical Phabricator installation, but you should replace that url with the url to your Phabricator install wherever you see it.

Prerequisites

Making the call

The interesting and undocumented parts of this are the authToken and authSignature bits.

Making a Call to Conduit

After you have a session key, it’s pretty straightforward to make a call.

Example

Here’s an example in Python, using the outstanding requests library.

import hashlib
import json
import requests
import time

# Constants to be filled in by the reader
CERT = 'Your cert here'
USER = 'Your user here'
PHAB = 'Your phabricator URL here'

# Format parameters for conduit.connect
token = int(time.time())
signature = hashlib.sha1(str(token) + CERT).hexdigest()
connect_params = {
    'client': 'Python demo',
    'clientVersion': 0,
    'clientDescription': 'A script for demonstrating conduit',
    'user': USER,
    'host': PHAB,
    'authToken': token,
    'authSignature': signature,
}

# Make the request to conduit.connect
req = requests.post('%s/api/conduit.connect' % PHAB, data={
    'params': json.dumps(connect_params),
    'output': 'json',
    '__conduit__': True,
})

# Parse out the response (error handling ommitted)
result = json.loads(req.content)['result']
conduit = {
    'sessionKey': result['sessionKey'],
    'connectionID': result['connectionID'],
}

# Make the call to phid.lookup
req = requests.post('%s/api/phid.lookup' % PHAB, data={
    'params': json.dumps({
        'names': ['D1337'],
        '__conduit__': conduit,
    }),
    'output': 'json',
})
result = json.loads(req.content)['result']
print result['D1337']['fullName']

Pretty simple once it’s documented :).

comments powered by Disqus