Skip to content

Commit 137f871

Browse files
authored
Merge pull request #21 from BigSpaceships/master
Fixed github auth stuff so it actually works
2 parents 3b1510f + 97a1fb1 commit 137f871

File tree

4 files changed

+122
-20
lines changed

4 files changed

+122
-20
lines changed

Dockerfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,7 @@ ARG PORT=8080
2222
ENV PORT=${PORT}
2323
EXPOSE ${PORT}
2424

25-
CMD ["sh", "-c", "gunicorn app:application --bind=0.0.0.0:${PORT} --access-logfile=- --timeout=600"]
25+
# --access-logfile - prints access log to stdout
26+
# --error-log - prints errors to stdout
27+
# --capture-output logging and print go to error log (stdout)
28+
CMD ["sh", "-c", "gunicorn app:application --bind=0.0.0.0:${PORT} --access-logfile - --error-log - --capture-output --timeout=600"]

config.env.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
# GitHub secrets
3131
GITHUB_CLIENT_ID = os.environ.get('GITHUB_ID', '')
3232
GITHUB_SECRET = os.environ.get('GITHUB_SECRET', '')
33-
ORG_TOKEN = os.environ.get('GITHUB_ORG_TOKEN', '')
33+
GITHUB_APP_ID = os.environ.get('GITHUB_APP_ID', '')
34+
GITHUB_APP_PRIVATE_KEY = os.environ.get('GITHUB_APP_PRIVATE_KEY', '')
3435

3536
# Twitch secrets
3637
TWITCH_CLIENT_ID = os.environ.get('TWITCH_CLIENT_ID', '')

eac/__init__.py

Lines changed: 113 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
import base64
1212
from typing import Any
1313

14+
import jwt
15+
from requests.models import HTTPError
16+
1417
import flask
1518
import werkzeug
1619
from flask import Flask, request, redirect, session, render_template, send_from_directory, jsonify
@@ -51,7 +54,7 @@
5154
+ '&code=%s'
5255

5356
_GITHUB_AUTH_URI = 'https://github.com/login/oauth/authorize' \
54-
+ '?client_id=%s'\
57+
+ '?client_id=%s' \
5558
+ '&state=%s'
5659
_GITHUB_TOKEN_URI = 'https://github.com/login/oauth/access_token' \
5760
+ '?client_id=%s' \
@@ -168,19 +171,29 @@ def _github_landing() -> tuple[str, int]:
168171
(APP.config['GITHUB_CLIENT_ID'], APP.config['GITHUB_SECRET'],
169172
request.args.get('code')),
170173
headers={'Accept': 'application/json'},
171-
timeout=APP.config['REQUEST_TIMEOUT'],
172-
)
173-
token = resp.json()['access_token']
174+
timeout=APP.config['REQUEST_TIMEOUT'])
175+
try:
176+
resp.raise_for_status()
177+
except HTTPError as e:
178+
print('response:', resp.json())
179+
raise e
180+
181+
resp_json = resp.json()
182+
token = resp_json['access_token']
174183
header = {
175184
'Authorization': 'token ' + token,
176185
'Accept': 'application/vnd.github.v3+json'
177186
}
178187

179-
user_resp = requests.get(
180-
'https://api.github.com/user',
181-
headers=header,
182-
timeout=APP.config['REQUEST_TIMEOUT'],
183-
)
188+
user_resp = requests.get('https://api.github.com/user',
189+
headers=header,
190+
timeout=APP.config['REQUEST_TIMEOUT'])
191+
try:
192+
user_resp.raise_for_status()
193+
except HTTPError as e:
194+
print('response:', user_resp.json())
195+
raise e
196+
184197
user_resp_json = user_resp.json()
185198

186199
github_username = user_resp_json['login']
@@ -194,20 +207,88 @@ def _github_landing() -> tuple[str, int]:
194207
return render_template('callback.html'), 200
195208

196209

