2FA
This commit is contained in:
parent
b58cfc65b5
commit
96ae523c40
3 changed files with 70 additions and 4 deletions
|
@ -163,3 +163,6 @@ at = Client.from_hashed('username', my_passwd)
|
||||||
|
|
||||||
at.change_password_hashed(my_passwd, new_passwd)
|
at.change_password_hashed(my_passwd, new_passwd)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Two-Factor Authentication
|
||||||
|
...
|
||||||
|
|
|
@ -6,13 +6,14 @@ import re
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from typing import List, Optional
|
from typing import List, Dict, Optional
|
||||||
|
|
||||||
import lxml.html
|
import lxml.html
|
||||||
|
|
||||||
from .atserver import AternosServer
|
from .atserver import AternosServer
|
||||||
from .atconnect import AternosConnect
|
from .atconnect import AternosConnect
|
||||||
from .aterrors import CredentialsError
|
from .aterrors import CredentialsError
|
||||||
|
from .aterrors import TwoFactorAuthError
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
|
@ -47,6 +48,7 @@ class Client:
|
||||||
cls,
|
cls,
|
||||||
username: str,
|
username: str,
|
||||||
md5: str,
|
md5: str,
|
||||||
|
code: Optional[int] = None,
|
||||||
sessions_dir: str = '~'):
|
sessions_dir: str = '~'):
|
||||||
|
|
||||||
"""Log in to an Aternos account with
|
"""Log in to an Aternos account with
|
||||||
|
@ -55,6 +57,7 @@ class Client:
|
||||||
Args:
|
Args:
|
||||||
username (str): Your username
|
username (str): Your username
|
||||||
md5 (str): Your password hashed with MD5
|
md5 (str): Your password hashed with MD5
|
||||||
|
code (Optional[int]): 2FA code
|
||||||
sessions_dir (str): Path to the directory
|
sessions_dir (str): Path to the directory
|
||||||
where session will be automatically saved
|
where session will be automatically saved
|
||||||
|
|
||||||
|
@ -77,14 +80,20 @@ class Client:
|
||||||
|
|
||||||
credentials = {
|
credentials = {
|
||||||
'user': username,
|
'user': username,
|
||||||
'password': md5
|
'password': md5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if code is not None:
|
||||||
|
credentials['code'] = code
|
||||||
|
|
||||||
loginreq = atconn.request_cloudflare(
|
loginreq = atconn.request_cloudflare(
|
||||||
'https://aternos.org/panel/ajax/account/login.php',
|
'https://aternos.org/panel/ajax/account/login.php',
|
||||||
'POST', data=credentials, sendtoken=True
|
'POST', data=credentials, sendtoken=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if b'"show2FA":true' in loginreq.content:
|
||||||
|
raise TwoFactorAuthError('2FA code is required')
|
||||||
|
|
||||||
if 'ATERNOS_SESSION' not in loginreq.cookies:
|
if 'ATERNOS_SESSION' not in loginreq.cookies:
|
||||||
raise CredentialsError(
|
raise CredentialsError(
|
||||||
'Check your username and password'
|
'Check your username and password'
|
||||||
|
@ -104,6 +113,7 @@ class Client:
|
||||||
cls,
|
cls,
|
||||||
username: str,
|
username: str,
|
||||||
password: str,
|
password: str,
|
||||||
|
code: Optional[int] = None,
|
||||||
sessions_dir: str = '~'):
|
sessions_dir: str = '~'):
|
||||||
|
|
||||||
"""Log in to Aternos with a username and a plain password
|
"""Log in to Aternos with a username and a plain password
|
||||||
|
@ -111,13 +121,14 @@ class Client:
|
||||||
Args:
|
Args:
|
||||||
username (str): Your username
|
username (str): Your username
|
||||||
password (str): Your password without any encryption
|
password (str): Your password without any encryption
|
||||||
|
code (Optional[int]): 2FA code
|
||||||
sessions_dir (str): Path to the directory
|
sessions_dir (str): Path to the directory
|
||||||
where session will be automatically saved
|
where session will be automatically saved
|
||||||
"""
|
"""
|
||||||
|
|
||||||
md5 = Client.md5encode(password)
|
md5 = Client.md5encode(password)
|
||||||
return cls.from_hashed(
|
return cls.from_hashed(
|
||||||
username, md5,
|
username, md5, code,
|
||||||
sessions_dir
|
sessions_dir
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -372,6 +383,52 @@ class Client:
|
||||||
'https://aternos.org/panel/ajax/account/password.php',
|
'https://aternos.org/panel/ajax/account/password.php',
|
||||||
'POST', data={
|
'POST', data={
|
||||||
'oldpassword': old,
|
'oldpassword': old,
|
||||||
'newpassword': new
|
'newpassword': new,
|
||||||
|
}, sendtoken=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def qrcode_2fa(self) -> Dict[str, str]:
|
||||||
|
|
||||||
|
"""Requests a secret code and
|
||||||
|
a QR code for enabling 2FA"""
|
||||||
|
|
||||||
|
resp: Dict[str, str]
|
||||||
|
resp = self.atconn.request_cloudflare(
|
||||||
|
'https://aternos.org/panel/ajax/account/secret.php',
|
||||||
|
'GET', sendtoken=True
|
||||||
|
).json()
|
||||||
|
|
||||||
|
return {
|
||||||
|
'qrcode': resp.get('qrcode'),
|
||||||
|
'secret': resp.get('secret'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def enbale_2fa(self, code: int) -> None:
|
||||||
|
|
||||||
|
"""Enables Two-Factor Authentication
|
||||||
|
|
||||||
|
Args:
|
||||||
|
code (int): 2FA code
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.atconn.request_cloudflare(
|
||||||
|
'https://aternos.org/panel/ajax/account/twofactor.php',
|
||||||
|
'POST', data={
|
||||||
|
'code': code
|
||||||
|
}, sendtoken=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def disable_2fa(self, code: int) -> None:
|
||||||
|
|
||||||
|
"""Disables Two-Factor Authentication
|
||||||
|
|
||||||
|
Args:
|
||||||
|
code (int): 2FA code
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.atconn.request_cloudflare(
|
||||||
|
'https://aternos.org/panel/ajax/account/disbaleTwofactor.php',
|
||||||
|
'POST', data={
|
||||||
|
'code': code
|
||||||
}, sendtoken=True
|
}, sendtoken=True
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,6 +20,12 @@ class CredentialsError(AternosError):
|
||||||
which means incorrect credentials"""
|
which means incorrect credentials"""
|
||||||
|
|
||||||
|
|
||||||
|
class TwoFactorAuthError(CredentialsError):
|
||||||
|
|
||||||
|
"""Raised if 2FA is enabled,
|
||||||
|
but code was not passed to a login function"""
|
||||||
|
|
||||||
|
|
||||||
class TokenError(AternosError):
|
class TokenError(AternosError):
|
||||||
|
|
||||||
"""Raised when the parser is unable
|
"""Raised when the parser is unable
|
||||||
|
|
Reference in a new issue