The OAuth protocol enables websites or applications (Consumers) to access Protected Resources from Web services (Service Providers) via an API, without requiring Users to disclose their Service Provider credentials to those Consumers. More generally, OAuth creates a freely-implementable and generic methodology for API-oriented authentication.
For Consumer developers, OAuth is a method to publish and interact with protected data.
For Service Provider developers, OAuth gives users access to their data while protecting their account credentials.
One use case would be allowing a printing service, printer.example.com (the Consumer), to access private photos stored on photos.example.net (the Service Provider), without requiring Users to reveal their photos.example.net credentials to printer.example.com.
OAuth allows the user to selectively grant access to their private resources housed on one site (called the Service Provider), to another site (called the Consumer). In other words, OAuth enables you to grant access to some of your information without sharing all of your identity.
OAuth does not require a specific user interface or interaction pattern, nor does it specify how Service Providers authenticate Users, making the protocol ideally suited for cases where authentication credentials are unavailable to the Consumer, such as with OpenID.
OAuth aims to unify the experience and implementation of delegated web service authentication with a single, community-driven protocol. OAuth builds on existing protocols and best practices that have been independently implemented by various websites. An open standard, supported by large and small providers alike, promotes a consistent and trusted experience for both application developers and the users of those applications.
What is publicly known as "OAuth" is really the "OAuth Core 1.0" specification. The "Core" designation is used to stress that this is the skeleton upon which other extensions and protocols may be built. OAuth Core 1.0 does NOT by itself provide many desired features such as automated discovery of endpoints, language support, support for XML-RPC and SOAP, standard definition of resource access, OpenID integration, a full range of signing algorithms, or any number of other great ideas posted to the OAuth group.
This was intentional and is viewed by the authors as a benefit. As the name implies, Core deals only with the most fundamental aspects of the protocol:
More details can be found here.
Credentials bearing tokens enable a user to provide their credentials in tokenized form in cases where HTTP redirection to a browser plus human interaction is unavailable or unsuitable. For example, intermediary intelligent agents, mobile phones, or set-top devices.
To request an Access Token in this model, the Consumer makes an HTTP request to the Service Provider's Access Token URL. The authentication request contains [nine] parameters contained in the HTTP Authorization header or as URL parameters. Parameter names and values must be "percent-encoded" to handle characters in different character sets. The request should be performed using TLS, and should use HTTP POST.
Before granting an access token, the Service Provider must ensure that the request signature has been successfully verified as per OAuth, that a request with the supplied timestamp and nonce has never been received before, and that the supplied username and password match a User's credentials. If successful, the Service Provider generates an Access Token and Token Secret using a 200 Ok response and returns them in the HTTP response body.
After successfully receiving the Access Token and Token Secret, the Consumer is able to access the Protected Resources on behalf of the User as per section 7 of the OAuth core specification. In other words, the Access Token obtained here is no different in capability to the Access Token specified by OAuth. Once authenticated using the above process, the Consumer will sign all subsequent requests for the User's Protected Resources using the returned Token Secret.
Virtuoso implements the OAuth Core 1.0 specification, and exposes the following API endpoints:
Endpoint:
http://server-cname/OAuth/request_token
Parameters:
Request:
http://localhost:8890/OAuth/request_token?oauth_version=1.0&oauth_nonce =dad4cb071e2169cbcaa051d404ac61a3&oauth_timestamp=1201873644&oauth_cons umer_key=f756023be5ff1f20881cf8fe398069f3976b2304&oauth_signature_metho d=HMAC-SHA1&oauth_signature=z76k5fQ0msFsQzCmhO%2FJZ329ZUE%3D
Note: all long lines in example texts are split, i.e., the GET request is single line.
Response:
oauth_token=b4e22daa117b0bebf60ab6ba6e401edc7addd78c&oauth_token_secret =4de6e3ab17553a0a385ebf6a3b4dd30f
Endpoint:
http://server-cname/OAuth/authorize
Parameters:
Request:
http://localhost:8890/OAuth/authorize?oauth_token=b4e22daa117b0bebf60ab 6ba6e401edc7addd78c&oauth_callback=http%3A%2F%2Flocalhost%3A8890%2Foaut h%2Fexample%2Fclient.php%3Fkey%3Df756023be5ff1f20881cf8fe398069f3976b23 04%26secret%3Dcc249bfb732039d8ecba9e4f94fdead7%26token%3Db4e22daa117b0b ebf60ab6ba6e401edc7addd78c%26token_secret%3D4de6e3ab17553a0a385ebf6a3b4 dd30f%26endpoint%3Dhttp%253A%252F%252Flocalhost%253A8890%252FOAuth%252F authorize
The User will be asked via web page to accept or decline the token.
Endpoint:
http://server-cname/OAuth/access_token
Parameters:
Request:
http://localhost:8890/OAuth/access_token?oauth_version=1.0&oauth_nonce= 8ad75091a66bdd741472be42149c828e&oauth_timestamp=1201873800&oauth_consu mer_key=f756023be5ff1f20881cf8fe398069f3976b2304&oauth_token=b4e22daa11 7b0bebf60ab6ba6e401edc7addd78c&oauth_signature_method=HMAC-SHA1&oauth_s ignature=tCxy0Lod4%2Bp%2FCBPV7Ph7RrsHXe4%3D
Response:
oauth_token=8c03b3da93480ca4728cc1194d6d03962f3bb5bb&oauth_token_secret =854fd29c00adcedff4fbeaeb96584911
In addtion to the endpoints it define a API for PL applications to check authentication:
OAUTH.DBA.check_authentication (in params any, in lines any)
Parameters:
Result:
A sample service (oauth.vsp):
<html> <body> <?vsp OAUTH..check_authentication (params, lines); ?> An OAuth testing page </body> </html>
http://localhost:8890/admin/oauth.vsp?oauth_version=1.0&oauth_nonce=d57 640869b994b2d51bf9800229c4997&oauth_timestamp=1201873935&oauth_consumer _key=f756023be5ff1f20881cf8fe398069f3976b2304&oauth_token=8c03b3da93480 ca4728cc1194d6d03962f3bb5bb&oauth_signature_method=HMAC-SHA1&oauth_sign ature=X3K4lr9bJVz5YLnnyJDkykQZivY%3D
http://localhost:8890/admin/oauth.vsp?oauth_version=1.0&oauth_nonce=d57 640869b994b2d51bf9800229c4997&oauth_timestamp=1201873935&oauth_consumer _key=f756023be5ff1f20881cf8fe398069f3976b2304&oauth_token=8c03b3da93480 ca4728cc1194d6d03962f3bb5bb&oauth_signature_method=HMAC-SHA1&oauth_sign ature=X3K4lr9bJVz5YLnnyJDkykQZivY%3D
<html> <body> An OAuth testing page </body> </html>
OAuth tokens must be generated for each user account, for each ODS application, via ODS -> Settings -> OAuth Keys. This UI provides a list of all applications to which the logged-in user has access, i.e., of which the user is a member or owner. To enable access with OAuth, the user simply selects the desired application instance from the list, and clicks the 'generate keys' button. The generated Consumer Key and Secret will be associated with the given ODS user account & application instance.
Once a consumer token is available, the sequence below must be executed in order to establish an authorized session:
To demonstrate the Virtuoso implementation of OAuth, we have written this sample client, in Virtuoso/PL.
<html> <?vsp declare consumer_key, consumer_secret, oauth_token, oauth_secret, signature, timest, nonce varchar; declare srv, res, signature_base, ret_url, url, tmp, sid varchar; declare meth, pars any; consumer_key := {?'key'}; srv := sprintf ('http://localhost:%s/OAuth/', server_http_port ()); sid := null; res := ''; sid := {?'sid'}; if (sid = '') sid := null; else { -- if selected token is not same as one from the session we need to get new authentication token if (consumer_key <> OAUTH..get_consumer_key (sid)) { OAUTH..session_terminate (sid); sid := null; } } meth := get_keyword ('meth', params, 'weblog.post.new');; pars := get_keyword ('pars', params, 'inst_id=15&title=testing&description=Some test post');; if ({?'rt'} is not null and sid is null) -- request new token for the session { url := srv||'request_token'; url := OAUTH..sign_request ('GET', url, '', consumer_key, sid); res := http_get (url); sid := OAUTH..parse_response (sid, consumer_key, res); OAUTH..set_session_data (sid, params); ret_url := sprintf ('http://localhost:%s/oauth/oauth_client.vsp?ready=%U', server_http_port (), sid); -- call authorize url := sprintf ('%sauthorize?oauth_token=%U&oauth_callback=%U', srv, OAUTH..get_auth_token (sid), ret_url); http_status_set (301); http_header (sprintf ('Location: %s\r\n', url)); return; } else if ({?'ready'} is not null) -- get access token { -- we go here when token above is authorized sid := {?'ready'}; url := srv||'access_token'; consumer_key := OAUTH..get_consumer_key (sid); url := OAUTH..sign_request ('GET', url, '', consumer_key, sid); res := http_get (url); sid := OAUTH..parse_response (sid, consumer_key, res); } if (sid is not null) -- access token is ready, and we can call API { -- here we are ready to call service if ({?'rt'} is null) { tmp := OAUTH..get_session_data (sid); pars := get_keyword ('pars', tmp, pars); meth := get_keyword ('meth', tmp, meth); } url := sprintf ('http://localhost:%s/ods/api/%s', server_http_port (), meth); tmp := split_and_decode (pars); params := ''; for (declare i,l int, l:=length (tmp); i < l; i := i + 2) { params := params || sprintf ('%U=%U&', tmp[i], tmp[i+1]); } --params := sprintf ('inst_id=%d&description=%U&title=%U', 15, 'Some test post', 'testing'); consumer_key := OAUTH..get_consumer_key (sid); url := OAUTH..sign_request ('GET', url, params, consumer_key, sid); res := http_get (url); --dbg_obj_print (res); } ?> <head><title>OAuth Client</title></head> <body> <h1>OAuth client for ODS Controllers</h1> <form method="POST" action="oauth_client.vsp"> <input type="hidden" name="sid" value="<?V sid ?>"/> APPLICATION : <br /> <select name="key"> <?vsp for select a_name, a_key from OAUTH..APP_REG do { ?> <option value="<?V a_key ?>" <?vsp if (consumer_key = a_key) http ('selected'); ?>><?V a_name ?></option> <?vsp } ?> </select> <?vsp if (sid is not null) http (sprintf (' TOKEN: %s', OAUTH..get_auth_token (sid))); ?> <br /> ODS API: <br /><input type="text" name="meth" value="<?V meth ?>" size=50/> <br /> PARAMETERS: <br /> <textarea name="pars" rows="5" cols="50"><?V pars ?></textarea> <br /> <input type="submit" value="Execute" name="rt"/><br /> </form> RESULT: <hr/> <pre><?V res ?></pre> </body> </html>
The following shows a sample session, using the above Virtuoso/PL OAuth client.
GET /OAuth/request_token?oauth_consumer_key=50082d0fb861b0e6e67d5d986b8 333607edc5f36&oauth_nonce=b8f1089077cbce6e&oauth_signature_method=HMAC- SHA1&oauth_timestamp=1211212829&oauth_version=1.0&oauth_signature=V1zmk 757LBHcmqVJ6obMhNX5hKA%3D HTTP/1.1 Host: localhost:6666 HTTP/1.1 200 Ok Content-Length: NNN <CR/LF> oauth_token=86da75079d3aee0fab57a36fcffbf900768e4de3&oauth_token_secret =M...
GET /OAuth/authorize?oauth_token=86da75079d3aee0fab57a36fcffbf900768e4d e3&oauth_callback=http%3A//localhost%3A6666/oauth/oauth_client.vsp%3Fre ady%3D00c874b2fab2f6424008b5064fe83e88 HTTP/1.1 Host: localhost:6666 HTTP/1.1 301 Moved Location: /ods/oauth_authorize.vspx?....
GET /OAuth/access_token?oauth_consumer_key=50082d0fb861b0e6e67d5d986b83 33607edc5f36&oauth_nonce=242cc4875a0059f6&oauth_signature_method=HMAC-S HA1&oauth_timestamp=1211212831&oauth_token=86da75079d3aee0fab57a36fcffb f900768e4de3&oauth_version=1.0&oauth_signature=sqs/8nmNNnNJiZ/eBa688uNe g9o%3D HTTP/1.1 Host: localhost:6666 HTTP/1.1 200 Ok Content-Length: NNN <CR/LF> oauth_token=N..&oauth_token_secret=M...
GET /ods/api/weblog.post.new?description=Some%20test%20post&inst_id=15& oauth_consumer_key=50082d0fb861b0e6e67d5d986b8333607edc5f36&oauth_nonce =2f4765d20664e696&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1211 213321&oauth_token=db83a37d74faf53edc8ed56d418ded3a70fcc0bc&oauth_versi on=1.0&title=testing&oauth_signature=oocIyr6kgoEQkC3WVwzvl6w62W4%3D HTT P/1.1 Host: localhost:6666 HTTP/1.1 200 Ok Content-Length: NNN <CR/LF> <result><code>1</code></result>
The following steps describe how to Setup Application OAuth keys in ODS:
![]() |
Figure: 15.4.4.1. OAuth Generate Keys |
![]() |
Figure: 15.4.4.1. OAuth Generate Keys |
ODS provides Ubiquity commands to manipulate user accounts as well as instances and instance specific data using the ODS Controllers API. This command set is available only for the Firefox browser with the Ubiquity extension installed.
First, the Ubiquity Firefox extension must be installed. Then, ODS Ubiquity commands can be installed by accessing http://host:port/ods/ods_ubiquity.html page. Ubiquity commands are accessed by the ctrl-space key combination.
Assuming the OAuth endpoint: http://myopenlink.net/OAuth, in order to change it use the command:
Syntax: ods-oauth-host <host_url> Example: ods-oauth-host http://demo.openlinksw.com/OAuth
There are two command modes available to ubiquity commands when working against an ODS instance: oauth or sid.
In OAuth mode, for every ODS application instance, an OAuth key must be obtained and then initialized via the following steps:
http://myopenlink.net/ods/oauth_sid.vsp
If you choose the SID mode of interaction with ODS you have to perform the following steps:
Note: The sid is a session ID applicable to all ODS commands for a given bound instance and user combination. It's obtained from an ODS session.
The following example demonstrates oauth authentication getting the OAuth SID value for ex. for existing Bookmark instance "mybookmarks" with owner user demo at the OpenLink Demo server.
In order to execute correctly the example, you need to have OAuth Generate Key for the Bookmark "mybookmarks" instance at OpenLink Demo server. More information and simple scenario how to be done you can find here.
ods-oauth-host <host_url> -- for ex.: ods-oauth-host http://demo.openlinksw.com/OAuth
![]() |
Figure: 15.4.5.2.3.1. OAuth Authentication |
ods-set-mode oauth
![]() |
Figure: 15.4.5.2.3.1. OAuth Authentication |
![]() |
Figure: 15.4.5.2.3.1. OAuth Authentication |
![]() |
Figure: 15.4.5.2.3.1. OAuth Authentication |
![]() |
Figure: 15.4.5.2.3.1. OAuth Authentication |
![]() |
Figure: 15.4.5.2.3.1. OAuth Authentication |
![]() |
Figure: 15.4.5.2.3.1. OAuth Authentication |
ods-set-sid 7ef4dcf23869488823b771b09b952cc9 or ods-set-addressbook-oauth 7ef4dcf23869488823b771b09b952cc9
![]() |
Figure: 15.4.5.2.3.1. OAuth Authentication |
ods-set-briefcase-oauth <the obtained oauth session-key> -- or ods-set-bookmark-oauth <the obtained oauth session-key> -- or ods-set-feeds-oauth <the obtained oauth session-key> -- or ods-set-calendar-oauth <the obtained oauth session-key> -- or ods-set-addressbook-oauth <the obtained oauth session-key> -- or ods-set-poll-oauth <the obtained oauth session-key> -- or ods-set-weblog-oauth <the obtained oauth session-key> -- or ods-set-discussion-oauth <the obtained oauth session-key>
the Virtuoso SPARQL OAuth Tutorial and the full list of ODS Application Authentication Examples using OAuth
the full list of ODS Ubiquity Commands and the full list of OpenLink Data Spaces (ODS) Ubiquity Commands Tutorials
The ODS OAuth Test Tool creates examples to show users the correct format for constructing HTTP requests signed according to OAuth specifications. The users use this format in their applications to make successful requests to the ODS REST APIs.
The ODS users generate a Consumer Key and a Consumer Secret for their application instances by ODS application UI (Setings -> OAuth Keys). You can find more information and sample scenario here.
To reach a specific ODS resource via the ODS REST API, a user must also specify a API method and associated API parameters.
ODS OAuth standards validate the credentials of an external user by means of the digital signature. If the user signs the request, and the ODS server validates the digital signature, the developer is granted access to the requested resource.
To tool is accessible via http:/host:port/ods/oauth_test.vsp
The following example demonstrates creating and getting contact info by the ODS REST APIs weblog.post.new and weblog.post.get using the OAuth Test Tool.
![]() |
Figure: 15.4.6.1.1. Weblog OAuth |
150fd483a3219e09847676deebae6c725d5a0a03
inst_id=44&description=my test&title=my first post
ods-host http://demo.openlinksw.com/ods ods-set-mode sid ods-authenticate-user demo password demo ods-get-instance-id demo's Weblog
![]() |
Figure: 15.4.6.1.1. Weblog OAuth |
![]() |
Figure: 15.4.6.1.1. Weblog OAuth |
![]() |
Figure: 15.4.6.1.1. Weblog OAuth |
![]() |
Figure: 15.4.6.1.1. Weblog OAuth |
In order to use the MySpace OAuth Testing Tool:
Google's OAuth playground tool can be tried here.
In order to use the tool, you need to register the web application as domain:
Note: for now registered domains cannot be deleted (not supported from the Google UI)
![]() |
Figure: 15.4.7.2.1.1. Google OAuth |
![]() |
Figure: 15.4.7.2.1.1. Google OAuth |
OAuth Consumer Key: ec2-67-202-42-146.compute-1.amazonaws.com OAuth Consumer Secret: uEkfBvpMhTTT/VyFItEnEYt4
![]() |
Figure: 15.4.7.2.1.1. Google OAuth |
![]() |
Figure: 15.4.7.2.1.1. Google OAuth |
Let's try the playground tool:
![]() |
Figure: 15.4.7.2.2.1. Google OAuth |
GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key %3Dec2-67-202-42-146.compute-.amazonaws.com%26oauth_nonce%3D60f50c8800b2f52807732ca1ae3855ef %26oauth_signature_method%3DHMACSHA1%26oauth_timestamp%3D1224191856%26oauth_version%3D1.0 %26scope%3Dhttp%253A%252F%252Fwww.blogger.com%252Ffeeds%252F
Authorization: OAuth oauth_version="1.0", oauth_nonce="60f50c8800b2f52807732ca1ae3855ef", oauth_timestamp="1224191856", oauth_consumer_key="ec2-67-202-42-146.compute-1.amazonaws.com", oauth_signature_method="HMAC-SHA1", oauth_signature="nohPMCw%2BMrO8%2FwslS4oEm2wfuhg%3D"
HTTP/1.1 200 OK Content-Type: text/plain; charset=UTF-8 Date: Thu, 16 Oct 2008 21:17:37 GMT X-Content-Type-Options: nosniff Expires: Thu, 16 Oct 2008 21:17:37 GMT Cache-Control: private, max-age=0 Content-Length: 76 Server: GFE/1.3 oauth_token=COW3iN_7HxCXqfuzAQ&oauth_token_secret=ulsD7N5SuY16qC%2FvY2Sdk3AS
![]() |
Figure: 15.4.7.2.2.1. Google OAuth |
![]() |
Figure: 15.4.7.2.2.1. Google OAuth |
![]() |
Figure: 15.4.7.2.2.1. Google OAuth |
![]() |
Figure: 15.4.7.2.2.1. Google OAuth |
Blogger http://www.blogger.com/feeds/default/blogs http://www.blogger.com/feeds/<blogID>/posts/default http://www.blogger.com/feeds/<blogID>/[<postID>]/comments/default
![]() |
Figure: 15.4.7.2.2.1. Google OAuth |
Previous
FOAF+SSL Support |
Chapter Contents |
Next
WS-Security (WSS) Support in Virtuoso SOAP Server |