public
Description: An HTTP proxy for signing OAuth requests
Clone URL: git://github.com/mojodna/oauth-proxy.git
spaces to tabs
mojodna (author)
Fri May 02 08:13:22 -0700 2008
commit  4c8a589db43ae8d3b3a88a90931e09aac4183480
tree    c1d53d46f33b5a74c0ab5f07dfb3e4a03d0c362e
parent  6632e8c1d0dbd6a3aef4b4d761074f78c11950a7
...
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
158
159
160
161
162
163
 
 
 
 
164
165
166
 
 
167
168
169
170
171
172
173
174
175
176
177
 
 
 
 
 
 
 
 
...
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
 
 
 
 
160
161
162
163
164
 
 
165
166
167
168
169
 
 
 
 
 
 
 
 
170
171
172
173
174
175
176
177
0
@@ -21,157 +21,157 @@ from twisted.python import log, usage
0
 from zope.interface import implements, Interface
0
 
0
 class IOAuthCredentialProvider(Interface):
0
- """An OAuth credential provider"""
0
-
0
- def fetchCredentials():
0
- """Fetch credentials"""
0
+ """An OAuth credential provider"""
0
+
0
+ def fetchCredentials():
0
+ """Fetch credentials"""
0
 
0
 
0
 class StaticOAuthCredentialProvider:
0
- implements(IOAuthCredentialProvider)
0
-
0
- def __init__(self, credentials):
0
- self.credentials = credentials
0
-
0
- def fetchCredentials(self):
0
- return self.credentials
0
+ implements(IOAuthCredentialProvider)
0
+
0
+ def __init__(self, credentials):
0
+ self.credentials = credentials
0
+
0
+ def fetchCredentials(self):
0
+ return self.credentials
0
 
0
 
0
 class OAuthCredentials:
0
- """
0
- A container for OAuth credentials
0
- """
0
- def __init__(self, consumerKey, consumerSecret, token = None, tokenSecret = None, signatureMethod = oauth.OAuthSignatureMethod_HMAC_SHA1()):
0
- self.oauthConsumer = oauth.OAuthConsumer(consumerKey, consumerSecret)
0
-
0
- if token is not None and tokenSecret is not None:
0
- self.oauthToken = oauth.OAuthToken(token, tokenSecret)
0
- else:
0
- self.oauthToken = None
0
-
0
- self.signatureMethod = signatureMethod
0
+ """
0
+ A container for OAuth credentials
0
+ """
0
+ def __init__(self, consumerKey, consumerSecret, token = None, tokenSecret = None, signatureMethod = oauth.OAuthSignatureMethod_HMAC_SHA1()):
0
+ self.oauthConsumer = oauth.OAuthConsumer(consumerKey, consumerSecret)
0
+
0
+ if token is not None and tokenSecret is not None:
0
+ self.oauthToken = oauth.OAuthToken(token, tokenSecret)
0
+ else:
0
+ self.oauthToken = None
0
+
0
+ self.signatureMethod = signatureMethod
0
 
0
 
0
 class Options(usage.Options):
0
- synopsis = "Usage: oauth_proxy --consumer-key <consumer key> --consumer-secret <consumer secret> [--token <token>] [--token-secret <token secret>] [-p <proxy port>] [--ssl]"
0
- longdesc = "An OAuth HTTP proxy server.."
0
- optParameters = [
0
- ['consumer-key', None, None, "OAuth Consumer Key"],
0
- ['consumer-secret', None, None, "OAuth Consumer Secret"],
0
- ['token', None, None, "OAuth Access/Request Token"],
0
- ['token-secret', None, None, "OAuth Access/Request Token Secret"],
0
- ['port', 'p', 8001, "Proxy port", int],
0
- ]
0
+ synopsis = "Usage: oauth_proxy --consumer-key <consumer key> --consumer-secret <consumer secret> [--token <token>] [--token-secret <token secret>] [-p <proxy port>] [--ssl]"
0
+ longdesc = "An OAuth HTTP proxy server.."
0
+ optParameters = [
0
+ ['consumer-key', None, None, "OAuth Consumer Key"],
0
+ ['consumer-secret', None, None, "OAuth Consumer Secret"],
0
+ ['token', None, None, "OAuth Access/Request Token"],
0
+ ['token-secret', None, None, "OAuth Access/Request Token Secret"],
0
+ ['port', 'p', 8001, "Proxy port", int],
0
+ ]
0
 
0
- optFlags = [['ssl', 's']]
0
+ optFlags = [['ssl', 's']]
0
 
