Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
* [#687](https://github.com/workos/workos-python/pull/687) fix(generated): regenerate from spec

**Features**
* **[user_management](https://workos.com/docs/reference/authkit/user)**:
* Added model `UserRoleAssignmentSource`
* Added `source` to `UserRoleAssignment`
* Added enum `UserRoleAssignmentSourceType`
* Added parameter `UserManagementAuthentication.authorize.max_age`
* Added endpoint `GET /user_management/cors_origins`
* Added endpoint `GET /user_management/redirect_uris`

**Fixes**
* Restore mistakenly removed CreateMagicAuth logic from previous release
2 changes: 1 addition & 1 deletion .last-synced-sha
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4b4e0618779460dbebc1cf5e0f02197c21796d1f
23faa38318d596e581656934ed72c4a18476d742
1 change: 0 additions & 1 deletion .oagen-manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"version": 2,
"language": "python",
"generatedAt": "2026-07-02T17:29:55.736Z",
"files": [
"src/workos/_client.py",
"src/workos/admin_portal/__init__.py",
Expand Down
176 changes: 176 additions & 0 deletions src/workos/user_management/_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ def authenticate_with_password(
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
signals_id: Optional[str] = None,
radar_auth_attempt_id: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with password."""
Expand All @@ -196,6 +198,10 @@ def authenticate_with_password(
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent
if signals_id is not None:
body["signals_id"] = signals_id
if radar_auth_attempt_id is not None:
body["radar_auth_attempt_id"] = radar_auth_attempt_id

return self._client.request(
method="POST",
Expand All @@ -214,6 +220,7 @@ def authenticate_with_code(
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
signals_id: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with code."""
Expand All @@ -235,6 +242,8 @@ def authenticate_with_code(
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent
if signals_id is not None:
body["signals_id"] = signals_id

return self._client.request(
method="POST",
Expand Down Expand Up @@ -289,6 +298,7 @@ def authenticate_with_magic_auth(
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
radar_auth_attempt_id: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with magic auth."""
Expand All @@ -309,6 +319,8 @@ def authenticate_with_magic_auth(
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent
if radar_auth_attempt_id is not None:
body["radar_auth_attempt_id"] = radar_auth_attempt_id

return self._client.request(
method="POST",
Expand Down Expand Up @@ -456,6 +468,82 @@ def authenticate_with_device_code(
request_options=request_options,
)

def authenticate_with_radar_email_challenge(
self,
*,
code: str,
radar_challenge_id: str,
pending_authentication_token: str,
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with radar email challenge."""
body: Dict[str, Any] = {
"grant_type": "urn:workos:oauth:grant-type:radar-email-challenge:code",
"code": code,
"radar_challenge_id": radar_challenge_id,
"pending_authentication_token": pending_authentication_token,
}
if self._client.client_id is not None:
body["client_id"] = self._client.client_id
if self._client._api_key is not None:
body["client_secret"] = self._client._api_key
if ip_address is not None:
body["ip_address"] = ip_address
if device_id is not None:
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent

return self._client.request(
method="POST",
path=("user_management", "authenticate"),
body=body,
model=AuthenticateResponse,
request_options=request_options,
)

def authenticate_with_radar_sms_challenge(
self,
*,
code: str,
verification_id: str,
phone_number: str,
pending_authentication_token: str,
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with radar sms challenge."""
body: Dict[str, Any] = {
"grant_type": "urn:workos:oauth:grant-type:radar-sms-challenge:code",
"code": code,
"verification_id": verification_id,
"phone_number": phone_number,
"pending_authentication_token": pending_authentication_token,
}
if self._client.client_id is not None:
body["client_id"] = self._client.client_id
if self._client._api_key is not None:
body["client_secret"] = self._client._api_key
if ip_address is not None:
body["ip_address"] = ip_address
if device_id is not None:
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent

return self._client.request(
method="POST",
path=("user_management", "authenticate"),
body=body,
model=AuthenticateResponse,
request_options=request_options,
)

def get_authorization_url(
self,
*,
Expand Down Expand Up @@ -2379,6 +2467,8 @@ async def authenticate_with_password(
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
signals_id: Optional[str] = None,
radar_auth_attempt_id: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with password."""
Expand All @@ -2399,6 +2489,10 @@ async def authenticate_with_password(
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent
if signals_id is not None:
body["signals_id"] = signals_id
if radar_auth_attempt_id is not None:
body["radar_auth_attempt_id"] = radar_auth_attempt_id

return await self._client.request(
method="POST",
Expand All @@ -2417,6 +2511,7 @@ async def authenticate_with_code(
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
signals_id: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with code."""
Expand All @@ -2438,6 +2533,8 @@ async def authenticate_with_code(
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent
if signals_id is not None:
body["signals_id"] = signals_id

return await self._client.request(
method="POST",
Expand Down Expand Up @@ -2492,6 +2589,7 @@ async def authenticate_with_magic_auth(
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
radar_auth_attempt_id: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with magic auth."""
Expand All @@ -2512,6 +2610,8 @@ async def authenticate_with_magic_auth(
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent
if radar_auth_attempt_id is not None:
body["radar_auth_attempt_id"] = radar_auth_attempt_id

return await self._client.request(
method="POST",
Expand Down Expand Up @@ -2659,6 +2759,82 @@ async def authenticate_with_device_code(
request_options=request_options,
)

async def authenticate_with_radar_email_challenge(
self,
*,
code: str,
radar_challenge_id: str,
pending_authentication_token: str,
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with radar email challenge."""
body: Dict[str, Any] = {
"grant_type": "urn:workos:oauth:grant-type:radar-email-challenge:code",
"code": code,
"radar_challenge_id": radar_challenge_id,
"pending_authentication_token": pending_authentication_token,
}
if self._client.client_id is not None:
body["client_id"] = self._client.client_id
if self._client._api_key is not None:
body["client_secret"] = self._client._api_key
if ip_address is not None:
body["ip_address"] = ip_address
if device_id is not None:
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent

return await self._client.request(
method="POST",
path=("user_management", "authenticate"),
body=body,
model=AuthenticateResponse,
request_options=request_options,
)

async def authenticate_with_radar_sms_challenge(
self,
*,
code: str,
verification_id: str,
phone_number: str,
pending_authentication_token: str,
ip_address: Optional[str] = None,
device_id: Optional[str] = None,
user_agent: Optional[str] = None,
request_options: Optional[RequestOptions] = None,
) -> AuthenticateResponse:
"""Authenticate with radar sms challenge."""
body: Dict[str, Any] = {
"grant_type": "urn:workos:oauth:grant-type:radar-sms-challenge:code",
"code": code,
"verification_id": verification_id,
"phone_number": phone_number,
"pending_authentication_token": pending_authentication_token,
}
if self._client.client_id is not None:
body["client_id"] = self._client.client_id
if self._client._api_key is not None:
body["client_secret"] = self._client._api_key
if ip_address is not None:
body["ip_address"] = ip_address
if device_id is not None:
body["device_id"] = device_id
if user_agent is not None:
body["user_agent"] = user_agent

return await self._client.request(
method="POST",
path=("user_management", "authenticate"),
body=body,
model=AuthenticateResponse,
request_options=request_options,
)

def get_authorization_url(
self,
*,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,32 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Dict, Optional
from datetime import datetime
from typing import Any, Dict, Literal, Optional
from workos._types import _raise_deserialize_error
from workos._types import _format_datetime, _parse_datetime


@dataclass(slots=True)
class MagicAuthSendMagicAuthCodeAndReturnResponse:
"""Magic Auth Send Magic Auth Code And Return Response model."""

object: Literal["magic_auth"]
"""Distinguishes the Magic Auth object."""
id: str
"""The unique ID of the Magic Auth code."""
user_id: str
"""The unique ID of the user."""
email: str
"""The email address of the user."""
expires_at: datetime
"""The timestamp when the Magic Auth code expires."""
created_at: datetime
"""An ISO 8601 timestamp."""
updated_at: datetime
"""An ISO 8601 timestamp."""
code: str
"""The code used to verify the Magic Auth code."""
radar_auth_attempt_id: Optional[str] = None
"""The ID of the Radar authentication attempt created for this request when Radar is enabled. Pass this value to the authenticate endpoint to associate the subsequent authentication with this Radar attempt."""

Expand All @@ -21,6 +39,14 @@ def from_dict(
"""Deserialize from a dictionary."""
try:
return cls(
object=data.get("object", "magic_auth"),
id=data["id"],
user_id=data["user_id"],
email=data["email"],
expires_at=_parse_datetime(data["expires_at"]),
created_at=_parse_datetime(data["created_at"]),
updated_at=_parse_datetime(data["updated_at"]),
code=data["code"],
radar_auth_attempt_id=data.get("radar_auth_attempt_id"),
)
except (KeyError, ValueError) as e:
Expand All @@ -29,6 +55,14 @@ def from_dict(
def to_dict(self) -> Dict[str, Any]:
"""Serialize to a dictionary."""
result: Dict[str, Any] = {}
result["object"] = self.object
result["id"] = self.id
result["user_id"] = self.user_id
result["email"] = self.email
result["expires_at"] = _format_datetime(self.expires_at)
result["created_at"] = _format_datetime(self.created_at)
result["updated_at"] = _format_datetime(self.updated_at)
result["code"] = self.code
if self.radar_auth_attempt_id is not None:
result["radar_auth_attempt_id"] = self.radar_auth_attempt_id
return result
Loading