Tech Blog

Integrating with Alma’s Real Time Availability and Get-It Tab

Alma provides APIs to determine the physical, electronic, and digital availability of a BIB. Alma’s fulfillment services page, or “Get It tab”, provides users with detailed information about the resource, along with links to view online versions or request physical copies. Combining the availability API with the fulfillment services page, integrated with your organization’s single sign on, can provide your users with a full “discovery-like” experience.

RTA API

Real time availability is a feature of the Retrieve BIB API. Using the expand parameter with the values p_avail,e_avail,d_avail will return a bibliographic record enriched with availability information. The availability information is returned in non-standard MARC tags called AVA, AVE, and AVD respectively. Here’s a sample of the AVA tag from a BIB:

<datafield ind1=" " ind2=" " tag="AVA">
   <subfield code="a">TR_INTEGRATION_INST</subfield>
   <subfield code="b">MAIN</subfield>
   <subfield code="c">Not Currently Available</subfield>
   <subfield code="d">E184.J5 F75</subfield>
   <subfield code="e">unavailable</subfield>
   <subfield code="f">1</subfield>
   <subfield code="g">1</subfield>
   <subfield code="j">main</subfield>
   <subfield code="k">1</subfield>
   <subfield code="p">1</subfield>
</datafield>

By extracting the information from the MARCXML of the BIB record, we can prepare a small JSON object which summarizes the availability for the requested BIBs. Below we do just that in Ruby:

def alma_get_bibs_availability(mms_id)
  response =
  RestClient.get ENV['almaurl'] +
    "/bibs?mms_id=#{mms_id}&expand=p_avail,e_avail,d_avail",
    authorization: 'apikey ' + ENV['apikey']

  xml = Nokogiri::XML(response)
  bibs = {}
  bib_nodes = xml.xpath('/bibs/bib')
  bib_nodes.each do |bib_node|
    print = bib_node.at_xpath('record/datafield[@tag="AVA"]/subfield[@code="e"]')
    digital = bib_node.at_xpath('record/datafield[@tag="AVD"]')
    electronic = bib_node.at_xpath('record/datafield[@tag="AVE"]')

    bibs[bib_node.at_xpath('mms_id').text] =
      { :physical =>
        {   :exists => print ? true : false,
          :available => print && print.text == 'available' ? true : false
        },
         :online   =>
        { :exists => digital || electronic ? true : false }
      }
  end

  return bibs
end

Then from our HTML page which shows information on the relevant BIB, we can query the availability for the displayed records and respond accordingly, for example enabling and coloring a button:

$.get("<%=availability_catalog_path%>?mms_ids=" + mms_ids,
    function(data, status) {
        for (var mms_id in data) {
            var availability = data[mms_id];
            $('#physical-' + mms_id).toggleClass(function() {
                if (!availability.physical.exists) {
                    return "disabled";
                } else if (availability.physical.available) {
                    return "btn-default btn-success";
                } else {
                    return "btn-default btn-warning";
                }
            });
            $('#online-' + mms_id).toggleClass(function() {
                if (!availability.online.exists) {
                    return "disabled";
                } else {
                    return "btn-default btn-success";
                }
            });
        }
});

The result is a display sensitive to the availability of the resource.

Single Sign On via SAML

Now that we can display links depending on a resource’s availability, we want to integrate with our institution’s single sign on (SSO) system. This will allow users to see personalized options in the fulfillment services page (Get It tab). These personalized options might include request types or displaying online resources limited by access rights. This integration involves 4 steps- configuring the SAML identity provider, configuring Alma, configuring the application, and putting it together when displaying the Get It tab.

SAML IdP

Alma supports SAML for SSO, so we need a SAML 2.0-compliant identity provider. Many organizations use Shibboleth. In this example, we use OneLogin, an online service. We created an account in OneLogin, added a user, and created 2 applications- one for Alma and one for our catalog app.

Configuration in Alma

We then configure Alma with an integration profile for SAML, as described here. This allows Alma to authenticate with OneLogin as a SAML provider.

Application Configuration

In order for the single sign on to work smoothly, we need our application to authenticate against the same identity provider. This ensures that when a user is logged in to our application, he will be logged into Alma for the purpose of displaying the Get It tab.
In our Ruby application, we use the omniauth-saml gem by PracticallyGreen. This gem provides all of the interaction with the SAML IdP, and allows for relatively painless integration. We do some minor configuration in the omniauth.rb initializer to hook up to our OneLogin SAML provider:
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :saml,
    :issuer                             => "my-alma-rails-library",
    :idp_sso_target_url                 => "https://exlibris.onelogin.com/trust/saml2/http-post/sso/458700",
    :idp_cert_fingerprint               => "A5:4A:77:86:60:B8:19:E4:62:F5:83:F8:83:64:06:E0:5A:AC:4C:54",
    :name_identifier_format             => "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
end
Once this is configured, we’re able to log in to our application using OneLogin. We match on the user ID and get the user’s name from the SAML response.

Putting it Together

So now we have both our application and Alma integrated with the same SAML identity provider so a user can be seamlessly logged in to both. Now we have to display the Get It tab with a reference to SSO depending on whether the user is logged in to our app via SAML.The two relevant parameters are documented here: sso=true and a token to prevent cross-session contamination in case a user doesn’t close his browser on a shared machine.
When we determine the link for the openurl which displays the Get It tab, we check if the user is logged in via SAML and add the parameters accordingly:
def openurl
   "https://#{ENV['alma']}.alma.exlibrisgroup.com/view/uresolver/#{ENV['institution']}/openurl?" +
      (current_user && current_user.provider=='saml' ? "sso=true&token=#{session.id}&" : "") 
end
Now if we’re not logged in, we see a Get It tab without request options.
And if we’re logged in, we see additional options.
That’s all there is to it! The code for this example is available in this repository.
Github

Leave a Reply