Skip to content

Instantly share code, notes, and snippets.

@Torvin
Created April 2, 2023 06:33
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Torvin/2036687dac5376e15aec8975354e4602 to your computer and use it in GitHub Desktop.
Save Torvin/2036687dac5376e15aec8975354e4602 to your computer and use it in GitHub Desktop.
Twitter challenge login
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from base64 import b64decode,b64encode
from urllib.parse import quote,parse_qs,urlsplit,urlparse
from random import randint
from bs4 import BeautifulSoup
import calendar
import requests
import hashlib
import base64
import time
import hmac
import types
class Twitter(object):
def __init__(self):
self.twitter_android_key = "XXXXXXX"
self.twitter_android_secret = "XXXXXXX"
self.session = requests.Session()
self.access_token = None
self.guest_token = None
self.challenged = False
self.challenge_type = None
self.challenge = None
self.on_challenge = None
self.xauth = None
def oauth_signature(self,request,oauth_secret):
key = bytes(self.twitter_android_secret +"&"+ oauth_secret, 'UTF-8')
message = bytes(request, 'UTF-8')
digester = hmac.new(key, message, hashlib.sha1)
signature1 = digester.digest()
signature2 = base64.urlsafe_b64encode(signature1)
signature2 = str(signature2, 'UTF-8').replace("-","+").replace("_","/")
return quote(signature2,safe='')
def signature_message(self,url,params,oauth_secret,method="POST"):
header = method + "&" + quote(url,safe='') + "&"
body = bytes()
for key,value in params.items():
body += bytes(key,"UTF-8") + b"=" + bytes(value,"UTF-8") + b"&"
body = body[:-1]
return self.oauth_signature(header + quote(body,safe=''),oauth_secret)
def xauth_login(self,username,password):
self.access_token = self.session.post("https://api.twitter.com/oauth2/token",params = {'grant_type':'client_credentials'},
headers = {
"Accept": "application/json",
"Authorization": "Basic " + b64encode((self.twitter_android_key + ":" + self.twitter_android_secret).encode("utf8")).decode("utf8")
}
).json()["access_token"]
self.guest_token = self.session.post("https://api.twitter.com/1.1/guest/activate.json",headers={"Authorization": "Bearer " + self.access_token}).json()["guest_token"]
auth = self.session.post("https://api.twitter.com/auth/1/xauth_password.json",headers={
"Authorization": "Bearer " + self.access_token,
"X-Guest-Token": self.guest_token
},
params = {
"x_auth_identifier":username,
"x_auth_password":password,
"send_error_codes":"true",
"x_auth_login_challenge":"1",
"x_auth_login_verification":"1",
"x_auth_country_code":"US",
"ui_metrics":""
}).json()
self.xauth = auth
if "login_verification_request_url" in auth.keys():
self.challenged = True
self.challenge = auth
self.challenge_type = parse_qs(urlparse(auth["login_verification_request_url"]).query)['challenge_type'][0]
return auth
def challenge_access_token(self,user_id,request_id):
oauth_nonce = ''.join([str(randint(0,9)) for n in range(31)])
oauth_timestamp = str(calendar.timegm(time.gmtime()))
return self.session.post("https://api.twitter.com/oauth/access_token",data={
"x_auth_mode":"client_auth",
"x_auth_login_verification":"1",
"x_auth_login_challenge": "1",
"send_error_codes":"true",
"login_verification_user_id": user_id,
"login_verification_request_id": request_id
},
headers = {
"Authorization":'OAuth realm="http://api.twitter.com/", oauth_version="1.0", oauth_nonce="{oauth_nonce}", oauth_timestamp="{oauth_timestamp}", oauth_signature="{oauth_signature}", oauth_consumer_key="{oauth_consumer_key}", oauth_signature_method="HMAC-SHA1"'.format(
oauth_nonce = oauth_nonce,
oauth_timestamp = oauth_timestamp,
oauth_consumer_key = self.twitter_android_key,
oauth_signature = self.signature_message(url="https://api.twitter.com/oauth/access_token",params={
"login_verification_request_id": request_id,
"login_verification_user_id": user_id,
"oauth_consumer_key":self.twitter_android_key,
"oauth_nonce": oauth_nonce,
"oauth_signature_method":"HMAC-SHA1",
"oauth_timestamp": oauth_timestamp,
"oauth_version":"1.0",
"send_error_codes":"true",
"x_auth_login_challenge":"1",
"x_auth_login_verification":"1",
"x_auth_mode":"client_auth",
},oauth_secret="")
),
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
}).json()
def solve_challenge(self,challenge):
self.has_challenge = True
challenge_url = challenge["login_verification_request_url"]
request_id = challenge["login_verification_request_id"]
response = self.session.get(challenge_url)
soup = BeautifulSoup(response.content, "lxml")
authenticity_token = soup.select_one("input[name=authenticity_token]")["value"]
challenge_id = soup.select_one("input[name=challenge_id]")["value"]
user_id = soup.select_one("input[name=user_id]")["value"]
self.challenge_type = soup.select_one("input[name=challenge_type]")["value"]
print(response.content)
answer = input("code:").strip()
data = {
'authenticity_token':authenticity_token,
'challenge_id':challenge_id,
'user_id':user_id,
'challenge_type':self.challenge_type,
'platform':'mobile',
'redirect_after_login':'',
'remember_me':'true',
'challenge_response':answer,
}
self.session.post("https://twitter.com/account/login_challenge",data=data)
twitter_session = self.challenge_access_token(user_id, request_id)
self.xauth = twitter_session
print(twitter_session)
return twitter_session
def auth_headers(self,oauth_nonce,oauth_timestamp,oauth_signature,skip_token=False):
return {
"Authorization": 'OAuth realm="http://api.twitter.com/", oauth_version="1.0", oauth_token="{oauth_token}", oauth_nonce="{oauth_nonce}", oauth_timestamp="{oauth_timestamp}", oauth_signature="{oauth_signature}", oauth_consumer_key="{oauth_consumer_key}", oauth_signature_method="{oauth_signature_method}"'.format(
oauth_token = self.xauth["oauth_token"] if not skip_token else "",
oauth_nonce = oauth_nonce,
oauth_timestamp = oauth_timestamp,
oauth_signature = oauth_signature,
oauth_consumer_key = self.twitter_android_key,
oauth_signature_method = "HMAC-SHA1"
),
"User-Agent": "TwitterAndroid/8.40.0-release.02 (18400002-r-2) Nexus 7/7.0 (asus;Nexus 7;google;nakasi;0;;0;2012)",
"X-Twitter-Active-User": "yes",
"X-Twitter-API-Version": "5",
"X-Twitter-Client": "TwitterAndroid",
"X-Twitter-Client-Language": "en-US",
"Accept": "application/json",
}
def tweet(self, text):
api_statuses = "https://api.twitter.com/1.1/statuses/update.json"
oauth_nonce = ''.join([str(randint(0,9)) for n in range(31)])
oauth_timestamp = str(calendar.timegm(time.gmtime()))
params = {
"batch_mode":"off",
"cards_platform":"Android-12",
"earned_read":"true",
"enable_dm_commands":"false",
"ext":"mediaRestrictions%2CaltText%2CmediaStats%2CmediaColor%2Cinfo360%2CcameraMoment%2ChighlightedLabel%2Cmaster_playlist_only",
"include_blocked_by":"true",
"include_blocking":"true",
"include_cards":"true",
"include_entities":"true",
"include_media_features":"true",
"include_reply_count":"true",
"oauth_consumer_key":self.twitter_android_key,
"oauth_nonce": oauth_nonce,
"oauth_signature_method":"HMAC-SHA1",
"oauth_timestamp":oauth_timestamp,
"oauth_token": self.xauth["oauth_token"],
"oauth_version":"1.0",
"send_error_codes":"true",
"status": quote(text,safe=''),
"tweet_mode":"extended"
}
headers = self.auth_headers(
oauth_nonce= oauth_nonce,
oauth_timestamp= oauth_timestamp,
oauth_signature= self.signature_message(
url= api_statuses,
params= params,
oauth_secret= self.xauth['oauth_token_secret']
)
)
headers["Content-Type"] = "application/x-www-form-urlencoded"
post_params = '&'.join([k + u"=" + v for k,v in params.items()])
return self.session.post(api_statuses,headers=headers,data=post_params.encode('utf-8'),verify=False).json()
api = Twitter()
username = input('username: ').strip()
password = input('password: ').strip()
result = api.xauth_login(username, password)
print(result)
if api.challenged:
api.solve_challenge(result)
@tangxiangpi
Copy link

https://api.twitter.com/auth/1/xauth_password.json get {'errors': [{'code': 34, 'message': 'Sorry, that page does not exist.'}]}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment