annotate mod_rest/example/prosody_oauth.py @ 5616:59d5fc50f602

mod_http_oauth2: Implement refresh token rotation Makes refresh tokens one-time-use, handing out a new refresh token with each access token. Thus if a refresh token is stolen and used by an attacker, the next time the legitimate client tries to use the previous refresh token, it will not work and the attack will be noticed. If the attacker does not use the refresh token, it becomes invalid after the legitimate client uses it. This behavior is recommended by draft-ietf-oauth-security-topics
author Kim Alvefur <zash@zash.se>
date Sun, 23 Jul 2023 02:56:08 +0200
parents 9a4556a13cc7
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4953
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
1 from requests_oauthlib import OAuth2Session
5269
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
2 import requests
4953
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
3
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
4
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
5 class ProsodyRestSession(OAuth2Session):
5269
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
6 def __init__(
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
7 self, base_url, client_name, client_uri, redirect_uri, *args, **kwargs
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
8 ):
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
9 self.base_url = base_url
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
10 discovery_url = base_url + "/.well-known/oauth-authorization-server"
4953
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
11
5269
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
12 meta = requests.get(discovery_url).json()
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
13 reg = requests.post(
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
14 meta["registration_endpoint"],
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
15 json={
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
16 "client_name": client_name,
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
17 "client_uri": client_uri,
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
18 "redirect_uris": [redirect_uri],
5488
9a4556a13cc7 mod_rest/example: Include 'application_type' in registration
Kim Alvefur <zash@zash.se>
parents: 5269
diff changeset
19 "application_type": redirect_uri[:8] == "https://"
9a4556a13cc7 mod_rest/example: Include 'application_type' in registration
Kim Alvefur <zash@zash.se>
parents: 5269
diff changeset
20 and "web"
9a4556a13cc7 mod_rest/example: Include 'application_type' in registration
Kim Alvefur <zash@zash.se>
parents: 5269
diff changeset
21 or "native",
5269
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
22 },
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
23 ).json()
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
24
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
25 super().__init__(client_id=reg["client_id"], *args, **kwargs)
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
26
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
27 self.meta = meta
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
28 self.client_secret = reg["client_secret"]
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
29 self.client_id = reg["client_id"]
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
30
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
31 def authorization_url(self, *args, **kwargs):
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
32 return super().authorization_url(
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
33 self.meta["authorization_endpoint"], *args, **kwargs
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
34 )
4953
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
35
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
36 def fetch_token(self, *args, **kwargs):
5269
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
37 return super().fetch_token(
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
38 token_url=self.meta["token_endpoint"],
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
39 client_secret=self.client_secret,
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
40 *args,
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
41 **kwargs
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
42 )
4953
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
43
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
44 def xmpp(self, json=None, *args, **kwargs):
5269
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
45 return self.post(self.base_url + "/rest", json=json, *args, **kwargs)
4953
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
46
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
47
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
48 if __name__ == "__main__":
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
49 # Example usage
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
50
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
51 # from prosody_oauth import ProsodyRestSession
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
52 from getpass import getpass
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
53
5269
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
54 p = ProsodyRestSession(
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
55 input("Base URL: "),
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
56 "Prosody mod_rest OAuth 2 example",
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
57 "https://modules.prosody.im/mod_rest",
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
58 "urn:ietf:wg:oauth:2.0:oob",
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
59 )
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
60
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
61 print("Open the following URL in a browser and login:")
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
62 print(p.authorization_url()[0])
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
63
0e5a37f55440 mod_rest: Update prosody_oauth.py example to non-legacy OAuth2
Kim Alvefur <zash@zash.se>
parents: 4953
diff changeset
64 p.fetch_token(code=getpass("Paste Authorization code: "))
4953
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
65
ccce785f53e1 mod_rest: Add an example OAuth client (needs mod_http_oauth2)
Kim Alvefur <zash@zash.se>
parents:
diff changeset
66 print(p.xmpp(json={"disco": True, "to": "jabber.org"}).json())