shazino

Using the Mendeley API in ruby

Thursday, 14 March 2013 in dev journal by Damien Mathieu

Mendeley offers a public API for developers to retrieve some of their data and use it in third-party applications.

At Shazino, we love trying out new things and wanted to use it. Our first attempt led us to release the iOS Mendeley SDK as an Open Source project.

Lately, we tried something similar in Ruby. There is already an interesting Open Source mendeley SDK in ruby. Unfortunately, we needed to make authenticated requests, and this gem allows only public API calls.

So we went and made something simple to fix that problem.

A bit of background: OAuth1

OAuth is an authentication protocol for machines. You probably already saw it when applications allow you to authenticate using your account in an other one.
The current main version of OAuth is 2.0, and is the most documented one. However, Mendeley supports only the version 1.0 of the protocol.

The OAuth1 authentication flow is as following:

OAuth1 authentication flow

We don’t need to implement token authentication though, as there already is omniauth-mendeley, a ruby gem to manage that authentication process. But we still need to be able to make API calls with a token once we managed to get one with the above flow.

These calls need to get an oauth_signature parameter, which is SHA1 of all the parameters + your consumer secret and the user’s secret token. You can check out this gist to check how this works.

Fortunately, we aren’t the first ones to try doing this, and faraday has a nice oauth middleware

The Mendeley Ruby library

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#
# Make API calls to the mendeley API
#
#     Mendeley.
#       new("your user's api token", "your user's api key").
#       get('/oapi/profiles/info/me/')
#         #=> Returns a hash with the current's user profile from the API.
#
#
# Dependencies:
#
# * faraday, to make the HTTP calls
# * faraday_middleware, to get the OAuth faraday middleware
#
class Mendeley
  attr_reader :token, :secret

  #
  # Create a new mendeley object
  #
  # @param token [String] the user's access token
  # @param secret [String] the user's access secret
  #
  def initialize(token, secret)
    @token, @secret = token, secret
  end

  #
  # Sends a get request to the mendeley API
  #
  # @param path [String] the path of the request to execute
  # @return [Hash] the json returned by the server
  #
  def get(path)
    connection.get do |req|
      req.url path
    end.body
  end

  private
  def connection
    @connection ||= Faraday.new(url: 'http://api.mendeley.com') do |connection|
      connection.request  :url_encoded
      connection.request  :oauth, oauth_data
      connection.response :json, content_type: //
      connection.adapter  *Faraday.default_adapter
    end
  end

  def oauth_data
    {
      consumer_key: consumer_key,
      consumer_secret: consumer_secret,
      token: token,
      token_secret: secret
    }
  end

  def consumer_key
    'replace this with your Mendeley consumer key'
  end

  def consumer_secret
    'replace this with your Mendeley consumer secret'
  end
end

We can now easily make authenticated calls to the API:

1
2
3
4
5
token    = 'replace this with your user authentication token'
secret   = 'replace this with your user authentication secret'
mendeley = Mendeley.new(token, secret)
profile  = mendeley.get('/oapi/profiles/info/me/') 
  #=> This returns a hash with the current user's profile

For more information on the mendeley API, you should check apidocs.mendeley.com.
Happy Coding!