Skip to content
Snippets Groups Projects

Add standalone script to get a Taiga application auth token

Merged Jakob Moser requested to merge add-taiga-token-script into master
1 file
+ 127
0
Compare changes
  • Side-by-side
  • Inline
+ 127
0
#!/usr/bin/env python3
import requests
import secrets
from getpass import getpass
from typing import Any
TAIGA_BASE = "https://todo.fachschaft.cl.uni-heidelberg.de"
# https://docs.taiga.io/api.html#object-auth-user-detail
UserAuthDetail = dict[str, Any]
class AuthenticationFailedError(Exception):
pass
def json_or_error(r: requests.Response) -> dict[str, Any]:
if r.status_code == 401:
raise AuthenticationFailedError(r.json())
elif r.status_code != 200:
raise RuntimeError(r.json())
return r.json()
def __login_with_type(username: str, psasword: str, type_: str) -> UserAuthDetail:
# See https://docs.taiga.io/api.html#auth-normal-login
r = requests.post(
f"{TAIGA_BASE}/api/v1/auth",
json={
"type": type_,
"username": username,
"password": password,
},
)
return json_or_error(r)
def login(username: str, password: str) -> UserAuthDetail:
"""Log in to the Taiga instance at TAIGA_BASE with the given username and password.
If successful, return an auth_detail dictionary, which (among other things) contains
an "auth_token" that can be used to authorize API operations.
This first treats the account as an LDAP account. If this doesn't work, it falls back
to normal authentication.
:return: auth_detail dictionary, token stored with key "auth_token"
:raise AuthenticationFailedError: When authentication is not possible (HTTP 401)
"""
try:
auth_detail = __login_with_type(username, password, "ldap")
except AuthenticationFailedError:
auth_detail = __login_with_type(username, password, "normal")
return auth_detail
def get_auth_code_dict(application_id: str, user_auth_token: str) -> dict[str, Any]:
"""
https://docs.taiga.io/api.html#external-app-authorization
"""
r = requests.post(
f"{TAIGA_BASE}/api/v1/application-tokens/authorize",
json={"application": application_id, "state": secrets.token_hex(48)},
headers={"Authorization": f"Bearer {user_auth_token}"},
)
return json_or_error(r)
def get_token_dict(
application_id: str, user_auth_token: str, auth_code_dict: dict[str, Any]
) -> dict[str, Any]:
r = requests.post(
f"{TAIGA_BASE}/api/v1/application-tokens/validate",
json={
"application": application_id,
"auth_code": auth_code_dict["auth_code"],
"state": auth_code_dict["state"],
},
headers={"Authorization": f"Bearer {user_auth_token}"},
)
return json_or_error(r)
def get_application_auth_token(application_id: str, user_auth_token: str) -> str:
auth_code_dict = get_auth_code_dict(application_id, user_auth_token)
token_dict = get_token_dict(application_id, user_auth_token, auth_code_dict)
return token_dict["token"]
if __name__ == "__main__":
print(
f"Tool to request an application access token from the Taiga instance {TAIGA_BASE}"
)
print()
username = input("[?] Username: ")
password = getpass("[?] Password: ")
try:
auth_detail = login(username, password)
print("[✓] Successfully logged in.")
print()
except AuthenticationFailedError:
print(
"[✗] Login failed: Maybe password or username were wrong, or Taiga made an error."
)
exit(1)
print(
f"[!] Now, create an application under {TAIGA_BASE}/admin/external_apps/application "
f"(you will need an admin account for this)."
)
print()
application_id = input("[?] Application id: ")
application_auth_token = get_application_auth_token(
application_id, auth_detail["auth_token"]
)
print(f"[✓] Your application auth token is: {application_auth_token}")
Loading