Skip to content

Commit b6a2e21

Browse files
committed
added more parameters for outbound apps
1 parent 7512514 commit b6a2e21

File tree

3 files changed

+228
-9
lines changed

3 files changed

+228
-9
lines changed

README.md

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,7 @@ apps = apps_resp["apps"]
13071307
You can create, update, delete, load outbound applications and fetch tokens for them:
13081308

13091309
```python
1310-
# Create an outbound application
1310+
# Create a basic outbound application
13111311
response = descope_client.mgmt.outbound_application.create_application(
13121312
name="my new app",
13131313
description="my desc",
@@ -1316,14 +1316,67 @@ response = descope_client.mgmt.outbound_application.create_application(
13161316
)
13171317
app_id = response["app"]["id"]
13181318

1319-
# Update an outbound application
1319+
# Create a full OAuth outbound application with all parameters
1320+
from descope.management.common import URLParam, AccessType, PromptType
1321+
1322+
# Create URL parameters for authorization
1323+
auth_params = [
1324+
URLParam("response_type", "code"),
1325+
URLParam("client_id", "my-client-id"),
1326+
URLParam("redirect_uri", "https://myapp.com/callback")
1327+
]
1328+
1329+
# Create URL parameters for token endpoint
1330+
token_params = [
1331+
URLParam("grant_type", "authorization_code"),
1332+
URLParam("client_id", "my-client-id")
1333+
]
1334+
1335+
# Create prompt types
1336+
prompts = [PromptType.LOGIN, PromptType.CONSENT]
1337+
1338+
full_app = descope_client.mgmt.outbound_application.create_application(
1339+
name="My OAuth App",
1340+
description="A full OAuth outbound application",
1341+
logo="https://example.com/logo.png",
1342+
id="my-custom-id", # Optional custom ID
1343+
client_secret="my-secret-key",
1344+
client_id="my-client-id",
1345+
discovery_url="https://accounts.google.com/.well-known/openid_configuration",
1346+
authorization_url="https://accounts.google.com/o/oauth2/v2/auth",
1347+
authorization_url_params=auth_params,
1348+
token_url="https://oauth2.googleapis.com/token",
1349+
token_url_params=token_params,
1350+
revocation_url="https://oauth2.googleapis.com/revoke",
1351+
default_scopes=["https://www.googleapis.com/auth/userinfo.profile"],
1352+
default_redirect_url="https://myapp.com/callback",
1353+
callback_domain="myapp.com",
1354+
pkce=True, # Enable PKCE
1355+
access_type=AccessType.OFFLINE, # Request refresh tokens
1356+
prompt=prompts
1357+
)
1358+
1359+
# Update an outbound application with all parameters
13201360
# Update will override all fields as is. Use carefully.
13211361
descope_client.mgmt.outbound_application.update_application(
13221362
id="my-app-id",
13231363
name="my updated app",
13241364
description="updated description",
13251365
logo="https://example.com/logo.png",
13261366
client_secret="new-secret", # Optional
1367+
client_id="new-client-id",
1368+
discovery_url="https://accounts.google.com/.well-known/openid_configuration",
1369+
authorization_url="https://accounts.google.com/o/oauth2/v2/auth",
1370+
authorization_url_params=auth_params,
1371+
token_url="https://oauth2.googleapis.com/token",
1372+
token_url_params=token_params,
1373+
revocation_url="https://oauth2.googleapis.com/revoke",
1374+
default_scopes=["https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email"],
1375+
default_redirect_url="https://myapp.com/updated-callback",
1376+
callback_domain="myapp.com",
1377+
pkce=True,
1378+
access_type=AccessType.OFFLINE,
1379+
prompt=[PromptType.LOGIN, PromptType.CONSENT, PromptType.SELECT_ACCOUNT]
13271380
)
13281381

13291382
# Delete an outbound application by id

descope/management/common.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,32 @@
1-
from typing import List, Optional
1+
from typing import List, Optional, Dict, Any
2+
from enum import Enum
3+
4+
5+
class AccessType(Enum):
6+
OFFLINE = "offline"
7+
ONLINE = "online"
8+
9+
10+
class PromptType(Enum):
11+
NONE = "none"
12+
LOGIN = "login"
13+
CONSENT = "consent"
14+
SELECT_ACCOUNT = "select_account"
15+
16+
17+
class URLParam:
18+
def __init__(self, name: str, value: str):
19+
self.name = name
20+
self.value = value
21+
22+
def to_dict(self) -> dict:
23+
return {"name": self.name, "value": self.value}
24+
25+
26+
def url_params_to_dict(url_params: Optional[List[URLParam]] = None) -> list:
27+
if url_params is None:
28+
return []
29+
return [param.to_dict() for param in url_params]
230

331

432
class MgmtV1:
@@ -27,8 +55,12 @@ class MgmtV1:
2755
outbound_application_load_all_path = "/v1/mgmt/outbound/apps"
2856
outbound_application_fetch_token_by_scopes_path = "/v1/mgmt/outbound/app/user/token"
2957
outbound_application_fetch_token_path = "/v1/mgmt/outbound/app/user/token/latest"
30-
outbound_application_fetch_tenant_token_by_scopes_path = "/v1/mgmt/outbound/app/tenant/token"
31-
outbound_application_fetch_tenant_token_path = "/v1/mgmt/outbound/app/tenant/token/latest"
58+
outbound_application_fetch_tenant_token_by_scopes_path = (
59+
"/v1/mgmt/outbound/app/tenant/token"
60+
)
61+
outbound_application_fetch_tenant_token_path = (
62+
"/v1/mgmt/outbound/app/tenant/token/latest"
63+
)
3264

3365
# user
3466
user_create_path = "/v1/mgmt/user/create"
@@ -376,7 +408,8 @@ def sort_to_dict(sort: List[Sort]) -> list:
376408
)
377409
return sort_list
378410

411+
379412
def map_to_values_object(input_map: dict):
380413
if not input_map:
381414
return {}
382-
return {k: {"values": v} for k, v in input_map.items()}
415+
return {k: {"values": v} for k, v in input_map.items()}

descope/management/outbound_application.py

Lines changed: 136 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
from typing import Any, List, Optional
22

33
from descope._auth_base import AuthBase
4-
from descope.management.common import MgmtV1
4+
from descope.management.common import (
5+
MgmtV1,
6+
URLParam,
7+
AccessType,
8+
PromptType,
9+
url_params_to_dict,
10+
)
511

612

713
class OutboundApplication(AuthBase):
@@ -12,6 +18,19 @@ def create_application(
1218
logo: Optional[str] = None,
1319
id: Optional[str] = None,
1420
client_secret: Optional[str] = None,
21+
client_id: Optional[str] = None,
22+
discovery_url: Optional[str] = None,
23+
authorization_url: Optional[str] = None,
24+
authorization_url_params: Optional[List[URLParam]] = None,
25+
token_url: Optional[str] = None,
26+
token_url_params: Optional[List[URLParam]] = None,
27+
revocation_url: Optional[str] = None,
28+
default_scopes: Optional[List[str]] = None,
29+
default_redirect_url: Optional[str] = None,
30+
callback_domain: Optional[str] = None,
31+
pkce: Optional[bool] = None,
32+
access_type: Optional[AccessType] = None,
33+
prompt: Optional[List[PromptType]] = None,
1534
) -> dict:
1635
"""
1736
Create a new outbound application with the given name. Outbound application IDs are provisioned automatically, but can be provided
@@ -23,6 +42,19 @@ def create_application(
2342
logo (str): Optional outbound application logo.
2443
id (str): Optional outbound application ID.
2544
client_secret (str): Optional client secret for the application.
45+
client_id (str): Optional client ID for the application.
46+
discovery_url (str): Optional OAuth discovery URL.
47+
authorization_url (str): Optional OAuth authorization URL.
48+
authorization_url_params (List[URLParam]): Optional authorization URL parameters.
49+
token_url (str): Optional OAuth token URL.
50+
token_url_params (List[URLParam]): Optional token URL parameters.
51+
revocation_url (str): Optional OAuth token revocation URL.
52+
default_scopes (List[str]): Optional default OAuth scopes.
53+
default_redirect_url (str): Optional default redirect URL.
54+
callback_domain (str): Optional callback domain.
55+
pkce (bool): Optional PKCE (Proof Key for Code Exchange) support.
56+
access_type (AccessType): Optional OAuth access type.
57+
prompt (List[PromptType]): Optional OAuth prompt parameters.
2658
2759
Return value (dict):
2860
Return dict in the format
@@ -35,7 +67,24 @@ def create_application(
3567
response = self._auth.do_post(
3668
uri,
3769
OutboundApplication._compose_create_update_body(
38-
name, description, logo, id, client_secret
70+
name,
71+
description,
72+
logo,
73+
id,
74+
client_secret,
75+
client_id,
76+
discovery_url,
77+
authorization_url,
78+
authorization_url_params,
79+
token_url,
80+
token_url_params,
81+
revocation_url,
82+
default_scopes,
83+
default_redirect_url,
84+
callback_domain,
85+
pkce,
86+
access_type,
87+
prompt,
3988
),
4089
pswd=self._auth.management_key,
4190
)
@@ -48,6 +97,19 @@ def update_application(
4897
description: Optional[str] = None,
4998
logo: Optional[str] = None,
5099
client_secret: Optional[str] = None,
100+
client_id: Optional[str] = None,
101+
discovery_url: Optional[str] = None,
102+
authorization_url: Optional[str] = None,
103+
authorization_url_params: Optional[List[URLParam]] = None,
104+
token_url: Optional[str] = None,
105+
token_url_params: Optional[List[URLParam]] = None,
106+
revocation_url: Optional[str] = None,
107+
default_scopes: Optional[List[str]] = None,
108+
default_redirect_url: Optional[str] = None,
109+
callback_domain: Optional[str] = None,
110+
pkce: Optional[bool] = None,
111+
access_type: Optional[AccessType] = None,
112+
prompt: Optional[List[PromptType]] = None,
51113
) -> dict:
52114
"""
53115
Update an existing outbound application with the given parameters. IMPORTANT: All parameters are used as overrides
@@ -59,6 +121,19 @@ def update_application(
59121
description (str): Optional outbound application description.
60122
logo (str): Optional outbound application logo.
61123
client_secret (str): Optional client secret for the application.
124+
client_id (str): Optional client ID for the application.
125+
discovery_url (str): Optional OAuth discovery URL.
126+
authorization_url (str): Optional OAuth authorization URL.
127+
authorization_url_params (List[URLParam]): Optional authorization URL parameters.
128+
token_url (str): Optional OAuth token URL.
129+
token_url_params (List[URLParam]): Optional token URL parameters.
130+
revocation_url (str): Optional OAuth token revocation URL.
131+
default_scopes (List[str]): Optional default OAuth scopes.
132+
default_redirect_url (str): Optional default redirect URL.
133+
callback_domain (str): Optional callback domain.
134+
pkce (bool): Optional PKCE (Proof Key for Code Exchange) support.
135+
access_type (AccessType): Optional OAuth access type.
136+
prompt (List[PromptType]): Optional OAuth prompt parameters.
62137
63138
Return value (dict):
64139
Return dict in the format
@@ -72,7 +147,24 @@ def update_application(
72147
uri,
73148
{
74149
"app": OutboundApplication._compose_create_update_body(
75-
name, description, logo, id, client_secret
150+
name,
151+
description,
152+
logo,
153+
id,
154+
client_secret,
155+
client_id,
156+
discovery_url,
157+
authorization_url,
158+
authorization_url_params,
159+
token_url,
160+
token_url_params,
161+
revocation_url,
162+
default_scopes,
163+
default_redirect_url,
164+
callback_domain,
165+
pkce,
166+
access_type,
167+
prompt,
76168
)
77169
},
78170
pswd=self._auth.management_key,
@@ -290,6 +382,19 @@ def _compose_create_update_body(
290382
logo: Optional[str] = None,
291383
id: Optional[str] = None,
292384
client_secret: Optional[str] = None,
385+
client_id: Optional[str] = None,
386+
discovery_url: Optional[str] = None,
387+
authorization_url: Optional[str] = None,
388+
authorization_url_params: Optional[List[URLParam]] = None,
389+
token_url: Optional[str] = None,
390+
token_url_params: Optional[List[URLParam]] = None,
391+
revocation_url: Optional[str] = None,
392+
default_scopes: Optional[List[str]] = None,
393+
default_redirect_url: Optional[str] = None,
394+
callback_domain: Optional[str] = None,
395+
pkce: Optional[bool] = None,
396+
access_type: Optional[AccessType] = None,
397+
prompt: Optional[List[PromptType]] = None,
293398
) -> dict:
294399
body: dict[str, Any] = {
295400
"name": name,
@@ -299,4 +404,32 @@ def _compose_create_update_body(
299404
}
300405
if client_secret:
301406
body["clientSecret"] = client_secret
407+
if client_id:
408+
body["clientId"] = client_id
409+
if discovery_url:
410+
body["discoveryUrl"] = discovery_url
411+
if authorization_url:
412+
body["authorizationUrl"] = authorization_url
413+
if authorization_url_params:
414+
body["authorizationUrlParams"] = url_params_to_dict(
415+
authorization_url_params
416+
)
417+
if token_url:
418+
body["tokenUrl"] = token_url
419+
if token_url_params:
420+
body["tokenUrlParams"] = url_params_to_dict(token_url_params)
421+
if revocation_url:
422+
body["revocationUrl"] = revocation_url
423+
if default_scopes:
424+
body["defaultScopes"] = default_scopes
425+
if default_redirect_url:
426+
body["defaultRedirectUrl"] = default_redirect_url
427+
if callback_domain:
428+
body["callbackDomain"] = callback_domain
429+
if pkce is not None:
430+
body["pkce"] = pkce
431+
if access_type:
432+
body["accessType"] = access_type.value
433+
if prompt:
434+
body["prompt"] = [p.value for p in prompt]
302435
return body

0 commit comments

Comments
 (0)