Log into external services with RERO ILS (OAuth)

  • api
Last updated: 07-07-2026

RERO ILS lets external services (resource providers, partner applications…) authenticate library users via OAuth 2.0 and retrieve a limited set of information about them.

RERO ILS acts as the authorization server and the resource server, your application is the client. For the protocol itself, see OAuth, RFC 6749 or Wikipedia.

1. Overview

RERO ILS uses the Authorization Code flow, in three steps:

RERO ILS OAuth 2.0 "Authorization Code" flow

  1. Authorization - you redirect the user to the authorization endpoint; they log in and approve (or refuse) the requested data. RERO ILS sends them back to your redirect_uri with a single-use authorization code.
  2. Token - your server exchanges this code (together with your client_secret) for an access_token and a refresh_token.
  3. Resource - you use the access_token to query /api/patrons/info.

⚠️ Steps 2 and 3 run server-side: the client_secret and the tokens must never reach the browser or a mobile application.

2. Endpoints

Responses in JSON, over HTTPS only.

Purpose Method URL
Authorization GET https://bib.rero.ch/oauth/authorize
Token (exchange + refresh) POST https://bib.rero.ch/oauth/token
User information GET https://bib.rero.ch/api/patrons/info

To test without affecting production, replace bib.rero.ch with bib.test.rero.ch in every example.

3. Token lifetimes

Token Validity Notes
authorization_code a few dozen seconds single use: exchange it immediately
access_token 1 hour for API calls
refresh_token long-lived to renew an expired access_token

Only one set of tokens is active per application and per user. Issuing a new token invalidates the previous one: keep only the latest one received.

4. Registering an application

  1. On bib.rero.ch, create an account (My account > Sign up) with a working, unique e-mail address; it will be shown to the users of your service.
  2. Log in, then go to Applications and choose New application.
  3. Declare one or more redirect URIs (see below) and note your client_id and client_secret.

redirect_uri: the one sent during authorization must match exactly a registered URI (scheme, domain, path, parameters). Any difference (trailing slash, http/https, subdomain) causes an invalid_request error.

5. Testing the connection

If you are commissioned by a library, ask them for a test patron account and for the criteria that do or do not allow the connection (typically institution, expiration_date, patron_type).

A plain site account (step 4) is not enough: until it is linked to a registered patron, the response does not contain the patron_info block and therefore does not let you test those criteria.

6. Step 1: Get an authorization code

Redirect the user to the authorization endpoint:

Parameter Required Value Description
response_type yes code fixed value
client_id yes identifier your application identifier
redirect_uri yes URL must match a registered URI
scope yes scopes requested data, space-separated (at least one)
state recommended opaque string anti-CSRF value to verify on return
GET https://bib.rero.ch/oauth/authorize?
    response_type=code&
    client_id={CLIENT_ID}&
    redirect_uri=https://your-domain.ch/oauth/callback&
    scope=fullname%20institution%20expiration_date%20patron_type&
    state={RANDOM_VALUE}

Scopes are separated by a space (encoded %20 or + in the URL), never by a comma.

Scopes

Three fields are always returned, without any scope:

  • user_id - unique technical identifier. Use it only for users not linked to a library.
  • patron_info.{institution}.patron_pid - the user's identifier in each institution where they are registered (present only for a registered patron).
  • barcode - deprecated, do not use.

Then request one or more scopes (at least one required):

Scope Returned data
fullname Last and first name (format Last, First)
birthdate Date of birth (YYYY-MM-DD)
institution Code of the institutions where the user is registered
expiration_date Registration expiration date, per institution (ISO 8601)
patron_type Code of the patron type (string defined by the library, e.g. "vs-pm"). This code is specific to each institution and optional: the field is absent if no code is defined.

The patron_types scope (plural) is deprecated. Use the patron_info format.

7. Step 2: Exchange the code for a token

RERO ILS redirects the user to your redirect_uri with the code (and the state):

GET https://your-domain.ch/oauth/callback?code={CODE}&state={RANDOM_VALUE}

Verify the state, then exchange the code immediately, server-side:

POST https://bib.rero.ch/oauth/token
Content-Type: application/x-www-form-urlencoded

client_id={CLIENT_ID}
&client_secret={CLIENT_SECRET}
&grant_type=authorization_code
&code={CODE}
&redirect_uri=https://your-domain.ch/oauth/callback

Common mistake: the body must be a form (application/x-www-form-urlencoded, or multipart/form-data as a fallback), never JSON, and the redirect_uri must be identical to the one from step 1.

Response:

{
    "access_token": "4NPtBhoiBmML6k7cDe9RdcrXrHl7XR",
    "expires_in": 3600,
    "token_type": "Bearer",
    "scope": "fullname birthdate institution expiration_date patron_type",
    "refresh_token": "iic37JVAq71uLDu3jzHWdT958qh01D"
}
Parameter Description
access_token access token for API calls
expires_in validity in seconds (3600 = 1 h)
token_type Bearer (only value used)
scope scopes actually granted
refresh_token refresh token (see "Refreshing an expired access token")

8. Step 3: Retrieve the user information

Query /api/patrons/info with the access_token, either via a header (recommended) or a parameter:

GET https://bib.rero.ch/api/patrons/info
Authorization: Bearer {ACCESS_TOKEN}
GET https://bib.rero.ch/api/patrons/info?access_token={ACCESS_TOKEN}

Example for a user registered in two institutions (vs and rbnj), all scopes granted:

{
    "user_id": 7653,
    "fullname": "Ziegler, Jean",
    "birthdate": "1934-04-19",
    "barcode": "xxxxxxxxxxx",
    "patron_info": {
        "vs": {
            "patron_pid": "316784",
            "institution": "vs",
            "patron_type": "vs-pm",
            "expiration_date": "2027-03-30T00:00:00"
        },
        "rbnj": {
            "patron_pid": "876",
            "institution": "rbnj",
            "expiration_date": "2029-08-24T00:00:00"
        }
    }
}
  • Only the fields of the granted scopes appear; fields without a value are omitted (here, rbnj has no patron_type).
  • patron_info is indexed by institution code: iterate over all entries, as a user may belong to several institutions.
  • patron_info is absent if the account is not linked to a registered patron (see "Testing the connection").
  • A client library must tell you which criteria (institution, expiration, type…) grant access to your service.

9. Refreshing an expired access token

Renew the access_token without re-authorizing the user, via a POST form:

POST https://bib.rero.ch/oauth/token
Content-Type: application/x-www-form-urlencoded

client_id={CLIENT_ID}
&client_secret={CLIENT_SECRET}
&grant_type=refresh_token
&refresh_token={REFRESH_TOKEN}

The response has the same structure as in step 2. A new refresh_token may be returned: always keep the latest one. If the refresh_token is no longer valid, restart the flow from step 1 ("Get an authorization code").

User refusal: if the user refuses on the authorization screen, RERO ILS redirects to your redirect_uri with error instead of code. Detect this case and do not call the token endpoint:

GET https://your-domain.ch/oauth/callback?error=access_denied&state={RANDOM_VALUE}

On the authorization endpoint (redirect with error / error_description, RFC 6749 §4.1.2.1):

error Likely cause
access_denied the user refused
invalid_request missing parameter or non-conforming redirect_uri
unauthorized_client unknown or unauthorized client_id
invalid_scope nonexistent or unauthorized scope
unsupported_response_type response_typecode

On the token endpoint (JSON, HTTP 4xx, RFC 6749 §5.2):

error Likely cause
invalid_grant code expired, already used, or different redirect_uri
invalid_client incorrect client_id / client_secret
unsupported_grant_type unsupported grant_type
invalid_request malformed body (e.g. JSON instead of a form)

On /api/patrons/info - 401: token missing, invalid or expired; 403: required scope not granted.

11. Logout and revocation

There is no token revocation endpoint (/oauth/revoke) nor any OAuth logout via API. Invalidation relies on:

  • Expiration - the access_token expires after 1 h; not renewing it lets access end when the refresh_token expires.
  • Client-side - ending the session in your application is your responsibility (delete the stored token); no call to RERO ILS is required.
  • User revocation - from their account, under Applications; your subsequent calls then receive a 401.
  • Rotation - re-authorizing the user issues a new set of tokens and invalidates the previous one.

Ending the RERO ILS session (Single Sign-Out)

To also close the user's browser session on RERO ILS (so that the next authorization prompts for their credentials again), redirect them from your own logout to:

GET https://bib.rero.ch/signout/
  • This route closes the browser session but does not revoke the OAuth tokens already issued (delete them on your side).
  • No automatic return to your site: the ?next= parameter only accepts URLs on the bib.rero.ch domain; any external URL is ignored and the user lands on the RERO ILS home page.

12. Security best practices

  • HTTPS everywhere, including your redirect_uri.
  • Secret and tokens server-side only - never in a browser or a mobile app.
  • state - generate a random value, store it in the session and verify it on return (anti-CSRF).
  • Authorization code - exchange it right away; do not log it, do not reuse it.
  • Least privilege - request only the scopes you need.
  • Storage - tokens encrypted at rest, restricted access, latest set only.

13. FAQ

patron_info is missing from the response. - The account is not linked to a registered patron; only user_id (and possibly barcode) are returned. Ask for a test patron account (see "Testing the connection").

An expected field (e.g. patron_type) is missing. - Either the scope was not granted, or the data does not exist for this user.

The token endpoint returns invalid_request / invalid_grant. - Check: body as x-www-form-urlencoded (not JSON), redirect_uri identical to step 1, code not expired or already used.

redirect_uri_mismatch at authorization. - The redirect_uri does not exactly match a registered URI (trailing slash, subdomain, http/https).

My old tokens no longer work after a new login. - This is normal: only one set of tokens is active per application and per user.

How do I log the user out or revoke a token via API? - See "Logout and revocation".


Interoperability applications | Access MARC data (SRU)