1 ! Copyright (C) 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs base64 calendar checksums.hmac
4 checksums.sha combinators fry http http.client kernel locals
5 make math namespaces present random sequences sorting strings
11 TUPLE: token key secret user-data ;
13 : <token> ( key secret -- token )
25 : new-token-params ( class -- params )
27 consumer-token get >>consumer-token
28 now timestamp>unix-time >integer >>timestamp
29 random-32 >>nonce ; inline
31 :: signature-base-string ( url request-method params -- string )
33 request-method % "&" %
34 url present url-encode-full % "&" %
35 params assoc>query url-encode-full %
38 : hmac-key ( consumer-secret token-secret -- key )
39 [ url-encode-full ] [ "" or url-encode-full ] bi* "&" glue ;
41 : make-token-params ( params quot -- assoc )
43 "1.0" "oauth_version" ,,
44 "HMAC-SHA1" "oauth_signature_method" ,,
48 [ consumer-token>> key>> "oauth_consumer_key" ,, ]
49 [ timestamp>> "oauth_timestamp" ,, ]
50 [ nonce>> "oauth_nonce" ,, ]
55 :: sign-params ( url request-method consumer-token request-token params -- signed-params )
56 params sort-keys :> params
57 url request-method params signature-base-string :> sbs
58 consumer-token secret>> request-token dup [ secret>> ] when hmac-key :> key
59 sbs key sha1 hmac-bytes >base64 >string :> signature
60 params { "oauth_signature" signature } prefix ;
62 : extract-user-data ( assoc -- assoc' )
65 { "oauth_token" "oauth_token_secret" } member? not
68 : parse-token ( response data -- token )
71 [ [ "oauth_token" ] dip at ]
72 [ [ "oauth_token_secret" ] dip at ]
75 [ <token> ] dip >>user-data ;
79 TUPLE: request-token-params < token-params
80 { callback-url initial: "oob" } ;
82 : <request-token-params> ( -- params )
83 request-token-params new-token-params ;
87 :: <token-request> ( url consumer-token request-token params -- request )
88 url "POST" consumer-token request-token params sign-params
92 : make-request-token-params ( params -- assoc )
93 [ callback-url>> "oauth_callback" ,, ] make-token-params ;
95 : <request-token-request> ( url params -- request )
96 [ consumer-token>> f ] [ make-request-token-params ] bi
101 : obtain-request-token ( url params -- token )
102 <request-token-request> http-request parse-token ;
104 TUPLE: access-token-params < token-params request-token verifier ;
106 : <access-token-params> ( -- params )
107 access-token-params new-token-params ;
111 : make-access-token-params ( params -- assoc )
113 [ request-token>> key>> "oauth_token" ,, ]
114 [ verifier>> "oauth_verifier" ,, ]
116 ] make-token-params ;
118 : <access-token-request> ( url params -- request )
121 [ make-access-token-params ] tri
126 : obtain-access-token ( url params -- token )
127 <access-token-request> http-request parse-token ;
131 TUPLE: oauth-request-params < token-params access-token ;
133 : <oauth-request-params> ( -- params )
134 oauth-request-params new-token-params
135 access-token get >>access-token ;
139 :: signed-oauth-request-params ( request params -- params )
142 params consumer-token>>
143 params access-token>>
146 access-token>> key>> "oauth_token" ,,
147 request post-data>> %%
151 : build-auth-string ( params -- string )
152 [ [ present url-encode-full ] bi@ "\"" "\"" surround "=" glue ] { } assoc>map
153 ", " join "OAuth realm=\"\", " prepend ;
157 : set-oauth ( request params -- request )
158 dupd signed-oauth-request-params build-auth-string
159 "Authorization" set-header ;