Outdated egg!

This is an egg for CHICKEN 4, the unsupported old release. You're almost certainly looking for the CHICKEN 5 version of this egg, if it exists.

If it does not exist, there may be equivalent functionality provided by another egg; have a look at the egg index. Otherwise, please consider porting this egg to the current version of CHICKEN.

OAuth

  1. Outdated egg!
  2. OAuth
    1. Description
    2. Author
    3. Repository
    4. Requirements
    5. API
      1. oauth-client
        1. empty-credential
        2. make-oauth-credential
        3. token
        4. secret
        5. make-oauth-service-provider
        6. make-oauth-service
        7. oauth-service
        8. oauth-protocol-parameters
        9. oauth-token-credential
        10. with-oauth
        11. authenticated-call-with-input-request
        12. call-with-input-request
        13. acquire-temporary-credential
        14. authorize-resource-owner
        15. acquire-token-credential
    6. Examples
      1. OAuth 1.0 Flow (no verifier)
      2. OAuth 1.0a Flow (with verifier)
    7. License
    8. Version History

Description

OAuth 1.0, 1.0a & RFC 5849

Author

Andy Bennett

Repository

https://bitbucket.org/knodium/oauth

Requirements

API

oauth-client

empty-credential
make-oauth-credential
[procedure] (make-oauth-credential identifier secret)

Returns a credential

Credentials are a pair of a unique identifier and a matching
shared secret.  OAuth defines three classes of credentials:
client, temporary, and token, used to identify and authenticate
the client making the request, the authorization request, and
the access grant, respectively.
  -- RFC 5849

You will need to turn your app token and app secret into a credential.

If you store token credentials persistently then you can recombine the identifier and secret with this procedure.

token
[procedure] (token credential)

Extracts the identifier part of the credential and returns it.

You will need this procedure in order to store credentials.

secret
[procedure] (secret credential)

Extracts the secret part of the credential and returns it.

You will need this procedure in order to store credentials.

make-oauth-service-provider
[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))

Defines an OAuth service provider.

Specifies:

The service provider definition returned from this procedure must be combined with a client credential before it can be used as part of a request.

