mirror of
https://github.com/vale981/outlook-oauth-hack
synced 2025-03-04 08:31:38 -05:00
add password
This commit is contained in:
parent
1d96d930db
commit
f5a0af281f
6 changed files with 48 additions and 22 deletions
33
config.py
33
config.py
|
@ -2,12 +2,18 @@ from pathlib import Path
|
||||||
import tomllib
|
import tomllib
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
import sys
|
import sys
|
||||||
|
import json
|
||||||
|
import gnupg
|
||||||
|
gpg = gnupg.GPG()
|
||||||
|
|
||||||
def get_config(profile):
|
def get_config(profile):
|
||||||
with open(Path.home() / ".o365-auth-config.toml", "rb") as f:
|
with open(Path.home() / ".o365-auth-config.toml", "rb") as f:
|
||||||
toplevel_data = tomllib.load(f)
|
toplevel_data = tomllib.load(f)
|
||||||
|
|
||||||
|
password = None
|
||||||
|
if "security" in toplevel_data and "password" in toplevel_data["security"]:
|
||||||
|
password = Path(toplevel_data["security"]["PasswordPath"]).read_text().strip()
|
||||||
|
|
||||||
|
|
||||||
default_data = toplevel_data["default"]
|
default_data = toplevel_data["default"]
|
||||||
config_data = default_data | toplevel_data.get(profile, {})
|
config_data = default_data | toplevel_data.get(profile, {})
|
||||||
|
@ -20,8 +26,33 @@ def get_config(profile):
|
||||||
Scopes = config_data["Scopes"],
|
Scopes = config_data["Scopes"],
|
||||||
CacheFile = cache_path / "cache.json",
|
CacheFile = cache_path / "cache.json",
|
||||||
Authority = config_data["Authority"] or None,
|
Authority = config_data["Authority"] or None,
|
||||||
|
Password = password
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_cache(config):
|
||||||
|
if not config.CacheFile.exists():
|
||||||
|
return None
|
||||||
|
|
||||||
|
data = config.CacheFile.read_text()
|
||||||
|
if config.Password:
|
||||||
|
data = gpg.decrypt(data, passphrase=config.Password).data.decode("utf-8")
|
||||||
|
|
||||||
|
return json.loads(data)
|
||||||
|
|
||||||
|
def write_cache(config, token):
|
||||||
|
with open(config.CacheFile, "w") as f:
|
||||||
|
payload = {'refresh_token': token['refresh_token'],
|
||||||
|
'expires_in': token['expires_in'],
|
||||||
|
'access_token': token['access_token']}
|
||||||
|
|
||||||
|
|
||||||
|
json_string = json.dumps(payload)
|
||||||
|
if config.Password:
|
||||||
|
encrypted_data = gpg.encrypt(json_string, symmetric="AES256", passphrase=config.Password, armor=True, recipients=None)
|
||||||
|
json_string = str(encrypted_data)
|
||||||
|
|
||||||
|
f.write(json_string)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
sys.exit(f"Usage: {sys.argv[0]} <profile> <key>")
|
sys.exit(f"Usage: {sys.argv[0]} <profile> <key>")
|
||||||
|
|
|
@ -3,5 +3,4 @@ ClientId = "08162f7c-0fd2-4200-a84a-f25a4db0b584"
|
||||||
ClientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82"
|
ClientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82"
|
||||||
Scopes = ['https://outlook.office.com/IMAP.AccessAsUser.All','https://outlook.office.com/SMTP.Send']
|
Scopes = ['https://outlook.office.com/IMAP.AccessAsUser.All','https://outlook.office.com/SMTP.Send']
|
||||||
Authority = false
|
Authority = false
|
||||||
|
PasswordPath = false
|
||||||
[mcgill]
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
name = "o365-auth";
|
name = "o365-auth";
|
||||||
propagatedBuildInputs = [
|
propagatedBuildInputs = [
|
||||||
(pkgs.python3.withPackages (pythonPackages: with pythonPackages; [
|
(pkgs.python3.withPackages (pythonPackages: with pythonPackages; [
|
||||||
msal
|
msal python-gnupg
|
||||||
]))
|
]))
|
||||||
];
|
];
|
||||||
dontUnpack = true;
|
dontUnpack = true;
|
||||||
|
|
|
@ -78,8 +78,4 @@ if 'error' in token:
|
||||||
print(token)
|
print(token)
|
||||||
sys.exit("Failed to get access token")
|
sys.exit("Failed to get access token")
|
||||||
|
|
||||||
|
config.write_cache(profile_config, token)
|
||||||
with open(profile_config.CacheFile, 'w') as f:
|
|
||||||
json.dump({'refresh_token': token['refresh_token'],
|
|
||||||
'expires_in': token['expires_in'],
|
|
||||||
'access_token': token['access_token']}, f)
|
|
||||||
|
|
|
@ -17,6 +17,9 @@ in
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = package;
|
default = package;
|
||||||
};
|
};
|
||||||
|
passwordPath = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
config = mkOption {
|
config = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = ''
|
default = ''
|
||||||
|
@ -25,12 +28,14 @@ in
|
||||||
ClientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82"
|
ClientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82"
|
||||||
Scopes = ['https://outlook.office.com/IMAP.AccessAsUser.All','https://outlook.office.com/SMTP.Send']
|
Scopes = ['https://outlook.office.com/IMAP.AccessAsUser.All','https://outlook.office.com/SMTP.Send']
|
||||||
Authority = false
|
Authority = false
|
||||||
Timeout = 3600
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
home.packages = [ cfg.package ];
|
home.packages = [ cfg.package ];
|
||||||
home.file.".o365-auth-config.toml".text = cfg.config;
|
home.file.".o365-auth-config.toml".text = cfg.config + ''
|
||||||
|
[security]
|
||||||
|
PasswordPath = "${cfg.passwordPath}"
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import config
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import json
|
|
||||||
print_access_token = True
|
print_access_token = True
|
||||||
|
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
|
@ -19,11 +19,10 @@ cache = SerializableTokenCache()
|
||||||
app = ConfidentialClientApplication(profile_config.ClientId, client_credential=profile_config.ClientSecret, token_cache=cache, authority=profile_config.Authority)
|
app = ConfidentialClientApplication(profile_config.ClientId, client_credential=profile_config.ClientSecret, token_cache=cache, authority=profile_config.Authority)
|
||||||
|
|
||||||
|
|
||||||
if not profile_config.CacheFile.exists():
|
token_cache = config.get_cache(profile_config)
|
||||||
|
if not token_cache:
|
||||||
sys.exit("Please get the initial token by running `o365-get-token` first.")
|
sys.exit("Please get the initial token by running `o365-get-token` first.")
|
||||||
|
|
||||||
token_cache = json.loads(profile_config.CacheFile.read_text())
|
|
||||||
|
|
||||||
st = os.stat(profile_config.CacheFile)
|
st = os.stat(profile_config.CacheFile)
|
||||||
if (time.time()-st.st_mtime) < token_cache["expires_in"]:
|
if (time.time()-st.st_mtime) < token_cache["expires_in"]:
|
||||||
print(token_cache["access_token"])
|
print(token_cache["access_token"])
|
||||||
|
@ -37,10 +36,6 @@ if 'error' in token:
|
||||||
sys.exit("Failed to get access token")
|
sys.exit("Failed to get access token")
|
||||||
|
|
||||||
|
|
||||||
# you're supposed to save the old refresh token each time
|
config.write_cache(profile_config, token)
|
||||||
with open(profile_config.CacheFile, 'w') as f:
|
if print_access_token:
|
||||||
json.dump({'refresh_token': token['refresh_token'],
|
print(token['access_token'])
|
||||||
'expires_in': token['expires_in'],
|
|
||||||
'access_token': token['access_token']}, f)
|
|
||||||
if print_access_token:
|
|
||||||
print(token['access_token'])
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue