source: project/wiki/eggref/4/oauth @ 37108

Last change on this file since 37108 was 37108, checked in by andyjpb, 6 months ago
File size: 10.4 KB
Line 
1[[tags: egg]]
2
3== OAuth
4
5[[toc:]]
6
7=== Description
8
9OAuth 1.0, 1.0a & RFC 5849
10
11* http://oauth.net/core/1.0/
12* http://oauth.net/core/1.0a/
13* http://tools.ietf.org/html/rfc5849
14
15=== Author
16
17[[/users/andyjpb|Andy Bennett]]
18
19=== Repository
20
21[[https://bitbucket.org/knodium/oauth|https://bitbucket.org/knodium/oauth]]
22
23=== Requirements
24
25* [[uri-common]] [[intarweb]] [[http-client]] [[hmac]] [[sha1]] [[base64]]
26
27=== API
28
29==== oauth-client
30
31===== empty-credential
32===== make-oauth-credential
33
34<procedure>(make-oauth-credential identifier secret)</procedure>
35
36Returns a credential
37
38        Credentials are a pair of a unique identifier and a matching
39        shared secret.  OAuth defines three classes of credentials:
40        client, temporary, and token, used to identify and authenticate
41        the client making the request, the authorization request, and
42        the access grant, respectively.
43          -- RFC 5849
44
45You will need to turn your app token and app secret into a credential.
46
47If you store token credentials persistently then you can recombine the
48identifier and secret with this procedure.
49
50
51===== token
52
53<procedure>(token credential)</procedure>
54
55Extracts the identifier part of the credential and returns it.
56
57You will need this procedure in order to store credentials.
58
59
60===== secret
61
62<procedure>(secret credential)</procedure>
63
64Extracts the secret part of the credential and returns it.
65
66You will need this procedure in order to store credentials.
67
68
69===== make-oauth-service-provider
70
71<procedure>(make-oauth-service-provider #!key protocol-version signature-method owner-auth-url credential-request-url (credential-request-method 'POST) token-request-url (token-request-method 'POST) (transmission-method 'authorization-header))</procedure>
72
73Defines an OAuth service provider.
74
75Specifies:
76* Which version of the protocol and how we want to speak to them.
77* The 3 URIs for Redirection-Based Authorization (RFC5849, Section 2.
78
79The service provider definition returned from this procedure must be combined
80with a client credential before it can be used as part of a request.
81
82
83===== make-oauth-service
84
85<procedure>(make-oauth-service #!key service client-credential)</procedure>
86
87Combines an OAuth service provider definition (from
88{{make-oauth-service-provider}}) with a client credential to produce something
89that can be used for API requests.
90
91
92===== oauth-service
93
94<parameter>oauth-service</parameter>
95
96Used to store the service passed to {{with-oauth}}.
97
98
99===== oauth-protocol-parameters
100
101<parameter>oauth-protocol-parameters</parameter>
102
103Used to store the protocol-parameters to pass to requests made within a
104{{with-oauth}} scope.
105
106
107===== oauth-token-credential
108
109<parameter>oauth-token-credential</parameter>
110
111Used to store the token-credential passed to {{with-oauth}}.
112
113
114===== with-oauth
115
116<procedure>(with-oauth service token-credential thunk)</procedure>
117
118Execute {{thunk}} in an environment where {{call-with-input-request}} is bound
119to a procedure that will sign the request with the supplied OAuth credentials
120but otherwise behave similarly to {{call-with-input-request}} from {{http-client}}.
121
122This is the procedure that you probably want to use to wrap API calls.
123
124
125===== authenticated-call-with-input-request
126
127<procedure>(authenticated-call-with-input-request service protocol-parameters token-credential uri-or-request writer reader)</procedure>
128
129Similar to {{call-with-input-request}} from {{http-client}} but will sign the
130request using the OAuth arguments supplied.
131
132===== call-with-input-request
133
134<procedure>(call-with-input-request uri-or-request writer reader)</procedure>
135
136Similar to {{call-with-input-request}} from {{http-client}} but will sign the
137request using the OAuth parameters {{oauth-service}}
138{{oauth-protocol-parameters}} and {{oauth-token-credential}}.
139
140You probably don't want to use this procedure directly: use {{with-oauth}} instead.
141
142
143===== acquire-temporary-credential
144
145<procedure>(acquire-temporary-credential service #!optional callback-url)</procedure>
146
147This is the first step in the three step Redirection-Based Authorization
148defined in OAuth.
149
150   1.  The client obtains a set of temporary credentials from the server
151       (in the form of an identifier and shared-secret).  The temporary
152       credentials are used to identify the access request throughout
153       the authorization process.
154         -- RFC 5849, Section 2
155
156If you are speaking OAuth 1.0a or RFC 5849 then you must specify callback-url at
157this stage rather than at the {{authorize-resource-owner}} stage.
158
159
160===== authorize-resource-owner
161
162<procedure>(authorize-resource-owner service temporary-credential #!optional callback-url)</procedure>
163
164This is the second step in the three step Redirection-Based Authorization
165defined in OAuth.
166
167   2.  The resource owner authorizes the server to grant the client's
168       access request (identified by the temporary credentials).
169         -- RFC 5849, Section 2
170
171This procedure returns a URI. It is up to you to redirect the user to this URI
172and handle the subsequent redirect back to a URI that you control once the user
173has granted the authorization.
174
175If you are speaking OAuth 1.0 then you may supply callback-url at this stage,
176otherwise you must not.
177
178
179===== acquire-token-credential
180
181<procedure>(acquire-token-credential service temporary-credential #!optional verifier)</procedure>
182
183This is the third step in the three step Redirection-Based Authorization
184defined in OAuth.
185
186   3.  The client uses the temporary credentials to request a set of
187       token credentials from the server, which will enable it to access
188       the resource owner's protected resources.
189         -- RFC 5849, Section 2
190
191When the user returns from the authorization step ({{authorize-resource-owner}})
192you must exchange their temporary credential for a token credential using this
193procedure.
194
195This procedure will return a token credential that you can save, and reuse along
196with your oauth-service ({{make-oauth-service}}), in order to make signed API
197calls on behalf of the authorized user.
198
199Once you have obtained the token-credential returned by this procedure you can
200use {{with-oauth}} to make API calls to arbitrary HTTP endpoints.
201
202
203=== Examples
204
205==== OAuth 1.0 Flow (no verifier)
206
207You will need some Dropbox App Credentials to follow this example
208https://www.dropbox.com/developers/apps
209
210        (define dropbox (make-oauth-service-provider
211                         protocol-version: 1.0
212                         credential-request-url: "https://api.dropbox.com/1/oauth/request_token"
213                         owner-auth-url: "https://www.dropbox.com/1/oauth/authorize"
214                         token-request-url: "https://api.dropbox.com/1/oauth/access_token"
215                         signature-method: 'plaintext))
216
217        (define dropbox-app
218          (make-oauth-service
219            service: dropbox
220            client-credential: (make-oauth-credential "<token>" "<secret>")))
221
222        (define x (acquire-temporary-credential dropbox-app))
223
224        (use uri-common)
225        (uri->string (authorize-resource-owner dropbox-app x "http://wiki.call-cc.org/eggref/4/oauth"))
226
227        (define save-me (acquire-token-credential dropbox-app x))
228        (with-oauth dropbox-app save-me
229         (lambda ()
230          (call-with-input-request "https://api.dropbox.com/1/account/info" #f (cut read-string #f <>))))
231
232==== OAuth 1.0a Flow (with verifier)
233
234You will need some Twitter App Credentials to follow this example
235https://apps.twitter.com/
236
237        ;;;;;
238        ; Bare minimum twitter binding
239        (use oauth-client uri-common rest-bind medea)
240
241        (define twitter (make-oauth-service-provider
242                          protocol-version: '1.0a
243                          credential-request-url: "https://api.twitter.com/oauth/request_token"
244                          owner-auth-url: "https://api.twitter.com/oauth/authorize"
245                          token-request-url: "https://api.twitter.com/oauth/access_token"
246                          signature-method: 'hmac-sha1))
247
248        (define twitter-app
249          (make-oauth-service
250            service: twitter
251            client-credential: (make-oauth-credential
252                                 "<token>"
253                                 "<secret>")))
254
255        ; Lots of web services, including Twitter, don't accept ';' separated query strings so
256        ; use '&' for encoding by default but support both '&' and ';' for decoding.
257        (form-urlencoded-separator "&;")
258
259        ; https://dev.twitter.com/rest/reference/get/account/verify_credentials
260        (define-method (verify-credentials #!key include_entities skip_status)
261          "https://api.twitter.com/1.1/account/verify_credentials.json"
262          #f read-json #f)
263        ;;;;;
264
265
266        ;;;;;
267        ; Acquire some credentials
268        (define x (acquire-temporary-credential twitter-app))
269        (uri->string (authorize-resource-owner twitter-app x))
270
271        ; Visit the supplied URL in browser, allow app and retrieve verifier
272        (define me (acquire-token-credential twitter-app x <VERIFIER>))
273
274        ; Example usage of binding
275        ; include_entities: false still seems to include the entities node??
276        (pp
277          (with-oauth twitter-app me
278                      (lambda ()
279                        (verify-credentials skip_status: "true" include_entities: "false"))))
280        ;;;;;
281
282
283=== License
284
285  Copyright (C) 2012, Andy Bennett
286  All rights reserved.
287 
288  Redistribution and use in source and binary forms, with or without
289  modification, are permitted provided that the following conditions are met:
290 
291  Redistributions of source code must retain the above copyright notice, this
292  list of conditions and the following disclaimer.
293  Redistributions in binary form must reproduce the above copyright notice,
294  this list of conditions and the following disclaimer in the documentation
295  and/or other materials provided with the distribution.
296  Neither the name of the author nor the names of its contributors may be
297  used to endorse or promote products derived from this software without
298  specific prior written permission.
299 
300  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
301  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
302  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
303  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
304  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
305  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
306  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
307  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
308  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
309  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
310  POSSIBILITY OF SUCH DAMAGE.
311
312=== Version History
313* 0.1, (2012/10/30) : Initial OAuth 1.0, 1.0a RFC 5849 client
314* 0.2, (2014/12/18) : HMAC-SHA1 signature algorithm. Bug fixes for 1.0a and RFC 5849 serialisation and verifiers.
315* 0.3, (2019/01/21) : oauth_timestamp header formatting fix from Evan Hanson. CHICKEN 5 Port.
Note: See TracBrowser for help on using the repository browser.