make-oauth-service
[procedure] (make-oauth-service #!key service client-credential)

Combines an OAuth service provider definition (from make-oauth-service-provider) with a client credential to produce something that can be used for API requests.

oauth-service
[parameter] oauth-service

Used to store the service passed to with-oauth.

oauth-protocol-parameters
[parameter] oauth-protocol-parameters

Used to store the protocol-parameters to pass to requests made within a with-oauth scope.

oauth-token-credential
[parameter] oauth-token-credential

Used to store the token-credential passed to with-oauth.

with-oauth
[procedure] (with-oauth service token-credential thunk)

Execute thunk in an environment where call-with-input-request is bound to a procedure that will sign the request with the supplied OAuth credentials but otherwise behave similarly to call-with-input-request from http-client.

This is the procedure that you probably want to use to wrap API calls.

authenticated-call-with-input-request
[procedure] (authenticated-call-with-input-request service protocol-parameters token-credential uri-or-request writer reader)

Similar to call-with-input-request from http-client but will sign the request using the OAuth arguments supplied.

call-with-input-request
[procedure] (call-with-input-request uri-or-request writer reader)

Similar to call-with-input-request from http-client but will sign the request using the OAuth parameters oauth-service oauth-protocol-parameters and oauth-token-credential.

You probably don't want to use this procedure directly: use with-oauth instead.

acquire-temporary-credential
[procedure] (acquire-temporary-credential service #!optional callback-url)

This is the first step in the three step Redirection-Based Authorization defined in OAuth.

  1.  The client obtains a set of temporary credentials from the server
      (in the form of an identifier and shared-secret).  The temporary
      credentials are used to identify the access request throughout
      the authorization process.
        -- RFC 5849, Section 2

If you are speaking OAuth 1.0a or RFC 5849 then you must specify callback-url at this stage rather than at the authorize-resource-owner stage.

authorize-resource-owner
[procedure] (authorize-resource-owner service temporary-credential #!optional callback-url)

This is the second step in the three step Redirection-Based Authorization defined in OAuth.

  2.  The resource owner authorizes the server to grant the client's
      access request (identified by the temporary credentials).
        -- RFC 5849, Section 2

This procedure returns a URI. It is up to you to redirect the user to this URI and handle the subsequent redirect back to a URI that you control once the user has granted the authorization.

If you are speaking OAuth 1.0 then you may supply callback-url at this stage, otherwise you must not.

acquire-token-credential
[procedure] (acquire-token-credential service temporary-credential #!optional verifier)

This is the third step in the three step Redirection-Based Authorization defined in OAuth.

  3.  The client uses the temporary credentials to request a set of
      token credentials from the server, which will enable it to access
      the resource owner's protected resources.
        -- RFC 5849, Section 2

When the user returns from the authorization step (authorize-resource-owner) you must exchange their temporary credential for a token credential using this procedure.

This procedure will return a token credential that you can save, and reuse along with your oauth-service (make-oauth-service), in order to make signed API calls on behalf of the authorized user.

Once you have obtained the token-credential returned by this procedure you can use with-oauth to make API calls to arbitrary HTTP endpoints.

Examples

OAuth 1.0 Flow (no verifier)

You will need some Dropbox App Credentials to follow this example https://www.dropbox.com/developers/apps

(define dropbox (make-oauth-service-provider
		 protocol-version: 1.0
		 credential-request-url: "https://api.dropbox.com/1/oauth/request_token"
		 owner-auth-url: "https://www.dropbox.com/1/oauth/authorize"
		 token-request-url: "https://api.dropbox.com/1/oauth/access_token"
		 signature-method: 'plaintext))
(define dropbox-app
  (make-oauth-service
    service: dropbox
    client-credential: (make-oauth-credential "<token>" "<secret>")))
(define x (acquire-temporary-credential dropbox-app))
(use uri-common)
(uri->string (authorize-resource-owner dropbox-app x "http://wiki.call-cc.org/eggref/4/oauth"))
(define save-me (acquire-token-credential dropbox-app x))
(with-oauth dropbox-app save-me
 (lambda ()
  (call-with-input-request "https://api.dropbox.com/1/account/info" #f (cut read-string #f <>))))

OAuth 1.0a Flow (with verifier)

You will need some Twitter App Credentials to follow this example https://apps.twitter.com/

;;;;;
; Bare minimum twitter binding
(use oauth-client uri-common rest-bind medea)
(define twitter (make-oauth-service-provider
		  protocol-version: '1.0a
		  credential-request-url: "https://api.twitter.com/oauth/request_token"
		  owner-auth-url: "https://api.twitter.com/oauth/authorize"
		  token-request-url: "https://api.twitter.com/oauth/access_token"
		  signature-method: 'hmac-sha1))
(define twitter-app
  (make-oauth-service
    service: twitter
    client-credential: (make-oauth-credential
			 "<token>"
			 "<secret>")))
; Lots of web services, including Twitter, don't accept ';' separated query strings so
; use '&' for encoding by default but support both '&' and ';' for decoding.
(form-urlencoded-separator "&;")
; https://dev.twitter.com/rest/reference/get/account/verify_credentials
(define-method (verify-credentials #!key include_entities skip_status)
  "https://api.twitter.com/1.1/account/verify_credentials.json"
  #f read-json #f)
;;;;;
;;;;;
; Acquire some credentials
(define x (acquire-temporary-credential twitter-app))
(uri->string (authorize-resource-owner twitter-app x))
; Visit the supplied URL in browser, allow app and retrieve verifier
(define me (acquire-token-credential twitter-app x <VERIFIER>))
; Example usage of binding
; include_entities: false still seems to include the entities node??
(pp
  (with-oauth twitter-app me
	      (lambda ()
		(verify-credentials skip_status: "true" include_entities: "false"))))
;;;;;

License

 Copyright (C) 2012, Andy Bennett
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 
 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.
 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following disclaimer in the documentation
 and/or other materials provided with the distribution.
 Neither the name of the author nor the names of its contributors may be
 used to endorse or promote products derived from this software without
 specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.

Version History