JSON Webトークンは、JSON形式に基づいてアクセストークンを作成するためのオープンスタンダードです。通常、クライアントサーバーアプリケーションで認証データを渡すために使用されます。ウィキペディア
機密データをブラウザに保存する場合は、CookieまたはlocalStorageの2つの利用可能なオプションのいずれかを使用する必要があります。ここでは誰もが味わうことを選択します。ただし、この記事は、D-Bus上で実行され、Linuxに「シークレット」を格納するように設計されたサービスであるSecretServiceに捧げました。
このサービスには、GNOMEKeyringがアプリケーションシークレットを保存するために使用するAPIがあります。
なぜ秘密のサービス
問題は、私がブラウザでトークンを受け取っていなかったということです。gitで使用されているものと同様のコンソールアプリケーションのクライアント認証を作成していました。
次回アプリケーションを起動したときにユーザーに強制的にログインさせたくなかったので、詳細をどのように保存するかという問題がすぐに発生しました。
最初は暗号化されたファイルにトークンを保存するオプションがありましたが、暗号化と復号化の機能がバイクになると推測したため、すぐに消えました。
, Linux, , .
Linux.
Secret Service
Secret Service — .
. - «default». . Seahorse .

, Google Chrome VSCode. .
.
, .
, , .

, , , .
Secret Service
, flow chart.

« ?» — .
« » — .
« » — .
« API» — .
« » — .
« » — .
Python
Click Framework CLI .
import click, , . . , .
@click.group()
def cli():
pass.
:
$ app login
Email:
Password::
$ app login
Logged in!login
@cli.command(help="Login into your account.")
@click.option(
'--email',
prompt=True,
help='Registered email address.')
@click.option(
'--password',
prompt=True,
hide_input=True,
help='Password provided at registration.'
)
def login(email, password):
pass
if __name__ == '__main__':
cli() login, , email password.
@cli.command , @click.option .
, hide_input .
prompt , lick Framework , .
True False , :
TrueClick Framework . . , WEB API Secret Service, Secret Service API;FalseClick Framework . , , Secret Service.
, prompt_desicion. Secret Service. , Secret Service API .
. , , Click Framework.
, , Click Framework, .
app Click Framework. auth, Auth .
.
├── auth.py
└── app.py
prompt_desicion auth Auth auth.
@cli.command(help="Login into your account.")
@click.option(
'--email',
prompt=auth.prompt_desicion,
help='Registered email address.')
@click.option(
'--password',
prompt=auth.prompt_desicion,
hide_input=True,
help='Password provided at registration.'
)
def login(email, password):
pass
if __name__ == '__main__':
cli()
Python SecreteStorage, Secret Service API.
, Secret Service.
Secret Service API WEB API, prompt_desicion .
requests — HTTP WEB API.
secretstorage — Secret Service API.
json — .
import requests
import secretstorage
import jsonSecrete Storage
class Auth:
def __init__(self, email=None, password=None):
# ,
# Secret Service
self._attributes = {'application': 'MyApp'}
# Dbus
self._connection = secretstorage.dbus_init()
# -
self._collection = secretstorage.collection.get_default_collection(
self._connection
)
#
self._items = self._collection.search_items(self._attributes)
#
self._stored_secret = self.get_stored_secret().
Secret Service self._attributes.
«_»
, . , . , . , , . , .
, . () SecretStorage () . , , self._items .
get_stored_secret, .
class Auth:
def get_stored_secret(self):
for item in self._items:
if item:
return json.loads(item.get_secret())
Item secretstorage, get_secret, .
. .
.
True False — ,
, , : « — False».
class Auth:
def __init__(self, email=None, password=None):
# ,
self.prompt_desicion = False
. , .
class Auth:
def __init__(self, email=None, password=None):
# ,
#
if self._stored_secret:
# token
self.token = self._stored_secret['token']
#
elif email and password:
# WEB API
self.token = self.get_token(email, password)
#
self._valid_secret = {'token': self.token}
# Secret Service
self.set_stored_secret()
else:
# Secret Storage,
#
self.prompt_desicion = True- .
Secret Storage API.
, .
Secret Storage.
Secret Storage API.
, Secret Storage.
, .
, WEB API.
, Secret Storage.
Secret Storage WEB API.
WEB API
class Auth:
def get_token(self, email: str, password: str) -> str:
try:
response = requests.post(
API_URL,
data= {
'email': email,
'passwd': password
})
data = response.json()
except requests.exceptions.ConnectionError:
raise requests.exceptions.ConnectionError()
if response.status_code != 200:
raise requests.exceptions.HTTPError(data['msg'])
return data['data']['token'] API_URL API. , . , POST «email» «passwd».
API , API .
API «msg» . try .
«data».
Secret Storage
class Auth:
def set_stored_secret(self):
self._collection.create_item(
'MyApp',
self._attributes,
bytes((json.dumps(self._valid_secret)), 'utf-8')
)
create_item , .
lick Framework
auth.
from auth import AuthSecret Storage.
auth = Auth().
@cli.command(help="Login into VPN Manager account.")
@click.option(
'--email',
prompt=auth.prompt_desicion,
help='Registered email address.')
@click.option(
'--password',
prompt=auth.prompt_desicion,
hide_input=True,
help='Password provided at registration.'
)login.
def login(email, password):
global auth
try:
#
if auth.prompt_desicion:
# Secret Storage
auth = Auth(email, password)
except Exception:
return click.echo('No API connection')
# , .
click.echo(auth.token)Click Frameworkは、ヘルプを自動的に生成します。これを行うには、help彼のデコレータのパラメータで指定した行が必要です。
$ python app.py
Usage: app.py [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
login Login into your account.
ログインコマンドヘルプ
$ python app.py login --help
Usage: app.py login [OPTIONS]
Login into your account
Options:
--email TEXT Registered email address
--password TEXT Password provided at registration
--help Show this message and exit.小切手
コマンドを使用してアプリケーションを起動python app.py loginすると、メールとパスワードの入力を求められます。このデータが正しければ、対応する要素がシークレットサービスに表示されます。

実際にトークンを保存します。

再起動すると、アプリケーションは詳細を要求しませんが、シークレットサービスからトークンをダウンロードします。