210+
def _get_github_jwt() -> str:
211+
signing_key = APP.config["GITHUB_APP_PRIVATE_KEY"]
212+
213+
payload = {
214+
'iat': int(time.time()),
215+
'exp': int(time.time() + 600),
216+
'iss': APP.config['GITHUB_APP_ID'],
217+
}
218+
219+
encoded_jwt = jwt.encode(payload, signing_key, algorithm='RS256')
220+
221+
return encoded_jwt
222+
223+
224+
def _auth_github_org() -> str:
225+
jwt_auth = _get_github_jwt()
226+
227+
headers = {
228+
'Accept': 'application/vnd.github.v3+json',
229+
'Authorization': f'Bearer {jwt_auth}',
230+
}
231+
232+
org_installation_resp = requests.get(
233+
'https://api.github.com/orgs/ComputerScienceHouse/installation',
234+
headers=headers,
235+
timeout=APP.config['REQUEST_TIMEOUT'])
236+
try:
237+
org_installation_resp.raise_for_status()
238+
except HTTPError as e:
239+
print('response:', org_installation_resp.json())
240+
raise e
241+
242+
org_installation_json = org_installation_resp.json()
243+
org_installation_id = org_installation_json['id']
244+
245+
org_token_resp = requests.post(
246+
f'https://api.github.com/app/installations/{org_installation_id}/access_tokens',
247+
headers=headers,
248+
timeout=APP.config['REQUEST_TIMEOUT'])
249+
try:
250+
org_token_resp.raise_for_status()
251+
except HTTPError as e:
252+
print('response:', org_token_resp.json())
253+
raise e
254+
255+
org_token_json = org_token_resp.json()
256+
org_token = org_token_json['token']
257+
258+
return org_token
259+
260+
197261
def _link_github(github_username: str, github_id: str, member: Any) -> None:
198262
"""
199263
Puts a member's github into LDAP and adds them to the org.
200264
:param github_username: the user's github username
201265
:param github_id: the user's github id
202266
:param member: the member's LDAP object
203267
"""
204-
payload = {'invitee_id': github_id}
205-
requests.post(
268+
org_token = _auth_github_org()
269+
270+
payload = {
271+
'org': 'ComputerScienceHouse',
272+
'invitee_id': github_id,
273+
'role': 'direct_member'
274+
}
275+
276+
github_org_headers = {
277+
'Accept': 'application/vnd.github.v3+json',
278+
'Authorization': f'Token {org_token}',
279+
}
280+
281+
resp = requests.post(
206282
'https://api.github.com/orgs/ComputerScienceHouse/invitations',
207-
headers=_ORG_HEADER,
208-
data=payload,
209-
timeout=APP.config['REQUEST_TIMEOUT'],
210-
)
283+
headers=github_org_headers,
284+
json=payload,
285+
timeout=APP.config['REQUEST_TIMEOUT'])
286+
try:
287+
resp.raise_for_status()
288+
except HTTPError as e:
289+
print('response:', resp.json())
290+
raise e
291+
211292
member.github = github_username
212293

213294

@@ -217,12 +298,27 @@ def _revoke_github() -> werkzeug.Response:
217298
""" Clear's a member's github in LDAP and removes them from the org. """
218299
uid = str(session['userinfo'].get('preferred_username', ''))
219300
member = _LDAP.get_member(uid, uid=True)
220-
requests.delete(
301+
302+
org_token = _auth_github_org()
303+
304+
headers = {
305+
'Accept': 'application/vnd.github.v3+json',
306+
'Authorization': f'Token {org_token}',
307+
}
308+
309+
resp = requests.delete(
221310
'https://api.github.com/orgs/ComputerScienceHouse/members/' +
222311
member.github,
223-
headers=_ORG_HEADER,
312+
headers=headers,
224313
timeout=APP.config['REQUEST_TIMEOUT'],
225314
)
315+
316+
try:
317+
resp.raise_for_status()
318+
except HTTPError as e:
319+
print('response:', resp.json())
320+
raise e
321+
226322
member.github = None
227323
return jsonify(success=True)
228324

requirements.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
csh-ldap==2.4.0
1+
csh-ldap @ git+https://github.com/ComputerScienceHouse/csh_ldap@2.5.1
22
Flask==3.1.2
33
Flask-pyoidc==3.14.3
44
gunicorn==23.0.0
@@ -7,4 +7,6 @@ pylint==3.3.8
77
pylint-quotes==0.2.3
88
requests==2.32.5
99
sentry-sdk[flask]==2.37.1
10+
PyJWT==2.10.1
11+
cryptography==46.0.2
1012
yapf==0.43.0

0 commit comments

Comments
 (0)