Merge remote-tracking branches 'ault011/instagram', 'ohaitch/markdown-hax-url', 'ault011/digitalocean' and 'ohaitch/procedural-security-drivers'

Conflicts:
	sec/com/dropboxapi.hoon

Many security drivers in this merge. A small markdown fix also snuck
into one of the octopus' arms as parent 3.
This commit is contained in:
Raymond Pasco 2016-04-12 13:03:25 -04:00
20 changed files with 851 additions and 387 deletions

View File

@ -1,6 +1,6 @@
:: Twitter daemon
::
:::: /hook/core/twit/app
:::: /hoon/twit/app
::
/+ twitter, talk
::

View File

@ -1,5 +1,5 @@
::
:::: /hoon/curl/gen
:::: /hoon/curl-hiss/gen
::
/? 310
/- sole

View File

@ -1,6 +1,6 @@
:: Display twitter feed
::
:::: /hook/core/twitter-feed/app
:::: /hoon/twitter-feed/twit/gen
::
/+ sh-utils
!:

View File

@ -1,8 +1,33 @@
!:
=+ keys=@t
|= bal/(bale keys)
?~ key.bal
~|(%basic-auth-no-key ~_(leaf+"Run |init-auth-basic {<`path`dom.bal>}" !!))
=+ aut=authorization+(cat 3 'Basic ' key.bal)
~& aut=`{@tas @t}`aut
|=(a/hiss [%send %_(a q.q (~(add ja q.q.a) -.aut +.aut))])
:: Basic authentication
::
:::: /hoon/basic-auth/lib
::
|%
++ keys @t
--
::
::::
::
|_ {bal/(bale keys) $~}
++ auth
|%
++ header
^- cord
?~ key.bal
~_ leaf+"Run |init-auth-basic {<`path`dom.bal>}"
~|(%basic-auth-no-key !!)
(cat 3 'Basic ' key.bal)
--
::
++ add-auth-header
|= a/hiss ^- hiss
~& auth+(earn p.a)
%_(a q.q (~(add ja q.q.a) %authorization header:auth))
::
++ standard
|%
++ out-adding-header
|= a/hiss ^- sec-move
[%send (add-auth-header a)]
--
--

View File

@ -210,7 +210,7 @@
|= a/tape ^- tape
?~ a ~
?: ?| [?=(^ q)]:(alp 1^1 a)
(~(has in (silt "!*'();:@&=+$,/?/%.~_")) i.a) :: XX reparse
(~(has in (silt "#!*'();:@&=+$,/?/%.~_")) i.a) :: XX reparse
==
[i.a $(a t.a)]
(weld (urle (trip i.a)) $(a t.a))

25
lib/hep-to-cab.hoon Normal file
View File

@ -0,0 +1,25 @@
:: rewrite query string keys
::
:::: /hoon/hep-to-cab/lib
::
/? 310
::
:::: ~fyr
::
=< term
|%
++ gsub :: replace chars
|= {a/@t b/@t t/@t}
^- @t
?: =('' t) t
%+ mix (lsh 3 1 $(t (rsh 3 1 t)))
=+ c=(end 3 1 t)
?:(=(a c) b c)
::
++ term |=(a/^term (gsub '-' '_' a)) :: single atom
++ path |=(a/^path (turn a term)) :: path elements
++ quay :: query string keys
|= a/^quay ^+ a
%+ turn a
|=({p/@t q/@t} [(term p) q])
--

49
lib/interpolate.hoon Normal file
View File

@ -0,0 +1,49 @@
:: /foo/:bar/baz interpolation syntax
::
:::: /hoon/interpolate/lib
::
/? 310
::
:::: ~fyr
::
=< into-url
|%
++ parse-url
|= a/$@(cord:purl purl) ^- purl
?^ a a
~| bad-url+a
(rash a auri:epur)
::
++ add-query
|= {a/$@(@t purl) b/quay} ^- purl
?@ a $(a (parse-url a)) :: deal with cord
a(r (weld r.a b))
::
++ into-url
|= {a/$@(cord purl) b/(unit hart) c/(list (pair term knot))}
^- purl
?@ a $(a (parse-url a)) :: deal with cord
%_ a
p ?^(b u.b p.a)
q.q (into-path q.q.a c)
==
::
++ into-path :: [/a/:b/c [%b 'foo']~] -> /a/foo/c
=+ replacable=|=(a/knot `(unit term)`(rush a ;~(pfix col sym)))
|= {a/path b/(list (pair term knot))} ^- path
?~ a ?~(b ~ ~|(unused-values+b !!))
=+ (replacable i.a)
?~ - [i.a $(a t.a)] :: literal value
?~ b ~|(no-value+u !!)
?. =(u p.i.b) ~|(mismatch+[u p.i.b] !!)
[q.i.b $(a t.a, b t.b)]
::
++ into-path-partial :: [/a/:b/c [d+'bar' b+'foo']~] -> [/a/foo/c [d+'bar']~]
|= {pax/path quy/quay} ^- {path quay}
=+ ^= inline :: required names
%- ~(gas in *(set term))
(murn pax replacable:into-path)
=^ inter quy
(skid quy |=({a/knot @} (~(has in inline) a)))
[(into-path pax inter) quy]
--

View File

@ -2,6 +2,7 @@
::
:::: /hoon/oauth1/lib
::
/+ interpolate, hep-to-cab
|%
++ keys cord:{key/@t sec/@t} :: app key pair
++ token :: user keys
@ -15,20 +16,7 @@
::::
::
|%
++ fass :: rewrite quay
|= a/quay
%+ turn a
|= {p/@t q/@t} ^+ +<
[(gsub '-' '_' p) q]
::
++ gsub :: replace chars
|= {a/@t b/@t t/@t}
^- @t
?: =('' t) t
%+ mix (lsh 3 1 $(t (rsh 3 1 t)))
=+ c=(end 3 1 t)
?:(=(a c) b c)
::
++ parse-url parse-url:interpolate
++ join
|= {a/cord b/(list cord)}
?~ b ''
@ -43,7 +31,7 @@
++ to-header
|= a/quay ^- tape
%+ joint ", "
(turn a |=({k/@t v/@t} `tape`~[k '="' v '"'])) :: normalized later
(turn a |=({k/@t v/@t} `tape`~[k '="' v '"'])) :: normalized later
::
:: partial tail:earn for sorting
++ encode-pairs
@ -52,7 +40,7 @@
|= {k/@t v/@t} ^- tape
:(weld (urle (trip k)) "=" (urle (trip v)))
::
++ parse-pairs :: x-form-urlencoded
++ parse-pairs :: x-form-urlencoded
|= bod/(unit octs) ^- quay-enc
~| %parsing-body
?~ bod ~
@ -60,6 +48,7 @@
::
++ post-quay
|= {a/purl b/quay} ^- hiss
=. b (quay:hep-to-cab b)
=- [a %post - ?~(b ~ (some (tact +:(tail:earn b))))]
(my content-type+['application/x-www-form-urlencoded']~ ~)
::
@ -69,60 +58,30 @@
=- (mean (flop `tang`[>a< -]))
(turn (lore (crip b)) |=(c/cord leaf+(trip c)))
::
++ dbg-post `purl`[`hart`[| `6.000 [%& /localhost]] `pork``/testing `quay`/]
++ bad-response |=(a/@u ?:(=(2 (div a 100)) | ~&(bad-httr+a &)))
++ quay-keys |-($@(knot {$ $})) :: improper tree
++ grab-quay :: ?=({@t @t @t} ((grab-quay *httr) %key1 %key2 %key3))
|* {a/httr b/quay-keys}
~| bad-quay+r.a
=+ quy=(rash q:(need r.a) yquy:urlp)
~| quy
=+ all=(malt quy)
++ grab-quay :: ?=({@t @t @t} (grab-quay r:*httr %key1 %key2 %key3))
|* {a/(unit octs) b/quay-keys}
=+ ~| bad-quay+a
c=(rash q:(need `(unit octs)`a) yquy:urlp)
~| grab-quay+[c b]
=+ all=(malt c)
%. b
|* b/quay-keys
?@ b ~|(b (~(got by all) b))
[(..$ -.b) (..$ +.b)]
::
++ parse-url
|= a/$@(cord:purl purl) ^- purl
?^ a a
~| bad-url+a
(rash a auri:epur)
::
++ interpolate-url
|= {a/$@(cord purl) b/(unit hart) c/(list (pair term knot))}
^- purl
?@ a $(a (parse-url a)) :: deal with cord
%_ a
p ?^(b u.b p.a)
q.q (interpolate-path q.q.a c)
==
::
++ interpolate-path :: [/a/:b/c [%b 'foo']~] -> /a/foo/c
|= {a/path b/(list (pair term knot))} ^- path
?~ a ?~(b ~ ~|(unused-values+b !!))
=+ (rush i.a ;~(pfix col sym))
?~ - [i.a $(a t.a)] :: not interpolable
?~ b ~|(no-value+u !!)
?. =(u p.i.b) ~|(mismatch+[u p.i.b] !!)
[q.i.b $(a t.a, b t.b)]
--
!:
::::
::
|= {request/$@(@t purl) dialog/$@(@t purl) code-exchange/$@(@t purl)}
=+ :+ dialog-url=(parse-url dialog)
exchange-url=(parse-url code-exchange)
token-reqs-url=(parse-url request)
|_ {done/* (bale keys) tok/token}
+- core-move $^({sec-move _done} sec-move) :: stateful
|_ {(bale keys) tok/token}
++ consumer-key key:decode-keys
++ consumer-secret sec:decode-keys
++ decode-keys :: XX from bale w/ typed %jael
^- {key/@t sec/@t $~}
?. =(~ `@`key)
~| %oauth-bad-keys
((hard {cid/@t cis/@t $~}) (lore key))
((hard {key/@t sec/@t $~}) (lore key))
%+ mean-wall %oauth-no-keys
"""
Run |init-oauth1 {<`path`dom>}
@ -130,41 +89,40 @@
{(trip oauth-callback)}
"""
::
++ exchange-token
|= a/$@(@t purl) ^- hiss
(post-quay (parse-url a) ~)
::
++ request-token
|= a/$@(@t purl) ^- hiss
(post-quay (parse-url a) oauth-callback+oauth-callback ~)
::
++ our-host .^(hart %e /(scot %p our)/host/fake)
++ oauth-callback
~& [%oauth-warning "Make sure this urbit ".
"is running on {(earn our-host `~ ~)}"]
%- crip %- earn
%^ interpolate-url 'https://our-host/~/ac/:domain/:user/in'
%^ interpolate 'https://our-host/~/ac/:domain/:user/in'
`our-host
:~ domain+(join '.' (flop dom))
user+(scot %ta usr)
==
::
++ auth-url
|= url/$@(@t purl) ^- purl
%+ add-query:interpolate url
%- quay:hep-to-cab
?. ?=({$request-token ^} tok)
~|(%no-token-for-dialog !!)
:- oauth-token+oauth-token.tok
?~(usr ~ [screen-name+usr]~)
::
++ toke-url
|= quy/quay ^- purl
%_ dialog-url
r (fass ?~(usr quy [screen-name+usr quy]))
==
++ grab-token-response
|= a/httr ^- {tok/@t sec/@t}
(grab-quay r.a 'oauth_token' 'oauth_token_secret')
::
++ token-exchange (post-quay exchange-url ~)
++ token-request (post-quay token-reqs-url oauth-callback+oauth-callback ~)
::
:: use token to sign authorization header. requires:
:: ++ res (res-handle-reqt handle-token) :: take request token
:: ++ bak (res-save-access handle-token) :: obtained access token
++ out-math
^- $-(hiss $%({$send hiss} {$show purl}))
?~ tok
_[%send (add-auth ~ token-request)]
?: ?=($request-token -.tok)
_[%show (toke-url oauth-token+oauth-token.tok ~)]
|= a/hiss ^- {$send hiss}
[%send (add-auth [oauth-token+oauth-token.tok]~ a)]
::
++ in-oauth-token
|= a/quay ^- sec-move
++ check-token-quay
|= a/quay ^+ %&
=. a (sort a aor)
?. ?=({{$'oauth_token' oauth-token/@t} {$'oauth_verifier' @t} $~} a)
~|(no-token+a !!)
@ -173,54 +131,15 @@
?. =(oauth-token.tok oauth-token.q.i.a)
~| wrong-token+[id=usr q.i.a]
~|(%multiple-tokens-unsupported !!)
[%send (add-auth a token-exchange)]
%&
::
++ token-response ['oauth_token' 'oauth_token_secret']
+- bak-save-access
|= handle/$-(token _done)
%- (res-parse token-response)
|= access-token/{tok/@t sec/@t} ^- core-move
[[%redo ~] (handle `token`[%access-token access-token])]
::
+- res-parse
|* para/quay-keys
|= handle/$-(_?~(para ~ (grab-quay *httr para)) core-move)
|= a/httr ^- core-move
?: (bad-response p.a)
[%give a]
:: [%redo ~] :: handle 4xx?
(handle (grab-quay a para))
::
++ res-give |=(a/httr [%give a])
+- res-handle-reqt
|= handle/$-(token _done) ^- $-(httr core-move)
?~ tok
(res-save-reqt handle)
res-give
::
+- res-save-reqt
|= handle/$-(token _done) ^- $-(httr core-move)
%- (res-parse token-response 'oauth_callback_confirmed')
|= {request-token/{tok/@t sec/@t} cof/term} ^- core-move
?. =(%true cof)
~|(%callback-rejected !!)
[[%redo ~] (handle `token`[%request-token request-token])]
::
::
++ add-auth
=< |= $: auq/quay :: extra oauth parameters
hiz/{purl meth hed/math (unit octs)}
==
^- hiss
~& add-auth+(earn -.hiz)
%_ hiz
hed (~(add ja hed.hiz) %authorization (authorization auq hiz))
==
++ auth
|%
++ authorization
++ header
|= {auq/quay url/purl med/meth math bod/(unit octs)}
^- cord
=^ quy url [r.url url(r ~)] :: query string handled separately
=. auq (fass (weld auq auth-quay))
=. auq (quay:hep-to-cab (weld auq computed-query))
=+ ^- qen/quay-enc :: semi-encoded for sorting
%+ weld (parse-pairs bod)
(encode-pairs (weld auq quy))
@ -229,7 +148,7 @@
=. auq ['oauth_signature'^(crip (urle sig)) auq]
(crip "OAuth {(to-header auq)}")
::
++ auth-quay
++ computed-query
^- quay
:~ oauth-consumer-key+consumer-key
oauth-nonce+(scot %uw (shaf %non eny))
@ -256,4 +175,136 @@
(trip ?^(tok token-secret.tok ''))
==
--
::
++ add-auth-header
|= {extra/quay request/{url/purl meth hed/math (unit octs)}}
^- hiss
:: =. url.request [| `6.000 [%& /localhost]] :: for use with unix nc
~& add-auth-header+(earn url.request)
%_ request
hed
(~(add ja hed.request) %authorization (header:auth extra request))
==
:: expected semantics, to be copied and modified if anything doesn't work
++ standard
|* {done/* save/$-(token *)} :: save/$-(token _done)
|%
++ save ^-($-(token _done) ^save) :: shadow(type canary)
++ core-move $^({sec-move _done} sec-move) :: stateful
::
:: use token to sign authorization header. expects:
:: ++ res res-handle-request-token :: save request token
:: ++ in (in-token-exhange 'http://...') :: handle callback
++ out-add-header
|= {request-url/$@(@t purl) dialog-url/$@(@t purl)}
::
|= a/hiss ^- $%({$send hiss} {$show purl})
?- tok
$~
[%send (add-auth-header ~ (request-token request-url))]
::
{$access-token ^}
[%send (add-auth-header [oauth-token+oauth-token.tok]~ a)]
::
{$request-token ^}
[%show (auth-url dialog-url)]
==
::
:: If no token is saved, the http response we just got has a request token
++ res-handle-request-token
|= a/httr ^- core-move
?^ tok [%give a]
?. =(%true (grab-quay r.a 'oauth_callback_confirmed'))
~|(%callback-rejected !!)
=+ request-token=(grab-token-response a)
[[%redo ~] (save `token`[%request-token request-token])]
::
:: Exchange oauth_token in query string for access token. expects:
:: ++ bak bak-save-token :: save access token
++ in-exchange-token
|= exchange-url/$@(@t purl)
::
|= a/quay ^- sec-move
?> (check-token-quay a)
[%send (add-auth-header a (exchange-token exchange-url))]
::
:: If a valid access token has been returned, save it
++ bak-save-token
|= a/httr ^- core-move
?: (bad-response p.a)
[%give a] :: [%redo ~] :: handle 4xx?
=+ access-token=(grab-token-response a)
[[%redo ~] (save `token`[%access-token access-token])]
--
--
::
:::: Example "standard" sec/ core:
::
::
:: ::
:: :::: /hoon/my-api/com/sec
:: ::
:: /+ oauth1
:: ::
:: ::::
:: ::
:: |_ {bal/(bale keys:oauth1) tok/token:oauth1}
:: ++ aut (~(standard oauth1 bal tok) . |=(tok/token:oauth1 +>(tok tok)))
:: ++ out
:: %+ out-add-header:aut
:: request-token='https://my-api.com/request_token'
:: oauth-dialog='https://my-api.com/authorize'
:: ::
:: ++ res res-handle-request-token:aut
:: ++ in
:: %- in-exchagne-token:aut
:: exchange-url='https://my-api.com/access_token'
:: ::
:: ++ bak bak-save-token:aut
:: --
::
::
:::: Equivalent imperative code:
::
::
:: ::
:: :::: /hoon/my-api/com/sec
:: ::
:: /+ oauth1
:: ::
:: ::::
:: ::
:: |_ {bal/(bale keys:oauth1) tok/token:oauth1}
:: ++ aut ~(. oauth1 bal tok)
:: ++ out :: add header
:: =+ aut
:: |= req/hiss ^- $%({$send hiss} {$show purl})
:: ?~ tok
:: [%send (add-auth-header ~ (request-token 'https://my-api.com/request_token'))]
:: ?: ?=($request-token -.tok)
:: [%show (auth-url 'https://my-api.com/authorize')]
:: [%send (add-auth-header [oauth-token+ouath-token.tok]~ req)]
:: ::
:: ++ res :: handle request token
:: =+ aut
:: |= res/httr ^- $%({{$redo $~} _..res} {$give httr})
:: ?^ tok [%give a]
:: ?> =(%true (grab r.res 'oauth_callback_confirmed'))
:: =. tok [%request-token (grab-token-response res)]
:: [[%redo ~] ..res]
:: ::
:: ++ in :: exchange token
:: =+ aut
:: |= inp/quay ^- {$send hiss}
:: ?> (check-token-quay inp)
:: :- %send
:: (add-auth-header inp (exchange-token 'https://my-api.com/access_token'))
:: ::
:: ++ bak :: save token
:: =+ aut
:: |= bak/httr ^- $%({{$redo $~} _..bak} {$give httr})
:: ?: (bad-response bak) [%give bak]
:: =. tok [%access-token (grab-token-response res)]
:: [[%redo ~] ..bak]
:: --
::

View File

@ -1,80 +1,47 @@
:: OAuth 2.0 %authorization
::
:::: /hoon/oauth2/lib
::
/+ hep-to-cab, interpolate
|%
++ fass :: rewrite quay
|= a/quay
%+ turn a
|= {p/@t q/@t} ^+ +<
[(gsub '-' '_' p) q]
::
++ gsub :: replace chars
|= {a/@t b/@t t/@t}
^- @t
?: =('' t) t
%+ mix (lsh 3 1 $(t (rsh 3 1 t)))
=+ c=(end 3 1 t)
?:(=(a c) b c)
::
++ join
++ parse-url parse-url:interpolate
++ join
|= {a/cord b/(list cord)}
?~ b ''
(rap 3 |-([i.b ?~(t.b ~ [a $(b t.b)])]))
::
++ post-quay
|= {a/purl b/quay} ^- hiss
=. b (quay:hep-to-cab b)
=- [a %post - ?~(b ~ (some (tact +:(tail:earn b))))]
(my content-type+['application/x-www-form-urlencoded']~ ~)
::
++ mean-wall !.
|= {a/term b/tape} ^+ !!
=- (mean (flop `tang`[>a< -]))
(turn (lore (crip b)) |=(c/cord leaf+(trip c)))
::
++ dbg-post `purl`[`hart`[| `6.000 [%& /localhost]] `pork``/testing `quay`/]
++ bad-response |=(a/@u ?:(=(2 (div a 100)) | ~&(bad-httr+a &)))
++ grab-json
|* {a/httr b/fist:jo}
~| bad-json+r.a
~| (poja q:(need r.a))
(need (;~(biff poja b) q:(need r.a)))
::
++ parse-url
|= a/$@(cord:purl purl) ^- purl
?^ a a
~| bad-url+a
(rash a auri:epur)
::
++ interpolate-url
|= {a/$@(cord purl) b/(unit hart) c/(list (pair term knot))}
^- purl
?@ a $(a (parse-url a)) :: deal with cord
%_ a
p ?^(b u.b p.a)
q.q (interpolate-path q.q.a c)
==
::
++ interpolate-path :: [/a/:b/c [%b 'foo']~] -> /a/foo/c
|= {a/path b/(list (pair term knot))} ^- path
?~ a ?~(b ~ ~|(unused-values+b !!))
=+ (rush i.a ;~(pfix col sym))
?~ - [i.a $(a t.a)] :: not interpolable
?~ b ~|(no-value+u !!)
?. =(u p.i.b) ~|(mismatch+[u p.i.b] !!)
[q.i.b $(a t.a, b t.b)]
--
::
::::
::
|%
++ token ?($~ @t)
++ refresh {tok/token needed/@da pending/_`?`|}
++ refresh {tok/token expiry/@da pending/_`?`|}
++ both-tokens {token refresh}
++ keys cord:{cid/@t cis/@t}
++ core-move |*(a/* $^({sec-move _a} sec-move)) ::here's a change
--
::
::::
::
|= {dialog/$@(cord:purl purl) code-exchange/$@(cord:purl purl)}
=+ :+ state-usr=|
dialog-url=(parse-url dialog)
exchange-url=(parse-url code-exchange)
|_ {(bale keys) scope/(list cord)}
=+ state-usr=|
|_ {(bale keys) tok/token}
++ client-id cid:decode-keys
++ client-secret cis:decode-keys
++ decode-keys :: XX from bale w/ typed %jael
@ -89,55 +56,32 @@
{(trip redirect-uri)}
"""
::
++ our-host .^(hart %e /(scot %p our)/host/fake)
++ auth-url
|= {scopes/(list @t) url/$@(@t purl)} ^- purl
~& [%oauth-warning "Make sure this urbit ".
"is running on {(earn our-host `~ ~)}"]
^- purl
%_ dialog-url
r
%+ welp r.dialog-url
%- fass
:~ state+?.(state-usr '' (pack usr /''))
client-id+client-id
redirect-uri+redirect-uri
scope+(join ' ' scope)
==
%+ add-query:interpolate url
%- quay:hep-to-cab
:~ state+?.(state-usr '' (pack usr /''))
client-id+client-id
redirect-uri+redirect-uri
scope+(join ' ' scopes)
==
::
++ our-host .^(hart %e /(scot %p our)/host/fake)
++ redirect-uri
%- crip %- earn
%^ interpolate-url 'https://our-host/~/ac/:domain/:user/in'
%^ interpolate 'https://our-host/~/ac/:domain/:user/in'
`our-host
:~ domain+(join '.' (flop dom))
user+?:(state-usr '_state' (scot %ta usr))
==
::
::
++ out-filtered
|= {tok/token aut/$-(hiss hiss)}
|= a/hiss ^- sec-move
?~(tok [%show auth-url] [%send (aut a)])
::
++ out-quay
|= {nam/knot tok/token}
%+ out-filtered tok
|=(a/hiss %_(a r.p :_(r.p.a nam^`@t`tok)))
::
++ out-math
|= ber/token
=+ hed=(cat 3 'Bearer ' `@t`ber)
%+ out-filtered ber
|= a/hiss ^+ a
:: =. p.a dbg-post
%_(a q.q (~(add ja q.q.a) %authorization hed))
::
++ toke-req
|= {grant-type/cord quy/quay} ^- {$send hiss}
:+ %send exchange-url
:+ %post (malt ~[content-type+~['application/x-www-form-urlencoded']])
=- `(tact +:(tail:earn -))
%- fass
++ request-token
|= {a/$@(@t purl) grant-type/cord quy/quay} ^- hiss
%+ post-quay (parse-url a)
%- quay:hep-to-cab
%+ welp quy
:~ client-id+client-id
client-secret+client-secret
@ -145,60 +89,295 @@
grant-type+grant-type
==
::
++ in-code
|= a/quay ^- sec-move
=+ code=~|(%no-code (~(got by (malt a)) %code))
(toke-req 'authorization_code' code+code ~)
++ request-token-by-code
|=({a/$@(@t purl) b/@t} (request-token a 'authorization_code' code+b ~))
::
++ token-type 'token_type'^(cu cass sa):jo
++ expires-in 'expires_in'^ni:jo
++ access-token 'access_token'^so:jo
++ refresh-token 'refresh_token'^so:jo
++ bak-save-access
|* {done/* handle/$-(cord:token *)} :: $+(token _done)
%- (bak-parse done access-token ~)
|=(tok/cord:token [[%redo ~] (handle tok)])
++ grab-token
|= a/httr ^- axs/@t
(grab-json a (ot 'access_token'^so ~):jo)
::
++ bak-parse
|* {done/* parse/(pole {knot fist}:jo)}
|= handle/$-(_?~(parse ~ (need *(ot:jo parse))) (core-move done))
|= a/httr ^- (core-move done)
?: (bad-response p.a)
[%give a]
:: [%redo ~] :: handle 4xx?
(handle (grab-json a (ot:jo parse)))
++ grab-expiring-token
|= a/httr ^- {axs/@t exp/@u}
(grab-json a (ot 'access_token'^so 'expires_in'^ni ~):jo)
::
++ res-give |=(a/httr [%give a])
++ grab-both-tokens
|= a/httr ^- {axs/@t exp/@u ref/@t}
(grab-json a (ot 'access_token'^so 'expires_in'^ni 'refresh_token'^so ~):jo)
::
++ auth
?~ tok ~|(%no-bearer-token !!)
|%
++ header `cord`(cat 3 'Bearer ' `@t`tok)
++ query `cord`tok
--
::
++ add-auth-header
|= request/{url/purl meth hed/math (unit octs)}
^+ request
:: =. p.url.request [| `6.000 [%& /localhost]] :: for use with unix nc
~& add-auth-header+(earn url.request)
request(hed (~(add ja hed.request) %authorization header:auth))
::
++ add-auth-query
|= {token-name/cord request/{url/purl meth math (unit octs)}}
^+ request
:: =. p.url.request [| `6.000 [%& /localhost]] :: for use with unix nc
~& add-auth-query+(earn url.request)
request(r.url [[token-name query:auth] r.url.request])
::
++ re
|* cor/* :: XX redundant with *export, but type headaches
|_ {ref/refresh export/$-(refresh _cor)}
++ out-fix-expired
|= default/$-(hiss sec-move)
^- $-(hiss (core-move cor))
?~ tok.ref default
?. (lth needed.ref (add now ~m59.s30))
default
|= a/hiss
:_ (export ref(pending &))
(toke-req 'refresh_token' refresh-token+tok.ref ~)
|_ ref/refresh
++ needs-refresh ?~(tok.ref | is-expired)
++ is-expired (lth expiry.ref (add now ~m5))
++ update
|= exp/@u ^+ ref
ref(pending |, expiry (add now (mul ~s1 exp)))
::
++ res-handle-refreshed
|= {handle-access/_=>(cor |=(@t +>)) default/$-(httr sec-move)}
^- $-(httr (core-move cor))
?. pending.ref default
%- (bak-parse cor expires-in access-token ~)
|= {exp/@u tok/axs/@t} ^- {sec-move _cor}
=. +>.handle-access
(export tok.ref (add now (mul ~s1 exp)) |)
[[%redo ~] (handle-access axs.tok)]
++ update-if-needed
|= exchange-url/$@(@t purl)
^- {(unit hiss) refresh}
?~ tok.ref `ref
?. is-expired `ref
:_ ref(pending &)
`(request-token exchange-url 'refresh_token' refresh-token+tok.ref ~)
--
::
:: expected semantics, to be copied and modified if anything doesn't work
++ standard
|* {done/* save/$-(token *)}
|%
++ save ^-($-(token _done) ^save) :: shadow(type canary)
++ core-move $^({sec-move _done} sec-move) :: stateful
::
++ bak-save-tokens
|= handle-access/_=>(cor |=(@t +>))
%- (bak-parse cor expires-in access-token refresh-token ~)
|= {exp/@u tok/{axs/@t ref/@t}} ^- {sec-move _cor}
=. +>.handle-access
(export ref.tok (add now (mul ~s1 exp)) |)
[[%redo ~] (handle-access axs.tok)]
:: Insert token into query string. expects:
:: ++ in (in-code-to-token 'http://...') :: handle callback
++ out-add-query-param
|= {token-name/knot scopes/(list cord) dialog/$@(@t purl)}
::
|= a/hiss ^- $%({$send hiss} {$show purl})
?~ tok [%show (auth-url scopes dialog)]
[%send (add-auth-query token-name a)]
::
:: Add token as a header. expects:
:: ++ in (in-code-to-token 'http://...') :: handle callback
++ out-add-header
|= {scopes/(list cord) dialog/$@(@t purl)}
::
|= a/hiss ^- sec-move
?~ tok [%show (auth-url scopes dialog)]
[%send (add-auth-header a)]
::
:: Exchange code in query string for access token. expects:
:: ++ bak bak-save-token :: save access token
++ in-code-to-token
|= exchange-url/$@(@t purl)
::
|= a/quay ^- sec-move
=+ code=~|(%no-code (~(got by (malt a)) %code))
[%send (request-token-by-code exchange-url code)]
::
:: If an access token has been returned, save it
++ bak-save-token
|= a/httr ^- core-move
?: (bad-response p.a)
[%give a] :: [%redo ~] :: handle 4xx?
[[%redo ~] (save `token`(grab-token a))]
--
::
++ standard-refreshing
|* {done/* ref/refresh save/$-({token refresh} *)}
=+ s=(standard done |=(tok/token (save tok ref)))
|%
++ save ^-($-(both-tokens _done) ^save) :: shadow(type canary)
++ core-move $^({sec-move _done} sec-move) :: stateful
::
:: See ++out-add-query-param:standard
:: Refresh token if we have an expired one, ask for authentication if none is present,
:: insert auth token into the query string if it's valid. expects:
:: ++ in (in-code-to-token 'http://...') :: handle callback
:: ++ res res-save-after-refresh
++ out-refresh-or-add-query-param
|= {exchange/$@(@t purl) s-args/{knot (list cord) $@(@t purl)}}
::
|= a/hiss ^- core-move
=^ upd ref (~(update-if-needed re ref) exchange)
?^ upd [[%send u.upd] (save tok ref)]
%.(a (out-add-query-param.s s-args))
::
:: See ++out-add-header:standard
:: Refresh token if we have an expired one, ask for authentication if none is present,
:: add token as a header if it's valid. expects:
:: ++ in (in-code-to-token 'http://...') :: handle callback
:: ++ res res-save-after-refresh
++ out-refresh-or-add-header
|= {exchange/$@(@t purl) s-args/{(list cord) dialog/$@(@t purl)}}
::
|= a/hiss ^- core-move
=^ upd ref (~(update-if-needed re ref) exchange)
?^ upd [[%send u.upd] (save tok ref)]
%.(a (out-add-header.s s-args))
::
:: If the last request refreshed the access token, save it.
++ res-save-after-refresh
|= a/httr ^- core-move
?. pending.ref [%give a]
=+ `{axs/token exp/@u}`(grab-expiring-token a)
=. ref (~(update re ref) exp)
[[%redo ~] (save axs ref)]
::
:: Exchange code in query string for access and refresh tokens. expects:
:: ++ bak bak-save-both-tokens :: save access token
++ in-code-to-token in-code-to-token.s
::
:: If valid access and refresh tokens have been returned, save them
++ bak-save-both-tokens
|= a/httr ^- core-move
=+ `{axs/token exp/@u ref-new/token}`(grab-both-tokens a)
=. tok.ref ref-new
=. ref (~(update re ref) exp)
[[%redo ~] (save axs ref)]
--
--
::
:: XX move-me
::
::
:::: Example "standard" sec/ core:
::
::
:: ::
:: :::: /hoon/my-api/com/sec
:: ::
:: /+ oauth2
:: ::
:: ::::
:: ::
:: |_ {bal/(bale keys:oauth2) tok/token:oauth2}
:: ++ aut (~(standard oauth2 bal tok) . |=(tok/token:oauth2 +>(tok tok)))
:: ++ out
:: %+ out-add-header:aut scope=/full
:: oauth-dialog='https://my-api.com/authorize'
:: ::
:: ++ in
:: %- in-code-to-token:aut
:: exchange-url='https://my-api.com/access_token'
:: ::
:: ++ bak bak-save-token:aut
:: --
::
::
:::: Equivalent imperative code:
::
::
:: ::
:: :::: /hoon/my-api/com/sec
:: ::
:: /+ oauth2
:: ::
:: ::::
:: ::
:: |_ {bal/(bale keys:oauth2) tok/token:oauth2}
:: ++ aut ~(. oauth2 bal tok)
:: ++ out :: add header
:: =+ aut
:: |= req/hiss ^- $%({$send hiss} {$show purl})
:: ?~ tok
:: [%show (auth-url scope=/full 'https://my-api.com/authorize')]
:: [%send (add-auth-header req)]
:: ::
:: ++ in :: code to token
:: =+ aut
:: |= inp/quay ^- {$send hiss}
:: =+ code=~|(%no-code (~(got by (malt inp)) %code))
:: [%send (request-token-by-code 'https://my-api.com/access_token' code)]
:: ::
:: ++ bak :: save token
:: =+ aut
:: |= bak/httr ^- $%({{$redo $~} _..bak} {$give httr})
:: ?: (bad-response bak) [%give bak]
:: =. tok (grab-token bak)
:: [[%redo ~] ..bak]
:: --
::
::: :::
::::: ::
::: :::
::
:::: Example "standard-refreshing" sec/ core:
::
::
:: ::
:: :::: /hoon/my-api/com/sec
:: ::
:: /+ oauth2
:: ::
:: ::::
:: ::
:: |_ {bal/(bale keys:oauth2) tok/token:oauth2 ref/refresh:oauth2}
:: ++ aut
:: %^ ~(standard-refreshing oauth2 bal tok) . ref
:: |=({tok/token ref/refresh}:oauth2 +>(tok tok, ref ref))
:: ::
:: ++ exchange-url 'https://my-api.com/access_token'
:: ++ out
:: %^ out-refresh-or-add-header:aut exchange-url
:: scope=/full
:: oauth-dialog='https://my-api.com/authorize'
:: ::
:: ++ res res-save-after-refresh:aut
:: ++ in (in-code-to-token:aut exchange-url)
:: ++ bak bak-save-both-tokens:aut
:: --
::
::
:::: Equivalent imperative code:
::
::
:: ::
:: :::: /hoon/my-api/com/sec
:: ::
:: /+ oauth2
:: ::
:: ::::
:: ::
:: |_ {bal/(bale keys:oauth2) axs/token:oauth2 ref/refresh:oauth2}
:: ++ aut ~(. oauth2 bal axs)
:: ++ exchange-url 'https://my-api.com/access_token'
:: ++ out :: refresh or add header
:: =+ aut
:: |= req/hiss ^- $^({{$send hiss} _..out} $%({$send hiss} {$show purl}))
:: ?~ axs
:: [%show (auth-url scope=/full 'https://my-api.com/authorize')]
:: =^ upd ref (~(update-if-needed re ref) exchange-url)
:: ?^ upd [[%send u.upd] ..out]
:: [%send (add-auth-header req)]
:: ::
:: ++ res :: save after refresh
:: =+ aut
:: |= a/httr ^- $^({{$redo $~} _..res} {$give httr})
:: ?. pending.ref [%give a]
:: =+ `{axs/token exp/@u}`(grab-expiring-token a)
:: [[%redo ~] ..out(axs axs, ref (~(update re ref) exp))]
:: ::
:: ++ in :: exchange token
:: =+ aut
:: |= inp/quay ^- {$send hiss}
:: =+ code=~|(%no-code (~(got by (malt inp)) %code))
:: [%send (request-token-by-code exchange-url code)]
::
:: ++ bak :: save both tokens
:: =+ aut
:: |= a/httr ^- {{$redo $~} _..res}
:: =+ `{axs/token exp/@u ref-new/token}`(grab-both-tokens a)
:: =. tok.ref ref-new
:: [[%redo ~] ..bak(axs axs, ref (~(update re ref) exp))]
:: ::
:: ::
:: ++ bak
:: =+ aut
:: |= bak/httr ^- $%({{$redo $~} _..bak} {$give httr})
:: ?: (bad-response bak) [%give bak]
:: =. tok (grab-token bak)
:: [[%redo ~] ..bak]
:: --
::

View File

@ -4,49 +4,18 @@
::
/? 314
/- twitter
/+ interpolate, hep-to-cab
=+ sur-twit:^twitter :: XX
!:
:::: functions
::
|%
++ fass :: rewrite path
|= a/path
%+ turn a
|=(b/@t (gsub '-' '_' b))
::
++ gsub :: replace chars
|= {a/@t b/@t t/@t}
^- @t
?: =('' t) t
%+ mix (lsh 3 1 $(t (rsh 3 1 t)))
=+ c=(end 3 1 t)
?:(=(a c) b c)
::
++ join
|= {a/char b/(list @t)} ^- @t
%+ rap 3
?~ b ~
|-(?~(t.b b [i.b a $(b t.b)]))
::
++ interpolate-some :: [/a/:b/c [d+'bar' b+'foo']~] -> [/a/foo/c [d+'bar']~]
|= {pax/path quy/quay} ^- {path quay}
=+ ^= inline :: required names
%- ~(gas in *(set term))
(murn pax replacable:interpolate-path)
=^ inter quy
(skid quy |=({a/knot @} (~(has in inline) a)))
[(interpolate-path pax inter) quy]
::
++ interpolate-path :: [/a/:b/c [%b 'foo']~] -> /a/foo/c
=+ replacable=|=(a/knot `(unit term)`(rush a ;~(pfix col sym)))
|= {a/path b/(list (pair term knot))} ^- path
?~ a ?~(b ~ ~|(unused-values+b !!))
=+ (replacable i.a)
?~ - [i.a $(a t.a)] :: literal value
?~ b ~|(no-value+u !!)
?. =(u p.i.b) ~|(mismatch+[u p.i.b] !!)
[q.i.b $(a t.a, b t.b)]
::
++ valve :: produce request
|= {med/?($get $post) pax/path quy/quay}
^- hiss
@ -82,7 +51,7 @@
++ parse :: json reparsers
|%
++ ce |*({a/_* b/fist:jo} (cu:jo |=(c/a c) b)) :: output type
++ fasp |*(a/{@tas *} [(gsub '-' '_' -.a) +.a]) :: XX usable electroplating
++ fasp |*(a/{@tas *} [(hep-to-cab -.a) +.a]) :: XX usable electroplating
++ user (cook crip (plus ;~(pose aln cab)))
++ mean (ot errors+(ar (ot message+so code+ni ~)) ~):jo
++ stat
@ -149,12 +118,13 @@
quy/quay
==
^- {path quay}
%+ interpolate-some (fass pax)
%+ into-path-partial:interpolate
(path:hep-to-cab pax)
=- (weld - quy)
%+ turn ban
|= p/param
^- {@t @t}
:- (gsub '-' '_' -.p)
:- (hep-to-cab -.p)
?+ -.p p.p :: usually plain text
?($source-id $target-id) (tid:print p.p)
?($follow $id $name $user-id) (lid:print p.p)

View File

@ -1,6 +1,6 @@
:: Twitter status
::
:::: /hoon/stat/twit/mar
:::: /hoon/status/twit/mar
::
/+ twitter, httr-to-json
|_ stat:twitter

41
sec/com/asana.hoon Normal file
View File

@ -0,0 +1,41 @@
:: Test url +https://app.asana.com/api/1.0/users/me
::
:::: /hoon/asana/com/sec
::
/+ oauth2
::
::::
::
|%
++ dialog-url 'https://app.asana.com/-/oauth_authorize?response_type=code'
++ exchange-url 'https://app.asana.com/-/oauth_token'
--
::
::::
::
|_ {bal/(bale keys:oauth2) tok/token:oauth2}
:: ++aut is a "standard oauth2" core, which implements the
:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
:: and examples at the bottom of the file.
++ aut (~(standard oauth2 bal tok) . |=(tok/token:oauth2 +>(tok tok)))
++ out (out-add-header:aut scope=~ dialog-url)
::
++ in (in-code-to-token:aut exchange-url)
++ bak bak-save-token:aut
--
:: create a developer app by logging into https://app.asana.com/, and clicking
:: "My Profile Settings" > Apps > "Manage my developer apps"
:: Be sure to be on https://localhost:8443 and to have registered
:: 'http://localhost:8443/~/ac/asana.com/~./in' as the redirect URI.
:: (If unable to change port number of ship, change the redirect URI port in %eyre)
:: |init-oauth2 /com/asana
:: Enter this sample command to get your user information:
:: +https://app.asana.com/api/1.0/users/me
:: Before you receive the response, you'll have to clink on the link.
:: If you successfully auth, you should receive the response in the dojo.

40
sec/com/digitalocean.hoon Normal file
View File

@ -0,0 +1,40 @@
:: Test url +https://api.digitalocean.com/v2/account
::
:::: /hoon/digitalocean/com/sec
::
/+ oauth2
::
::::
::
|%
++ dialog-url 'https://cloud.digitalocean.com/v1/oauth/authorize?response_type=code'
++ exchange-url 'https://cloud.digitalocean.com/v1/oauth/token'
--
::
::::
::
|_ {bal/(bale keys:oauth2) tok/token:oauth2}
:: ++aut is a "standard oauth2" core, which implements the
:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
:: and examples at the bottom of the file.
++ aut (~(standard oauth2 bal tok) . |=(tok/token:oauth2 +>(tok tok)))
++ out (out-add-header:aut scope=~[%read %write] dialog-url)
::
++ in (in-code-to-token:aut exchange-url)
++ bak bak-save-token:aut
--
:: create a developer app on https://cloud.digitalocean.com/settings/api/applications/new
:: to get a client id and secret
:: Be sure to be on https://localhost:8443 and to have registered
:: 'http://localhost:8443/~/ac/digitalocean.com/~./in' as the redirect URI.
:: (If unable to change port number of ship, change the redirect URI port in %eyre)
:: |init-oauth2 |init-oauth2 /com/digitalocean
:: Enter home this sample command to get your user information:
:: +https://api.digitalocean.com/v2/account
:: Before you receive the response, you'll have to clink on the link.
:: If you successfully auth, you should receive the response in the dojo.

View File

@ -1,22 +1,41 @@
:: Test url +https://api.dropboxapi.com/2/files/list_folder
:: Test url +https://api.dropboxapi.com/2/users/get_current_account &json ~
::
:::: /hoon/dropboxapi/com/sec
::
/+ oauth2
::
::::
::
=+ ^= aut
%+ oauth2
'https://www.dropbox.com/1/oauth2/authorize?response_type=code'
'https://api.dropboxapi.com/1/oauth2/token'
|_ {(bale keys:oauth2) tok/token.aut}
++ aut ~(. ^aut +<- /)
++ out
|= a/hiss
=; mow ~& db-authorized+mow mow
%. a
(out-math:aut tok)
++ in in-code:aut
++ bak (bak-save-access:aut . |=(tok/token:aut +>(tok tok)))
|%
++ dialog-url 'https://www.dropbox.com/1/oauth2/authorize?response_type=code'
++ exchange-url 'https://api.dropboxapi.com/1/oauth2/token'
--
::
::
::::
::
|_ {bal/(bale keys:oauth2) tok/token:oauth2}
:: ++aut is a "standard oauth2" core, which implements the
:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
:: and examples at the bottom of the file.
++ aut (~(standard oauth2 bal tok) . |=(tok/token:oauth2 +>(tok tok)))
++ out (out-add-header:aut scope=~ dialog-url)
::
++ in (in-code-to-token:aut exchange-url)
++ bak bak-save-token:aut
--
:: create a developer app on https://www.dropbox.com/developers-v1/apps to get a
:: client id and secret.
:: Be sure to be on https://localhost:8443 and to have registered
:: 'http://localhost:8443/~/ac/dropboxapi.com/~./in' as the redirect URI.
:: (If unable to change port number of ship, change the redirect URI port in %eyre)
:: |init-oauth2 |init-oauth2 /com/dropbox
:: Enter this sample command to show your user info:
:: +https://api.dropboxapi.com/2/users/get_current_account &json ~
:: Before you receive the response, you'll have to click on the link in the
:: dojo to authenticate yourself.
:: You should receive a response listing the contents of that directory.

View File

@ -6,21 +6,37 @@
::
::::
::
=+ ^= aut
%+ oauth2
dialog='https://www.facebook.com/dialog/oauth?response_type=code'
exchange='https://graph.facebook.com/v2.3/oauth/access_token'
|_ {bal/(bale keys.aut) access-token/token.aut}
++ auth ~(. aut bal /'user_about_me'/'user_posts')
++ out (out-quay:auth key='access_token' value=access-token)
++ in in-code:auth
++ bak
%- (bak-parse:auth . access-token.aut expires-in.aut ~)
|= {access-token/@t expires-in/@u}
?: (lth expires-in ^~((div ~d7 ~s1))) :: short-lived token
%^ toke-req:auth grant-type='fb_exchange_token'
[key='fb_exchange_token' value=access-token]
~
[[%redo ~] ..bak(access-token access-token)]
::++ wyp ~
|%
++ dialog-url 'https://www.facebook.com/dialog/oauth?response_type=code'
++ exchange-url 'https://graph.facebook.com/v2.3/oauth/access_token'
--
::
::::
::
|_ {bal/(bale keys:oauth2) access-token/token:oauth2}
:: ++aut is a "standard oauth2" core, which implements the
:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
:: and examples at the bottom of the file.
++ aut
%+ ~(standard oauth2 bal access-token) .
|=(access-token/token:oauth2 +>(access-token access-token))
::
++ out
%^ out-add-query-param:aut 'access_token'
scope=~['user_about_me' 'user_posts']
dialog-url
::
++ in (in-code-to-token:aut exchange-url)
::
++ bak
|= a/httr ^- core-move:aut
?: (bad-response:aut p.a)
[%give a] :: [%redo ~] :: handle 4xx?
=+ `{access-token/@t expires-in/@u}`(grab-expiring-token:aut a)
?. (lth expires-in ^~((div ~d7 ~s1))) :: short-lived token
[[%redo ~] ..bak(access-token access-token)]
:- %send
%^ request-token:aut exchange-url
grant-type='fb_exchange_token'
[key='fb_exchange_token' value=access-token]~
--

View File

@ -5,5 +5,6 @@
/+ basic-auth
!:
|_ {bal/(bale keys:basic-auth) $~}
++ out (basic-auth bal)
++ aut ~(standard basic-auth bal ~)
++ out out-adding-header:aut
--

View File

@ -2,7 +2,7 @@
::
:::: /hoon/googleapis/com/sec
::
/+ oauth2
/+ oauth2, interpolate, hep-to-cab
::
::::
::
@ -18,40 +18,38 @@
++ auth-usr
|= usr/iden
=+ lon=(fall (slaw %t usr) usr)
=< .(state-usr &)
%- oauth2
:_ exchange='https://www.googleapis.com/oauth2/v4/token'
^= dialog
%* . (need (epur 'https://accounts.google.com/o/oauth2/v2/auth'))
r
%- fass:oauth2
:~ login-hint+?~(lon '' (crip (rash lon suffix-email)))
access-type+%offline
response-type+%code
prompt+%consent
==
%+ add-query:interpolate 'https://accounts.google.com/o/oauth2/v2/auth'
%- quay:hep-to-cab
:~ login-hint+?~(lon '' (crip (rash lon suffix-email)))
access-type+%offline
response-type+%code
prompt+%consent
==
--
!:
::::
::
|_ {bal/(bale keys:oauth2) user-state}
++ auth-re ~(. (re:auth .) ref |=(a/_ref +>(ref a)))
++ auth ~(. (auth-usr usr.bal) bal scopes)
++ scopes
:~ 'https://mail.google.com'
'https://www.googleapis.com/auth/plus.me'
'https://www.googleapis.com/auth/userinfo.email'
==
::
++ out (out-fix-expired:auth-re (out-math:auth ber))
++ res |=(a/httr ((res-handle-refreshed:auth-re save-access res-give:auth) a))
::
++ save-access |=(a/cord:[token:oauth2] +>(ber a))
::
++ in
|= a/quay
(in-code:auth a)
++ bak |=(a/httr ((bak-save-tokens:auth-re save-access) a))
++ upd *user-state
++ exchange-url 'https://www.googleapis.com/oauth2/v4/token'
--
!:
::::
::
|_ {bal/(bale keys:oauth2) own/user-state}
:: ++auth is a "standard refreshing oauth2" core, which implements the
:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
:: and examples at the bottom of the file.
++ auth
=+ a=~(standard-refreshing oauth2 bal ber.own)
(a(state-usr &) ..auth ref.own |=(a/user-state ..auth(own a)))
::
++ out (out-refresh-or-add-header:auth exchange-url scopes dialog-url)
++ dialog-url (auth-usr usr.bal)
::
++ res res-save-after-refresh:auth
::
++ in (in-code-to-token:auth exchange-url)
++ bak bak-save-both-tokens:auth
:: ++ upd *user-state
--

42
sec/com/instagram.hoon Normal file
View File

@ -0,0 +1,42 @@
:: Test url +https://api.instagram.com/v1/users/self
::
:::: /hoon/instagram/com/sec
::
/+ oauth2
::
::::
::
|%
++ dialog-url 'https://api.instagram.com/oauth/authorize?response_type=code'
++ exchange-url 'https://api.instagram.com/oauth/access_token'
--
::
::::
::
|_ {bal/(bale keys:oauth2) tok/token:oauth2}
:: ++aut is a "standard oauth2" core, which implements the
:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
:: and examples at the bottom of the file.
++ aut (~(standard oauth2 bal tok) . |=(tok/token:oauth2 +>(tok tok)))
++ out
%^ out-add-query-param:aut 'access_token'
scope=~[%basic]
dialog-url
::
++ in (in-code-to-token:aut exchange-url)
++ bak bak-save-token:aut
--
:: create a developer app on https://www.instagram.com/developer/ to get a
:: client id and secret
:: Be sure to be on https://localhost:8443, and to have registered
:: http://localhost:8443/~/ac/instagram.com/~./in as the redirect URI.
:: (If unable to change port number of ship, change the redirect URI port in %eyre)
:: |init-oauth2 |init-oauth2 /com/instagram
:: Enter this sample command to get your user information:
:: +https://api.instagram.com/v1/users/self
:: Before you receive the response, you'll have to clink on the link to
:: authenicate yourself. You should then receive the response.

View File

@ -6,13 +6,16 @@
::
::::
::
=+ ^= aut
%+ oauth2
'https://slack.com/oauth/authorize'
'https://slack.com/api/oauth.access'
|_ {(bale keys:oauth2) tok/token.aut}
++ aut ~(. ^aut +<- /client/admin)
++ out (out-quay:aut 'token'^tok)
++ in in-code:aut
++ bak (bak-save-access:aut . |=(tok/token:aut +>(tok tok)))
|_ {bal/(bale keys:oauth2) tok/token:oauth2}
:: ++aut is a "standard oauth2" core, which implements the
:: most common handling of oauth2 semantics. see lib/oauth2 for more details,
:: and examples at the bottom of the file.
++ aut (~(standard oauth2 bal tok) . |=(tok/token:oauth2 +>(tok tok)))
++ out
%^ out-add-query-param:aut 'token'
scope=~[%client %admin]
oauth-dialog='https://slack.com/oauth/authorize'
::
++ in (in-code-to-token:aut url='https://slack.com/api/oauth.access')
++ bak bak-save-token:aut
--

View File

@ -1,22 +1,27 @@
:: Test url +https://api.twitter.com/1.1/account/verify_credentials.json
::
::
:::: /hoon/twitter/com/sec
::
/+ oauth1
!:
::::
::
=+ ^= aut
%^ oauth1
'https://api.twitter.com/oauth/request_token'
'https://api.twitter.com/oauth/authorize'
'https://api.twitter.com/oauth/access_token'
|_ {(bale keys:oauth1) tok/token:oauth1}
++ aut ~(. ^aut . +<- +<+) :: XX electroplating
++ out out-math:aut
++ in in-oauth-token:aut
++ bak (bak-save-access:aut save-token)
++ res (res-handle-reqt:aut save-token)
++ save-token |=(tok/token:aut +>(tok tok))
::++ wyp ~
|_ {bal/(bale keys:oauth1) tok/token:oauth1}
:: ++aut is a "standard oauth1" core, which implements the
:: most common handling of oauth1 semantics. see lib/oauth1 for more details,
:: and examples at the bottom of the file.
++ aut (~(standard oauth1 bal tok) . |=(tok/token:oauth1 +>(tok tok)))
++ out
%+ out-add-header:aut
token-request='https://api.twitter.com/oauth/request_token'
oauth-dialog='https://api.twitter.com/oauth/authorize'
::
++ res res-handle-request-token:aut
::
++ in
%- in-exchange-token:aut
exchange-url='https://api.twitter.com/oauth/access_token'
::
++ bak bak-save-token:aut
:: ++ wyp ~
--