@@ -87,25 +87,29 @@ def gen_payload_data():
8787
8888 Avoids `invalid_grant` by getting a new `exp` value during signing
8989 """
90-
9190 payload_data = {
92- "audience" : 'api.meetup.com' ,
93- "kid" : SIGNING_KEY_ID ,
9491 "sub" : SELF_ID ,
95- "iss" : CLIENT_SECRET ,
96- "exp" : time .time () + int (JWT_LIFE_SPAN )
92+ "iss" : CLIENT_ID ,
93+ "aud" : "api.meetup.com" ,
94+ "exp" : int (time .time () + JWT_LIFE_SPAN )
9795 }
98-
9996 return payload_data
10097
10198
10299def sign_token ():
103100 """Generate signed JWT"""
104101
102+ # Define headers exactly as specified in docs
103+ jwt_headers = {
104+ "kid" : SIGNING_KEY_ID ,
105+ "typ" : "JWT" ,
106+ "alg" : "RS256"
107+ }
108+
105109 payload_data = gen_payload_data ()
106110
107111 payload = jwt .encode (
108- headers = headers ,
112+ headers = jwt_headers ,
109113 payload = payload_data ,
110114 key = private_key ,
111115 algorithm = 'RS256'
@@ -121,7 +125,8 @@ def verify_token(token):
121125 jwt .decode (
122126 jwt = token ,
123127 key = public_key ,
124- issuer = CLIENT_SECRET ,
128+ issuer = CLIENT_ID ,
129+ audience = "api.meetup.com" ,
125130 verify = True ,
126131 algorithms = ['RS256' ]
127132 )
@@ -134,6 +139,7 @@ def verify_token(token):
134139 jwt .exceptions .InvalidTokenError ,
135140 jwt .exceptions .InvalidSignatureError ,
136141 jwt .exceptions .InvalidIssuerError ,
142+ jwt .exceptions .InvalidAudienceError ,
137143 ) as e :
138144 print (f"{ Fore .RED } { error :<10} { Fore .RESET } { e } " )
139145 sys .exit (1 )
@@ -142,18 +148,30 @@ def verify_token(token):
142148def get_access_token (token ):
143149 """Post token to auth server to get access token"""
144150
151+ # Headers for the token request
152+ request_headers = {
153+ "Content-Type" : "application/x-www-form-urlencoded"
154+ }
155+
156+ # Payload exactly as specified in docs
157+ # https://www.meetup.com/api/authentication/#p04-jwt-flow-section
145158 payload = {
146- "grant_type" : 'urn:ietf:params:oauth:grant-type:jwt-bearer' ,
147- "assertion" : token ,
148- "redirect_uri" : REDIRECT_URI ,
149- "client_id" : CLIENT_ID ,
150- "client_secret" : CLIENT_SECRET ,
151- "audience" : 'api.meetup.com' ,
152- "exp" : time .time () + int (JWT_LIFE_SPAN )
159+ "grant_type" : "urn:ietf:params:oauth:grant-type:jwt-bearer" ,
160+ "assertion" : token
153161 }
154162 payload = urlencode (payload )
155163
156- return requests .request ("POST" , TOKEN_URL , headers = headers , data = payload )
164+ try :
165+ response = requests .request ("POST" , TOKEN_URL , headers = request_headers , data = payload )
166+ response .raise_for_status ()
167+ return response .json ()
168+ except requests .exceptions .HTTPError as e :
169+ print (f"{ Fore .RED } { error :<10} { Fore .RESET } HTTP Error: { e } " )
170+ print (f"Response: { response .text } " )
171+ return None
172+ except requests .exceptions .RequestException as e :
173+ print (f"{ Fore .RED } { error :<10} { Fore .RESET } Request failed: { e } " )
174+ return None
157175
158176
159177def main ():
@@ -163,12 +181,17 @@ def main():
163181 token = sign_token ()
164182
165183 # verify JWT
166- verify_token (token )
184+ if not verify_token (token ):
185+ print (f"{ Fore .RED } { error :<10} { Fore .RESET } Token verification failed" )
186+ return None
167187
168188 # get access and refresh tokens
169- res = get_access_token (token )
189+ tokens = get_access_token (token )
190+ if not tokens :
191+ print (f"{ Fore .RED } { error :<10} { Fore .RESET } Failed to get access token" )
192+ return None
170193
171- return res . json ()
194+ return tokens
172195
173196
174197if __name__ == "__main__" :
0 commit comments