This library is a wrapper around the Web Service Authentication system used by OCLC web services, written for Python. It works with versions 2.7 and 3 (up to 3.6)
The easiest way to install is via pip:
pip install git+git:https://github.com/OCLC-Developer-Network/oclc-auth-python
Alternatively, clone the repository:
git clone https://github.com/OCLC-Developer-Network/oclc-auth-python.git
Install the library:
sudo python setup.py install
-
Change directories to
examples/hmac_authentication
-
Edit
hmac_request_example.py
to insert your:- key
- secret
- principal_id
- principal_idns
- authenticating_institution_id
-
Run from the command line:
python hmac_request_example.py
You should get back an XML result if your WSKey is configured properly.
<?xml version="1.0" encoding="UTF-8"?> <entry xmlns="http://www.w3.org/2005/Atom"> <content type="application/xml"> <response xmlns="http://worldcat.org/rb" mimeType="application/vnd.oclc.marc21+xml"> <record xmlns="http://www.loc.gov/MARC21/slim"> <leader>00000cam a2200000Ia 4500 ...
-
Change directories to
examples/client_credentials_grant
-
Edit
client_credentials_grant.py
to insert your:- key
- secret
- authenticating_institution_id
- context_institution_id
-
Run from the command line:
python client_credentials_grant.py
You should get back an access token if your WSKey is configured properly.
access token: tk_xxx5KWq9w1Cc0dc5MrvIhFvdEZteylgsR7VT expires_in: 1199 expires_at: 2014-09-09 15:22:49Z type: bearer
Or an error message if the key is not configured properly
error_code: 401 error_message: HTTP Error 401: Unauthorized error_url: https://authn.sd00.worldcat.org/oauth2/accessToken? grant_type=client_credentials& authenticatingInstitutionId=128807& contextInstitutionId=128807& scope=WorldCatDiscoveryAPI
This example demonstrates how to retrieve an access token, and has the following features:
- Provides a basic HTTPS server
- Redirects a user to authenticate to retrieve an Access Code
- Uses the Access Code to retrieve an Access Token
- Stores the Access Token in a Session and manages a list of sessions using a simple flat file.
- Uses the Access Token to request a Bibliographic Record from OCLC.
To use the example:
-
Change directories to
examples/authentication_token
-
Edit server.py to insert your WSKey parameters:
KEY = '{clientID}' SECRET = '{secret}'
-
From the command line:
python server.py
-
Navigate your browser to:
https://localhost:8000/auth/
Do not be concerned about "security warnings" - click through them. That is expected with the supplied, unsigned CACERT in server.pem. In production, you will use your institution's signed CACERT when implementing SSL.
For performing client side authentication using Access Tokens, we prepared an example using a popular framework, Django. We show how to set up a simple Django App and implement SSL on the localhost for testing.
First, we need to install these dependencies:
-
Change directories to
examples/djangoProject
. -
Install
pip
if you have not already - pip. -
Install Django (see Django Installation Guide).
sudo pip install django
-
To run SSL from localhost, install a django-sslserver.
sudo pip install django-sslserver
An alternate method popular with Django developers is to install Stunnel.
Note: if running stunnel, you should edit
djangoProject/settings.py
and remove the reference to sslserver:INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'exampleAuthTokenDjangoApp', 'sslserver', # remove if using Stunnel )
-
Edit
djangoProject/views.py
and insert your Key and Secret. Note that your WSKey must be configured with these parameters:- RedirectURI that matches the URI you are running the example from. For example, https://localhost:8000/auth/
- Scopes. ie, WorldCatMetadataAPI for the Django example provided with this library.
-
Use runsslserver to start Django's SSL server from the
examples/authentication_token_with_django
directory:python manage.py runsslserver
-
Direct your browser to
https://localhost:8000/auth/
. -
If all goes well, you should see some authentication warnings (that's expected - because runsslserver uses a self-signed CACERT). Click through the warning messages and you should see an authentication screen.
- Sign in with your userId and Password
- When prompted to allow access, click yes
You should see your access token details and a sample Bibliographic record, in XML format.
Authentication for server side requests uses HMAC Signatures. Because this pattern uses a secret and a key, it is never meant for client-side use. HMAC Signatures are discussed in detail at OCLC Developer Network - Authentication.
To use the authliboclc
library to create a HMAC Signature, include the following libraries in your Python script:
from authliboclc import wskey from authliboclc import user import urllib2
You must supply authentication parameters. OCLC Web Service Keys can be requested and managed here.
key = '{clientID}' secret = '{secret}' principal_id = '{principalID}' principal_idns = '{principalIDNS}' authenticating_institution_id = '{institutionID}'
Construct a request URL. See OCLC web services documentation. For example, to request a Bibliographic Record:
request_url = 'https://worldcat.org/bib/data/823520553?classificationScheme=LibraryOfCongress&holdingLibraryCode=MAIN'
Construct the wskey and user objects.
my_wskey = wskey.Wskey( key=key, secret=secret, options=None ) my_user = user.User( authenticating_institution_id=authenticating_institution_id, principal_id=principal_id, principal_idns=principal_idns )
Note that the options parameter is for access token use and you do not need to add them for this example. For details, see the wskey.py file in the authliboclc library folder.
Calculate the Authorization header:
authorization_header = my_wskey.get_hmac_signature( method='GET', request_url=request_url, options={ 'user': my_user, 'auth_params': None} )
With our request URL and Authorization header prepared, we are ready to use Python's urllib2 library to make the GET request.
my_request = urllib2.Request( url=request_url, data=None, headers={'Authorization': authorization_header} ) try: xmlresult = urllib2.urlopen(myRequest).read() print(xmlresult) except urllib2.HTTPError, e: print ('** ' + str(e) + ' **')
You should get a string containing an xml object, or an error message if a parameter is wrong or the WSKey is not configured properly.
The imports for working with the authentication library inside a Django view look like this:
from django.http import HttpResponse from authliboclc import wskey import urllib2
The authentication pattern is described in detail on the OCLC Developer Network. More specifically, we implemented the Explicit Authorization Code pattern in the authliboclc library.
An Authorization Code is a unique string which is returned in the url after a user has successfully authenticated. The Authorization Code will then be exchanged by the client to obtain Access Tokens:
-
You need to gather your authentication parameters:
- key
- secret
- context_institution_id
- authenticating_institution_id
- services (api service name, ie
WorldCatMetadataAPI
for the Metadata API - redirect_uri (where your app runs on the web, i.e.
https://localhost:8000/auth/
-
Create a wskey object:
myWskey = wskey.Wskey( key=key, secret=secret, options={ 'services': ['service1' {,'service2',...} ], 'redirect_uri': redirect_uri } )
-
Generate a login URL and redirect to it:
login_url = myWskey.get_login_url( authenticating_institution_id='{your institutionId}', context_institution_id='{your institutionId}' ) response['Location'] = login_url response.status_code = '303'
-
The user will be prompted to sign in with a UserId and Password. If they authenticate successfully, you will receive back a url with a code parameter embedded in it. Parse out the code parameter to be used to request an Access Token.
An Access Token is a unique string which the client will send to the web service in order to authenticate itself. Each Access Token represents a particular application’s right to access set of web services, on behalf of a given user in order to read or write data associated with a specific institution during a specific time period.
This library function takes the code and makes the Access Token request, returning the Access Token object.
access_token = myWskey.get_access_token_with_auth_code(
code=code,
authenticating_institution_id='128807',
context_institution_id='128807'
)
The access token object has these parameters:
- accessTokenString
- type
- expiresAt (ISO 8601 time)
- expiresIn (int, seconds)
- user
- principal_id
- principal_idns
- authenticating_institution_id
- context_institution_id
- errorCode
If you include refresh_token as one of the services, you will also get back a refresh token:
- refreshToken
- refreshToken (the string value of the token)
- expiresAt (ISO 8601 time)
- expiresIn (int, seconds)
Our access token has a user object which contains a principalID and principalIDNS. We can use those parameters to make a Bibliographic Record request. For example, let's retrieve the record for OCLC Number 823520553:
request_url = ( 'https://worldcat.org/bib/data/823520553?' + 'classificationScheme=LibraryOfCongress' + '&holdingLibraryCode=MAIN' )
Now we construct an authorization header using our Access Token's user parameter:
authorization_header = wskey.get_hmac_signature( method='GET', request_url=request_url, options={ 'user': access_token.user } )
Finally, we make the request:
myRequest = urllib2.Request( url=request_url, data=None, headers={'Authorization': authorization_header} ) try: xmlResult = urllib2.urlopen(myRequest).read() except urllib2.HTTPError, e: xmlResult = str(e)