2023-11-13 14:16:41 +00:00
|
|
|
from secrets import token_hex
|
2023-10-09 19:58:44 +00:00
|
|
|
from flask import Flask
|
2022-02-19 22:16:13 +00:00
|
|
|
from ory_hydra_client import Client
|
|
|
|
from typing import Optional
|
2023-11-13 14:16:41 +00:00
|
|
|
from ory_hydra_client.api.o_auth_2 import list_o_auth_2_clients, create_o_auth_2_client, set_o_auth_2_client
|
2023-10-09 19:58:44 +00:00
|
|
|
from ory_hydra_client.models.o_auth_20_client import OAuth20Client
|
2022-02-19 22:16:13 +00:00
|
|
|
|
2023-11-13 14:16:41 +00:00
|
|
|
import logging
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
2022-02-19 22:16:13 +00:00
|
|
|
|
|
|
|
class HydraService:
|
|
|
|
|
2023-10-09 19:58:44 +00:00
|
|
|
def __init__(self) -> None:
|
2023-03-18 11:00:40 +00:00
|
|
|
self._hydra_client: Optional[Client] = None
|
|
|
|
self._oauth_client: Optional[Client] = None
|
2022-02-19 22:16:13 +00:00
|
|
|
|
2023-10-09 19:58:44 +00:00
|
|
|
self.client_id = ''
|
|
|
|
self.client_secret = ''
|
|
|
|
|
|
|
|
def init_app(self, app: Flask) -> None:
|
|
|
|
|
|
|
|
self.set_hydra_client(Client(base_url=app.config['HYDRA_ADMIN_URL']))
|
|
|
|
|
|
|
|
client_name = app.config['OAUTH_ID']
|
2023-12-23 01:41:26 +00:00
|
|
|
client_secret = app.config['OAUTH_SECRET']
|
2023-12-24 10:10:49 +00:00
|
|
|
public_url = app.config['PUBLIC_URL']
|
2023-10-09 19:58:44 +00:00
|
|
|
|
|
|
|
clients = list_o_auth_2_clients.sync_detailed(_client=self.hydra_client).parsed
|
|
|
|
if clients is None:
|
|
|
|
raise RuntimeError("could not get clients list")
|
|
|
|
client: Optional[OAuth20Client] = None
|
|
|
|
for c in clients:
|
|
|
|
if c.client_name == client_name:
|
|
|
|
client = c
|
|
|
|
break
|
|
|
|
|
|
|
|
if client is None:
|
2023-12-24 10:10:49 +00:00
|
|
|
client_req = OAuth20Client(
|
2023-10-09 19:58:44 +00:00
|
|
|
client_name="identiy_provider",
|
|
|
|
# client_id=client_id,
|
|
|
|
client_secret=client_secret,
|
|
|
|
response_types=["code", "id_token"],
|
|
|
|
scope="openid profile manage",
|
|
|
|
grant_types=["authorization_code", "refresh_token"],
|
2023-12-17 13:47:38 +00:00
|
|
|
redirect_uris=[ f"{public_url}/oauth/authorized" ],
|
2023-10-09 19:58:44 +00:00
|
|
|
token_endpoint_auth_method="client_secret_basic",
|
|
|
|
)
|
2023-12-24 10:10:49 +00:00
|
|
|
ret = create_o_auth_2_client.sync(json_body=client_req, _client=self.hydra_client)
|
2023-10-09 19:58:44 +00:00
|
|
|
if ret is None:
|
2023-12-23 01:41:26 +00:00
|
|
|
raise RuntimeError("could not create account")
|
2023-12-24 10:10:49 +00:00
|
|
|
client = ret
|
2023-11-13 14:16:41 +00:00
|
|
|
else:
|
|
|
|
client.client_secret = client_secret
|
2023-12-24 10:10:49 +00:00
|
|
|
client.redirect_uris = [ f"{public_url}/oauth/authorized" ]
|
2023-12-23 01:41:26 +00:00
|
|
|
ret = set_o_auth_2_client.sync(id=client.client_id, json_body=client, _client=self.hydra_client)
|
2023-11-13 14:16:41 +00:00
|
|
|
if ret is None:
|
2023-12-23 01:41:26 +00:00
|
|
|
raise RuntimeError("could not update account")
|
2023-10-09 19:58:44 +00:00
|
|
|
if type(client.client_id) is not str:
|
|
|
|
raise RuntimeError("could not parse client_id from ory-hydra")
|
|
|
|
self.client_id = client.client_id
|
|
|
|
self.client_secret = client_secret
|
|
|
|
|
|
|
|
|
2022-02-19 22:16:13 +00:00
|
|
|
@property
|
|
|
|
def hydra_client(self) -> Client:
|
|
|
|
if self._hydra_client is None:
|
|
|
|
raise RuntimeError('need to init client first')
|
|
|
|
return self._hydra_client
|
|
|
|
|
|
|
|
def set_hydra_client(self, client: Client) -> None:
|
|
|
|
self._hydra_client = client
|
|
|
|
|
|
|
|
@property
|
|
|
|
def oauth_client(self) -> Client:
|
|
|
|
if self._oauth_client is None:
|
|
|
|
raise RuntimeError('need to init client first')
|
|
|
|
return self._oauth_client
|
|
|
|
|
|
|
|
def set_oauth_client(self, client: Client) -> None:
|
|
|
|
self._hydra_client = client
|
|
|
|
|
|
|
|
|
|
|
|
hydra_service = HydraService()
|