Last active
August 19, 2025 09:04
-
-
Save kemitche/9749639 to your computer and use it in GitHub Desktop.
reddit OAuth 2.0 Python Webserver Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| from flask import Flask, abort, request | |
| from uuid import uuid4 | |
| import requests | |
| import requests.auth | |
| import urllib | |
| CLIENT_ID = None # Fill this in with your client ID | |
| CLIENT_SECRET = None # Fill this in with your client secret | |
| REDIRECT_URI = "http://localhost:65010/reddit_callback" | |
| def user_agent(): | |
| '''reddit API clients should each have their own, unique user-agent | |
| Ideally, with contact info included. | |
| e.g., | |
| return "oauth2-sample-app by /u/%s" % your_reddit_username | |
| ''' | |
| raise NotImplementedError() | |
| def base_headers(): | |
| return {"User-Agent": user_agent()} | |
| app = Flask(__name__) | |
| @app.route('/') | |
| def homepage(): | |
| text = '<a href="%s">Authenticate with reddit</a>' | |
| return text % make_authorization_url() | |
| def make_authorization_url(): | |
| # Generate a random string for the state parameter | |
| # Save it for use later to prevent xsrf attacks | |
| state = str(uuid4()) | |
| save_created_state(state) | |
| params = {"client_id": CLIENT_ID, | |
| "response_type": "code", | |
| "state": state, | |
| "redirect_uri": REDIRECT_URI, | |
| "duration": "temporary", | |
| "scope": "identity"} | |
| url = "https://ssl.reddit.com/api/v1/authorize?" + urllib.urlencode(params) | |
| return url | |
| # Left as an exercise to the reader. | |
| # You may want to store valid states in a database or memcache. | |
| def save_created_state(state): | |
| pass | |
| def is_valid_state(state): | |
| return True | |
| @app.route('/reddit_callback') | |
| def reddit_callback(): | |
| error = request.args.get('error', '') | |
| if error: | |
| return "Error: " + error | |
| state = request.args.get('state', '') | |
| if not is_valid_state(state): | |
| # Uh-oh, this request wasn't started by us! | |
| abort(403) | |
| code = request.args.get('code') | |
| access_token = get_token(code) | |
| # Note: In most cases, you'll want to store the access token, in, say, | |
| # a session for use in other parts of your web app. | |
| return "Your reddit username is: %s" % get_username(access_token) | |
| def get_token(code): | |
| client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET) | |
| post_data = {"grant_type": "authorization_code", | |
| "code": code, | |
| "redirect_uri": REDIRECT_URI} | |
| headers = base_headers() | |
| response = requests.post("https://ssl.reddit.com/api/v1/access_token", | |
| auth=client_auth, | |
| headers=headers, | |
| data=post_data) | |
| token_json = response.json() | |
| return token_json["access_token"] | |
| def get_username(access_token): | |
| headers = base_headers() | |
| headers.update({"Authorization": "bearer " + access_token}) | |
| response = requests.get("https://oauth.reddit.com/api/v1/me", headers=headers) | |
| me_json = response.json() | |
| return me_json['name'] | |
| if __name__ == '__main__': | |
| app.run(debug=True, port=65010) |
This is brilliant! This is the first time I have understood what is going on with OAuth! Simple and clear. Thank you!
Thank you very much, this helped me a lot!
In the final step when I try to fetch the token I got this response:
{'message': 'Unauthorized', 'error': 401}
After asking Gemini about that It said that Reddit has changed the fetch token url
the new url I used is: 'https://www.reddit.com/api/v1/access_token' and its worked
so the get_token method looks like:
def get_token(code):
client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET)
post_data = {"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI}
headers = base_headers()
# Use the corrected URL below
response = requests.post("https://www.reddit.com/api/v1/access_token",
auth=client_auth,
headers=headers,
data=post_data)
token_json = response.json()
# Check if 'access_token' is in the response before trying to access it
if "access_token" in token_json:
return token_json["access_token"]
else:
# Handle the error gracefully if the token isn't in the response
print("Error fetching token.")
return None
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@prashant2796 A user agent is a description that tells a little bit about what your using such as "MozillaFirefox17.1;Ubuntu16.04;Python3; by: Mynameiskaleb"
From what I can tell, some sites expect them to be in certain formats like Firefox and others aren't too picky as long as it gives a decent description.