This code borrows heavily from the OAuth domain code for wub by andrewsh. I turned it into a Tcl module for just the client side of OAuth authentication.
Put this code in a file called oauth-1.0.tm and place it somewhere on the module path of your Tcl installation:
namespace eval oauth { package require sha1 package require base64 variable secret "" tagstr set tagstr 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ namespace ensemble create -subcommands {secret auth} } proc oauth::secret {str} { variable secret $str } proc oauth::random {max} { return [expr {entier(rand() * $max)}] } proc oauth::tag {len {pfx ""} {str ""}} { variable tagstr if {$str eq ""} {set str $tagstr} for {set max [string length $str]} {$len > 0} {incr len -1} { append pfx [string index $str [random $max]] } return $pfx } proc oauth::escape {str} { set map {} foreach c [lsort -unique [regexp -all -inline {[^a-zA-Z0-9._~-]} $str]] { lappend map $c [format %%%02X [scan $c %c]] } return [string map $map $str] } proc oauth::encode {args} { if {[llength $args] == 1} { set args [lindex $args 0] } set pairs {} foreach {n v} $args { lappend pairs [escape $n]=[escape $v] } return [join $pairs &] } proc oauth::sign {method req provider {tokensecret {}}} { variable secret # normalize request parameters dict unset req oauth_signature foreach key [lsort [dict keys $req]] { lappend sorted $key [dict get $req $key] } set query [escape [encode $sorted]] lappend secrets [escape $secret] lappend secrets [escape $tokensecret] set secrets [join $secrets &] set url [escape $provider] set hmac [::sha1::hmac -bin $secrets "$method&$url&$query"] return [base64::encode $hmac] } proc oauth::auth {method url req {secret ""}} { dict set req oauth_signature_method HMAC-SHA1 dict set req oauth_version 1.0 dict set req oauth_nonce [tag 40] dict set req oauth_timestamp [clock seconds] dict set req oauth_signature [sign $method $req $url $secret] dict for {key val} $req { if {[regexp {^oauth_} $key]} { lappend list [escape $key]="[escape $val]" } } return "OAuth [join $list {, }]" }
See Twitter for a usage example.
zashi: Added the regex that only passes on oauth_ values for header. This fixed an issue I was running into trying to use this with tradeking's API.
If you want to use an API like tradeking, you have to break apart the url. If you want to access https://api.tradeking.com/v1/market/quotes.json?symbols=NTAP then you need to pass https://api.tradeking.com/v1/market/quotes.json to the oauth auth command and add the parameters to req:
dict set req symbols NTAP.