! Copyright (C) 2010 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors assocs base64 calendar checksums.hmac checksums.sha combinators fry http http.client kernel locals make math namespaces present random sequences sorting strings urls urls.encoding ; IN: oauth SYMBOL: consumer-token TUPLE: token key secret user-data ; : ( key secret -- token ) token new swap >>secret swap >>key ; >consumer-token now timestamp>unix-time >integer >>timestamp random-32 >>nonce ; inline :: signature-base-string ( url request-method params -- string ) [ request-method % "&" % url present url-encode-full % "&" % params assoc>query url-encode-full % ] "" make ; : hmac-key ( consumer-secret token-secret -- key ) [ url-encode-full ] [ "" or url-encode-full ] bi* "&" glue ; : make-token-params ( params quot -- assoc ) '[ "1.0" "oauth_version" set "HMAC-SHA1" "oauth_signature_method" set _ [ [ consumer-token>> key>> "oauth_consumer_key" set ] [ timestamp>> "oauth_timestamp" set ] [ nonce>> "oauth_nonce" set ] tri ] bi ] H{ } make-assoc ; inline :: sign-params ( url request-method consumer-token request-token params -- signed-params ) params >alist sort-keys :> params url request-method params signature-base-string :> sbs consumer-token secret>> request-token dup [ secret>> ] when hmac-key :> key sbs key sha1 hmac-bytes >base64 >string :> signature params { "oauth_signature" signature } prefix ; : extract-user-data ( assoc -- assoc' ) [ drop { "oauth_token" "oauth_token_secret" } member? not ] assoc-filter ; : parse-token ( response data -- token ) nip query>assoc [ [ "oauth_token" ] dip at ] [ [ "oauth_token_secret" ] dip at ] [ extract-user-data ] tri [ ] dip >>user-data ; PRIVATE> TUPLE: request-token-params < token-params { callback-url initial: "oob" } ; : ( -- params ) request-token-params new-token-params ; ( url consumer-token request-token params -- request ) url "POST" consumer-token request-token params sign-params url ; : make-request-token-params ( params -- assoc ) [ callback-url>> "oauth_callback" set ] make-token-params ; : ( url params -- request ) [ consumer-token>> f ] [ make-request-token-params ] bi ; PRIVATE> : obtain-request-token ( url params -- token ) http-request parse-token ; TUPLE: access-token-params < token-params request-token verifier ; : ( -- params ) access-token-params new-token-params ; > key>> "oauth_token" set ] [ verifier>> "oauth_verifier" set ] bi ] make-token-params ; : ( url params -- request ) [ consumer-token>> ] [ request-token>> ] [ make-access-token-params ] tri ; PRIVATE> : obtain-access-token ( url params -- token ) http-request parse-token ; SYMBOL: access-token TUPLE: oauth-request-params < token-params access-token ; : ( -- params ) oauth-request-params new-token-params access-token get >>access-token ; > request method>> params consumer-token>> params access-token>> params [ access-token>> key>> "oauth_token" set namespace request post-data>> assoc-union! drop ] make-token-params sign-params ; : build-auth-string ( params -- string ) [ [ present url-encode-full ] bi@ "\"" "\"" surround "=" glue ] { } assoc>map ", " join "OAuth realm=\"\", " prepend ; PRIVATE> : set-oauth ( request params -- request ) dupd signed-oauth-request-params build-auth-string "Authorization" set-header ;