0
 
0
 class OAuthProxyClient(proxy.ProxyClient):
0
- def connectionMade(self):
0
- # if retrieval of OAuth credentials is to be asynchronous, it needs to be done here (if it's even possible)
0
- # otherwise, this class has no point
0
- # however, it's possible that reading headers can't happen in OAuthProxyClientFactory
0
- proxy.ProxyClient.connectionMade(self)
0
+ def connectionMade(self):
0
+ # if retrieval of OAuth credentials is to be asynchronous, it needs to be done here (if it's even possible)
0
+ # otherwise, this class has no point
0
+ # however, it's possible that reading headers can't happen in OAuthProxyClientFactory
0
+ proxy.ProxyClient.connectionMade(self)
0
 
0
 
0
 class OAuthProxyClientFactory(proxy.ProxyClientFactory):
0
- def buildProtocol(self, addr):
0
- credentials = self.father.credentialProvider.fetchCredentials()
0
- oauthRequest = self.signRequest(credentials)
0
-
0
- client = proxy.ProxyClientFactory.buildProtocol(self, addr)
0
- # upgrade proxy.proxyClient object to OAuthProxyClient
0
- client.__class__ = OAuthProxyClient
0
- client.factory = self
0
-
0
- client.headers.update(oauthRequest.to_header())
0
- return client
0
-
0
- def signRequest(self, credentials):
0
- """Create an OAuthRequest and sign it"""
0
-
0
- if self.father.useSSL:
0
- path = self.father.path.replace("http", "https", 1)
0
- else:
0
- path = self.father.path
0
-
0
- # python parses arguments into a dict of arrays, e.g. 'q=foo' becomes {'q': ['foo']}
0
- # while from_consumer_and_token expects a dict of strings, so we cross our fingers,
0
- # hope there are no repeated arguments ('q=foo&q=bar'), and take the first value of
0
- # each array.
0
- args = dict([(k,v[0]) for k,v in self.father.args.items()])
0
-
0
- # create an OAuth Request from the pieces that we've assembled
0
- oauthRequest = oauth.OAuthRequest.from_consumer_and_token(
0
- credentials.oauthConsumer,
0
- credentials.oauthToken,
0
- self.father.method,
0
- path,
0
- args
0
- )
0
-
0
- # now, sign it
0
- oauthRequest.sign_request(credentials.signatureMethod, credentials.oauthConsumer, credentials.oauthToken)
0
-
0
- return oauthRequest
0
+ def buildProtocol(self, addr):
0
+ credentials = self.father.credentialProvider.fetchCredentials()
0
+ oauthRequest = self.signRequest(credentials)
0
+
0
+ client = proxy.ProxyClientFactory.buildProtocol(self, addr)
0
+ # upgrade proxy.proxyClient object to OAuthProxyClient
0
+ client.__class__ = OAuthProxyClient
0
+ client.factory = self
0
+
0
+ client.headers.update(oauthRequest.to_header())
0
+ return client
0
+
0
+ def signRequest(self, credentials):
0
+ """Create an OAuthRequest and sign it"""
0
+
0
+ if self.father.useSSL:
0
+ path = self.father.path.replace("http", "https", 1)
0
+ else:
0
+ path = self.father.path
0
+
0
+ # python parses arguments into a dict of arrays, e.g. 'q=foo' becomes {'q': ['foo']}
0
+ # while from_consumer_and_token expects a dict of strings, so we cross our fingers,
0
+ # hope there are no repeated arguments ('q=foo&q=bar'), and take the first value of
0
+ # each array.
0
+ args = dict([(k,v[0]) for k,v in self.father.args.items()])
0
+
0
+ # create an OAuth Request from the pieces that we've assembled
0
+ oauthRequest = oauth.OAuthRequest.from_consumer_and_token(
0
+ credentials.oauthConsumer,
0
+ credentials.oauthToken,
0
+ self.father.method,
0
+ path,
0
+ args
0
+ )
0
+
0
+ # now, sign it
0
+ oauthRequest.sign_request(credentials.signatureMethod, credentials.oauthConsumer, credentials.oauthToken)
0
+
0
+ return oauthRequest
0
 
0
 
0
 class OAuthProxyRequest(proxy.ProxyRequest):
