Skip to content

Instantly share code, notes, and snippets.

Last active November 1, 2018 15:32
Show Gist options
  • Save joewiz/5929809 to your computer and use it in GitHub Desktop.
Save joewiz/5929809 to your computer and use it in GitHub Desktop.
Access OAuth 1.0-based services like the Twitter v1.1 API, with XQuery. (See comments below for explanation.)
xquery version "3.0";
module namespace oauth="";
(:~ A library module for signing and submitting OAuth requests such as the kind needed for the Twitter v1.1 API.
The EXPath Crypto library supplies the HMAC-SHA1 algorithm. The EXPath HTTP Client library makes the HTTP requests.
The OAuth standard requires a "nonce" parameter - a random string. Since there is no implementation-independent
nonce function in XQuery, we must rely on implementation-specific functions. For eXist-db we use util:uuid().
import module namespace crypto="";
import module namespace http="";
import module namespace util = "";
declare function oauth:send-request(
) {
let $base-url := if (contains($url, '?')) then substring-before($url, '?') else $url
let $query-string := if (contains($url, '?')) then substring-after($url, '?') else ()
let $query-string-params :=
for $param in tokenize($query-string, '&')
let $name := substring-before($param, '=')
let $value := substring-after($param, '=')
<param name="{$name}" value="{$value}"/>
let $params :=
<param name="oauth_consumer_key" value="{$consumer-key}"/>,
<param name="oauth_nonce" value="{$nonce}"/>,
<param name="oauth_signature_method" value="{$signature-method}"/>,
<param name="oauth_timestamp" value="{$timestamp}"/>,
<param name="oauth_token" value="{$access-token}"/>,
<param name="oauth_version" value="{$version}"/>
let $parameter-string := oauth:params-to-oauth-string($params, '&amp;')
let $signature-base-string :=
let $signing-key := concat(encode-for-uri($consumer-secret), '&amp;', encode-for-uri($access-token-secret))
let $oauth-signature := crypto:hmac($signature-base-string, $signing-key, 'HmacSha1', 'base64')
let $final-params :=
<param name="oauth_signature" value="{$oauth-signature}"/>
let $final-parameter-string := oauth:params-to-oauth-string($final-params, ', ')
let $authorization-header-value := concat('OAuth ', $final-parameter-string)
let $request :=
<http:request href="{$url}" method="{$method}">
<http:header name="Authorization" value="{$authorization-header-value}"/>
let $response := http:send-request($request)
declare function oauth:nonce() { util:uuid() };
declare variable $oauth:signature-method := 'HMAC-SHA1';
declare variable $oauth:oauth-version := '1.0';
(: Generates an OAuth timestamp, which takes the form of the number of seconds since the Unix Epoch.
You can test these values against
declare function oauth:timestamp() as xs:unsignedLong {
let $unix-epoch := xs:dateTime('1970-01-01T00:00:00Z')
let $now := current-dateTime()
let $duration-since-epoch := $now - $unix-epoch
let $seconds-since-epoch :=
days-from-duration($duration-since-epoch) * 86400 (: 60 * 60 * 24 :)
hours-from-duration($duration-since-epoch) * 3600 (: 60 * 60 :)
minutes-from-duration($duration-since-epoch) * 60
(: prepares OAuth authentication parameters :)
declare function oauth:params-to-oauth-string($params as element(param)+, $separator as xs:string) {
for $param in $params
let $name := encode-for-uri($param/@name)
let $value := encode-for-uri($param/@value)
order by $name, $value
concat($name, '=', $value)
xquery version "3.1";
module namespace twitter-client = "";
(:~ A library module for your application's Twitter credentials and any helper functions for processing
the raw results of Twitter requests. You can get your credentials from
Twitter responds with JSON; despite being text, the HTTP Client returns JSON as binary, so we need
util:binary-to-text() to get the text. We use XQuery 3.1 to turn the JSON into XML.
import module namespace twitter = "" at "twitter.xq";
import module namespace util = "";
import module namespace ju = "" at "";
declare variable $twitter-client:consumer-key := ''; (: insert your credentials :)
declare variable $twitter-client:consumer-secret := '';
declare variable $twitter-client:access-token := '';
declare variable $twitter-client:access-token-secret := '';
declare function twitter-client:echo-response($request-response as item()+) {
let $request := $request-response[1]
let $response-head := $request-response[2]
let $response-body := $request-response[3]
let $json := parse-json(util:binary-to-string($response-body))
let $xml := ju:json-to-xml($json)
xquery version "3.0";
module namespace twitter="";
(:~ A library module for Twitter API methods.
import module namespace oauth="" at "oauth.xq";
declare variable $twitter:api-base-uri := '';
Get the user timeline.
declare function twitter:user-timeline(
$consumer-key as xs:string,
$consumer-secret as xs:string,
$access-token as xs:string,
$access-token-secret as xs:string,
$user-id as xs:string?,
$screen-name as xs:string?,
$since-id as xs:unsignedLong?, (: IDs are too big for xs:integer :)
$count as xs:integer?,
$max-id as xs:unsignedLong?,
$trim-user as xs:boolean?,
$exclude-replies as xs:boolean?,
$contributor-details as xs:boolean?,
$include-rts as xs:boolean?
) {
let $api-method := '/statuses/user_timeline.json'
let $http-method := 'GET'
let $query-string :=
if ($user-id) then concat('user_id=', $user-id) else (),
if ($screen-name) then concat('screen_name=', $screen-name) else (),
if ($since-id) then concat('since_id=', $since-id) else (),
if ($count) then concat('count=', $count) else (),
if ($max-id) then concat('max_id=', $max-id) else (),
if ($trim-user) then concat('trim_user=', $trim-user) else (),
if ($exclude-replies) then concat('exclude_replies=', $exclude-replies) else (),
if ($contributor-details) then concat('contributor_details=', $contributor-details) else (),
if ($include-rts) then concat('include_rts=', $include-rts) else ()
let $api-url := concat($twitter:api-base-uri, $api-method, '?', $query-string)
xquery version "3.0";
(:~ A main module to retrieve the user timeline. :)
import module namespace twitter = "" at "twitter.xq";
import module namespace twitter-client = "" at "twitter-client.xq";
(: Parameters needed for the user timeline function. :)
let $user-id := ()
let $screen-name := ()
let $since-id := ()
let $count := 10
let $max-id := ()
let $trim-user := true()
let $exclude-replies := false()
let $contributor-details := false()
let $include-rts := false()
let $request-response :=
(: Echo the response so we can see the request, the response header, the response body (JSON), and the XML version of the JSON :)
Copy link

joewiz commented Aug 29, 2016

Sorry @mathias-goebel, I didn't see your comment until now. Since twitter requires that all requests to its API be signed, we do need some crypto library for HMAC-SHA1. I don't think I was aware of the datetime:timestamp() function (an eXist-specific function), but I generally prefer to use implementation independent functions when possible.

Copy link

Hi ,
I have an angular application sending azure auth token to marklogic .Is there a way to authenticate the token in xquery .I have done the same in a Java app and it has client supported libraries .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment