-
Notifications
You must be signed in to change notification settings - Fork 204
/
oauth2.factor
101 lines (83 loc) · 2.82 KB
/
oauth2.factor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
! Copyright (C) 2016 Björn Lindqvist.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs calendar combinators http.client io
json.reader kernel make math.order sequences unicode urls webbrowser ;
IN: oauth2
! Random utility
: set-query-params ( url params -- url )
[ first2 swap set-query-param ] each ;
: string+params>url ( string params -- url )
[ >url ] dip set-query-params ;
: console-prompt ( query -- str/f )
write flush readln [ blank? ] trim
dup "" = [ drop f ] [ ] if ;
: post-json-request ( params token-uri -- assoc )
<post-request> dup header>> "application/json" "Accept" rot set-at
http-request nip json> ;
TUPLE: tokens access refresh expiry ;
: assoc>expiry ( json -- expiry )
"expires_in" of [ seconds now time+ ] [ f ] if* ;
: assoc>tokens ( json -- tokens )
[ "access_token" of ]
[ "refresh_token" of ]
[ assoc>expiry ] tri tokens boa ;
: access-expired? ( tokens -- ? )
expiry>> [ now before? ] [ f ] if* ;
: update-tokens ( tokens1 tokens2 -- tokens1 )
2dup expiry>> >>expiry drop access>> >>access ;
TUPLE: oauth2
auth-uri
token-uri
redirect-uri
client-id
client-secret
scope
extra-params ;
: tokens-params ( oauth2 code -- params )
[
"code" ,,
{
[ client-id>> "client_id" ,, ]
[ client-secret>> "client_secret" ,, ]
[ redirect-uri>> "redirect_uri" ,, ]
[ extra-params>> %% ]
} cleave
"authorization_code" "grant_type" ,,
] { } make ;
: refresh-params ( oauth2 refresh -- params )
[
"refresh_token" ,,
[ client-id>> "client_id" ,, ]
[ client-secret>> "client_secret" ,, ]
[ extra-params>> %% ] tri
"refresh_token" "grant_type" ,,
] { } make ;
: auth-params ( oauth2 -- params )
[
{
[ client-id>> "client_id" ,, ]
[ scope>> "scope" ,, ]
[ redirect-uri>> "redirect_uri" ,, ]
[ extra-params>> %% ]
} cleave
"code" "response_type" ,,
"offline" "access_type" ,,
] { } make ;
: oauth2>auth-uri ( oauth2 -- uri )
[ auth-uri>> ] [ auth-params ] bi string+params>url ;
! Other flows can be useful to support too.
: console-flow ( oauth2 -- tokens/f )
dup oauth2>auth-uri open-url
"Enter verification code: " console-prompt
[
dupd tokens-params swap token-uri>> post-json-request
assoc>tokens
] [ drop f ] if* ;
: refresh-flow ( oauth2 tokens -- tokens' )
dupd refresh>> refresh-params swap token-uri>> post-json-request
assoc>tokens ;
! Using the token to access secured resources.
: add-token ( request url -- )
"Bearer " prepend "Authorization" rot header>> set-at ;
: oauth-http-get ( url access-token -- response data )
[ <get-request> dup ] dip add-token http-request ;