0
- protocols = {'http': OAuthProxyClientFactory}
0
-
0
- def __init__(self, credentialProvider, useSSL, *args):
0
- self.credentialProvider = credentialProvider
0
- self.useSSL = useSSL
0
- proxy.ProxyRequest.__init__(self, *args)
0
-
0
- if self.useSSL:
0
- # Since we magically mapped HTTP to HTTPS, we want to make sure that the transport knows as much
0
- self._forceSSL = True
0
- self.ports["http"] = 443
0
-
0
- # Copied from proxy.ProxyRequest just so the reactor connection can be SSL
0
- def process(self):
0
- parsed = urlparse.urlparse(self.uri)
0
- protocol = parsed[0]
0
- host = parsed[1]
0
- port = self.ports[protocol]
0
- if ':' in host:
0
- host, port = host.split(':')
0
- port = int(port)
0
- rest = urlparse.urlunparse(('', '') + parsed[2:])
0
- if not rest:
0
- rest = rest + '/'
0
- class_ = self.protocols[protocol]
0
- headers = self.getAllHeaders().copy()
0
- if 'host' not in headers:
0
- headers['host'] = host
0
- self.content.seek(0, 0)
0
- s = self.content.read()
0
- clientFactory = class_(self.method, rest, self.clientproto, headers,
0
- s, self)
0
- # The magic line for SSL support!
0
- if self.useSSL:
0
- self.reactor.connectSSL(host, port, clientFactory, ssl.ClientContextFactory())
0
- else:
0
- self.reactor.connectTCP(host, port, clientFactory)
0
+ protocols = {'http': OAuthProxyClientFactory}
0
+
0
+ def __init__(self, credentialProvider, useSSL, *args):
0
+ self.credentialProvider = credentialProvider
0
+ self.useSSL = useSSL
0
+ proxy.ProxyRequest.__init__(self, *args)
0
+
0
+ if self.useSSL:
0
+ # Since we magically mapped HTTP to HTTPS, we want to make sure that the transport knows as much
0
+ self._forceSSL = True
0
+ self.ports["http"] = 443
0
+
0
+ # Copied from proxy.ProxyRequest just so the reactor connection can be SSL
0
+ def process(self):
0
+ parsed = urlparse.urlparse(self.uri)
0
+ protocol = parsed[0]
0
+ host = parsed[1]
0
+ port = self.ports[protocol]
0
+ if ':' in host:
0
+ host, port = host.split(':')
0
+ port = int(port)
0
+ rest = urlparse.urlunparse(('', '') + parsed[2:])
0
+ if not rest:
0
+ rest = rest + '/'
0
+ class_ = self.protocols[protocol]
0
+ headers = self.getAllHeaders().copy()
0
+ if 'host' not in headers:
0
+ headers['host'] = host
0
+ self.content.seek(0, 0)
0
+ s = self.content.read()
0
+ clientFactory = class_(self.method, rest, self.clientproto, headers,
0
+ s, self)
0
+ # The magic line for SSL support!
0
+ if self.useSSL:
0
+ self.reactor.connectSSL(host, port, clientFactory, ssl.ClientContextFactory())
0
+ else:
0
+ self.reactor.connectTCP(host, port, clientFactory)
0
 
0
 
0
 class OAuthProxy(proxy.Proxy):
0
- def __init__(self, credentialProvider, useSSL):
0
- self.credentialProvider = credentialProvider
0
- self.useSSL = useSSL
0
- proxy.Proxy.__init__(self)
0
+ def __init__(self, credentialProvider, useSSL):
0
+ self.credentialProvider = credentialProvider
0
+ self.useSSL = useSSL
0
+ proxy.Proxy.__init__(self)
0
 
0
- def requestFactory(self, *args):
0
- return OAuthProxyRequest(self.credentialProvider, self.useSSL, *args)
0
+ def requestFactory(self, *args):
0
+ return OAuthProxyRequest(self.credentialProvider, self.useSSL, *args)
0
 
0
 
0
 class OAuthProxyFactory(http.HTTPFactory):
0
- def __init__(self, credentialProvider, useSSL):
0
- self.credentialProvider = credentialProvider
0
- self.useSSL = useSSL
0
- http.HTTPFactory.__init__(self)
0
-
0
- def buildProtocol(self, addr):
0
- protocol = OAuthProxy(self.credentialProvider, self.useSSL)
0
- return protocol
0
+ def __init__(self, credentialProvider, useSSL):
0
+ self.credentialProvider = credentialProvider
0
+ self.useSSL = useSSL
0
+ http.HTTPFactory.__init__(self)
0
+
0
+ def buildProtocol(self, addr):
0
+ protocol = OAuthProxy(self.credentialProvider, self.useSSL)
0
+ return protocol

Comments

    No one has commented yet.