Skip to content

Commit

Permalink
Release B2B step-up, OAuth refresh tokens, and other fixes (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
jennifer-stytch authored Mar 22, 2024
1 parent fe0f32f commit 53b10f8
Show file tree
Hide file tree
Showing 20 changed files with 208 additions and 70 deletions.
8 changes: 8 additions & 0 deletions stytch/b2b/api/magic_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def authenticate(
session_duration_minutes: Optional[int] = None,
session_custom_claims: Optional[Dict[str, Any]] = None,
locale: Optional[Union[AuthenticateRequestLocale, str]] = None,
intermediate_session_token: Optional[str] = None,
) -> AuthenticateResponse:
"""Authenticate a Member with a Magic Link. This endpoint requires a Magic Link token that is not expired or previously used. If the Member’s status is `pending` or `invited`, they will be updated to `active`.
Provide the `session_duration_minutes` parameter to set the lifetime of the session. If the `session_duration_minutes` parameter is not specified, a Stytch session will be created with a 60 minute duration.
Expand Down Expand Up @@ -88,6 +89,7 @@ def authenticate(
Request support for additional languages [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")!
- intermediate_session_token: (no documentation yet)
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
Expand All @@ -105,6 +107,8 @@ def authenticate(
data["session_custom_claims"] = session_custom_claims
if locale is not None:
data["locale"] = locale
if intermediate_session_token is not None:
data["intermediate_session_token"] = intermediate_session_token

url = self.api_base.url_for("/v1/b2b/magic_links/authenticate", data)
res = self.sync_client.post(url, data, headers)
Expand All @@ -119,6 +123,7 @@ async def authenticate_async(
session_duration_minutes: Optional[int] = None,
session_custom_claims: Optional[Dict[str, Any]] = None,
locale: Optional[AuthenticateRequestLocale] = None,
intermediate_session_token: Optional[str] = None,
) -> AuthenticateResponse:
"""Authenticate a Member with a Magic Link. This endpoint requires a Magic Link token that is not expired or previously used. If the Member’s status is `pending` or `invited`, they will be updated to `active`.
Provide the `session_duration_minutes` parameter to set the lifetime of the session. If the `session_duration_minutes` parameter is not specified, a Stytch session will be created with a 60 minute duration.
Expand Down Expand Up @@ -162,6 +167,7 @@ async def authenticate_async(
Request support for additional languages [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")!
- intermediate_session_token: (no documentation yet)
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
Expand All @@ -179,6 +185,8 @@ async def authenticate_async(
data["session_custom_claims"] = session_custom_claims
if locale is not None:
data["locale"] = locale
if intermediate_session_token is not None:
data["intermediate_session_token"] = intermediate_session_token

url = self.api_base.url_for("/v1/b2b/magic_links/authenticate", data)
res = await self.async_client.post(url, data, headers)
Expand Down
8 changes: 8 additions & 0 deletions stytch/b2b/api/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def authenticate(
session_custom_claims: Optional[Dict[str, Any]] = None,
pkce_code_verifier: Optional[str] = None,
locale: Optional[Union[AuthenticateRequestLocale, str]] = None,
intermediate_session_token: Optional[str] = None,
) -> AuthenticateResponse:
"""Authenticate a Member given a `token`. This endpoint verifies that the member completed the OAuth flow by verifying that the token is valid and hasn't expired. Provide the `session_duration_minutes` parameter to set the lifetime of the session. If the `session_duration_minutes` parameter is not specified, a Stytch session will be created with a 60 minute duration.
Expand Down Expand Up @@ -75,6 +76,7 @@ def authenticate(
Request support for additional languages [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")!
- intermediate_session_token: (no documentation yet)
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
Expand All @@ -92,6 +94,8 @@ def authenticate(
data["pkce_code_verifier"] = pkce_code_verifier
if locale is not None:
data["locale"] = locale
if intermediate_session_token is not None:
data["intermediate_session_token"] = intermediate_session_token

url = self.api_base.url_for("/v1/b2b/oauth/authenticate", data)
res = self.sync_client.post(url, data, headers)
Expand All @@ -106,6 +110,7 @@ async def authenticate_async(
session_custom_claims: Optional[Dict[str, Any]] = None,
pkce_code_verifier: Optional[str] = None,
locale: Optional[AuthenticateRequestLocale] = None,
intermediate_session_token: Optional[str] = None,
) -> AuthenticateResponse:
"""Authenticate a Member given a `token`. This endpoint verifies that the member completed the OAuth flow by verifying that the token is valid and hasn't expired. Provide the `session_duration_minutes` parameter to set the lifetime of the session. If the `session_duration_minutes` parameter is not specified, a Stytch session will be created with a 60 minute duration.
Expand Down Expand Up @@ -145,6 +150,7 @@ async def authenticate_async(
Request support for additional languages [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")!
- intermediate_session_token: (no documentation yet)
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
Expand All @@ -162,6 +168,8 @@ async def authenticate_async(
data["pkce_code_verifier"] = pkce_code_verifier
if locale is not None:
data["locale"] = locale
if intermediate_session_token is not None:
data["intermediate_session_token"] = intermediate_session_token

url = self.api_base.url_for("/v1/b2b/oauth/authenticate", data)
res = await self.async_client.post(url, data, headers)
Expand Down
20 changes: 12 additions & 8 deletions stytch/b2b/api/organizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,9 @@ def update(
auth_methods: Optional[str] = None,
allowed_auth_methods: Optional[List[str]] = None,
mfa_policy: Optional[str] = None,
rbac_email_implicit_role_assignments: Optional[List[str]] = None,
rbac_email_implicit_role_assignments: Optional[
List[EmailImplicitRoleAssignment]
] = None,
mfa_methods: Optional[str] = None,
allowed_mfa_methods: Optional[List[str]] = None,
method_options: Optional[UpdateRequestOptions] = None,
Expand Down Expand Up @@ -485,9 +487,9 @@ def update(
if mfa_policy is not None:
data["mfa_policy"] = mfa_policy
if rbac_email_implicit_role_assignments is not None:
data[
"rbac_email_implicit_role_assignments"
] = rbac_email_implicit_role_assignments
data["rbac_email_implicit_role_assignments"] = [
item.dict() for item in rbac_email_implicit_role_assignments
]
if mfa_methods is not None:
data["mfa_methods"] = mfa_methods
if allowed_mfa_methods is not None:
Expand All @@ -513,7 +515,9 @@ async def update_async(
auth_methods: Optional[str] = None,
allowed_auth_methods: Optional[List[str]] = None,
mfa_policy: Optional[str] = None,
rbac_email_implicit_role_assignments: Optional[List[str]] = None,
rbac_email_implicit_role_assignments: Optional[
List[EmailImplicitRoleAssignment]
] = None,
mfa_methods: Optional[str] = None,
allowed_mfa_methods: Optional[List[str]] = None,
method_options: Optional[UpdateRequestOptions] = None,
Expand Down Expand Up @@ -665,9 +669,9 @@ async def update_async(
if mfa_policy is not None:
data["mfa_policy"] = mfa_policy
if rbac_email_implicit_role_assignments is not None:
data[
"rbac_email_implicit_role_assignments"
] = rbac_email_implicit_role_assignments
data["rbac_email_implicit_role_assignments"] = [
item.dict() for item in rbac_email_implicit_role_assignments
]
if mfa_methods is not None:
data["mfa_methods"] = mfa_methods
if allowed_mfa_methods is not None:
Expand Down
12 changes: 10 additions & 2 deletions stytch/b2b/api/organizations_members.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ def update(
If this field is provided and a session header is passed into the request, the Member Session must have permission to perform the `update.settings.default-mfa-method` action on the `stytch.member` Resource.
Alternatively, if the Member Session matches the Member associated with the `member_id` passed in the request, the authorization check will also allow a Member Session that has permission to perform the `update.settings.default-mfa-method` action on the `stytch.self` Resource.
- email_address: Updates the Member's `email_address`, if provided.
- email_address: Updates the Member's `email_address`, if provided.
If a Member's email address is changed, other Members in the same Organization cannot use the old email address, although the Member may update back to their old email address.
A Member's email address can only be useable again by other Members if the Member is deleted.
If this field is provided and a session header is passed into the request, the Member Session must have permission to perform the `update.info.email` action on the `stytch.member` Resource. Members cannot update their own email address.
""" # noqa
headers: Dict[str, str] = {}
if method_options is not None:
Expand Down Expand Up @@ -230,7 +234,11 @@ async def update_async(
If this field is provided and a session header is passed into the request, the Member Session must have permission to perform the `update.settings.default-mfa-method` action on the `stytch.member` Resource.
Alternatively, if the Member Session matches the Member associated with the `member_id` passed in the request, the authorization check will also allow a Member Session that has permission to perform the `update.settings.default-mfa-method` action on the `stytch.self` Resource.
- email_address: Updates the Member's `email_address`, if provided.
- email_address: Updates the Member's `email_address`, if provided.
If a Member's email address is changed, other Members in the same Organization cannot use the old email address, although the Member may update back to their old email address.
A Member's email address can only be useable again by other Members if the Member is deleted.
If this field is provided and a session header is passed into the request, the Member Session must have permission to perform the `update.info.email` action on the `stytch.member` Resource. Members cannot update their own email address.
""" # noqa
headers: Dict[str, str] = {}
if method_options is not None:
Expand Down
18 changes: 17 additions & 1 deletion stytch/b2b/api/organizations_members_oauth_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from __future__ import annotations

from typing import Any, Dict
from typing import Any, Dict, Optional

from stytch.b2b.models.organizations_members_oauth_providers import (
GoogleResponse,
Expand All @@ -28,6 +28,7 @@ def google(
self,
organization_id: str,
member_id: str,
include_refresh_token: Optional[bool] = None,
) -> GoogleResponse:
"""Retrieve the saved Google access token and ID token for a member. After a successful OAuth login, Stytch will save the
issued access token and ID token from the identity provider. If a refresh token has been issued, Stytch will refresh the
Expand All @@ -40,12 +41,15 @@ def google(
Fields:
- organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value.
- member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value.
- include_refresh_token: Whether to return the refresh token Stytch has stored for the OAuth Provider. Defaults to false. **Important:** If your application exchanges the refresh token, Stytch may not be able to automatically refresh access tokens in the future.
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
"organization_id": organization_id,
"member_id": member_id,
}
if include_refresh_token is not None:
data["include_refresh_token"] = include_refresh_token

url = self.api_base.url_for(
"/v1/b2b/organizations/{organization_id}/members/{member_id}/oauth_providers/google",
Expand All @@ -58,6 +62,7 @@ async def google_async(
self,
organization_id: str,
member_id: str,
include_refresh_token: Optional[bool] = None,
) -> GoogleResponse:
"""Retrieve the saved Google access token and ID token for a member. After a successful OAuth login, Stytch will save the
issued access token and ID token from the identity provider. If a refresh token has been issued, Stytch will refresh the
Expand All @@ -70,12 +75,15 @@ async def google_async(
Fields:
- organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value.
- member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value.
- include_refresh_token: Whether to return the refresh token Stytch has stored for the OAuth Provider. Defaults to false. **Important:** If your application exchanges the refresh token, Stytch may not be able to automatically refresh access tokens in the future.
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
"organization_id": organization_id,
"member_id": member_id,
}
if include_refresh_token is not None:
data["include_refresh_token"] = include_refresh_token

url = self.api_base.url_for(
"/v1/b2b/organizations/{organization_id}/members/{member_id}/oauth_providers/google",
Expand All @@ -88,6 +96,7 @@ def microsoft(
self,
organization_id: str,
member_id: str,
include_refresh_token: Optional[bool] = None,
) -> MicrosoftResponse:
"""Retrieve the saved Microsoft access token and ID token for a member. After a successful OAuth login, Stytch will save the
issued access token and ID token from the identity provider. If a refresh token has been issued, Stytch will refresh the
Expand All @@ -96,12 +105,15 @@ def microsoft(
Fields:
- organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value.
- member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value.
- include_refresh_token: Whether to return the refresh token Stytch has stored for the OAuth Provider. Defaults to false. **Important:** If your application exchanges the refresh token, Stytch may not be able to automatically refresh access tokens in the future.
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
"organization_id": organization_id,
"member_id": member_id,
}
if include_refresh_token is not None:
data["include_refresh_token"] = include_refresh_token

url = self.api_base.url_for(
"/v1/b2b/organizations/{organization_id}/members/{member_id}/oauth_providers/microsoft",
Expand All @@ -114,6 +126,7 @@ async def microsoft_async(
self,
organization_id: str,
member_id: str,
include_refresh_token: Optional[bool] = None,
) -> MicrosoftResponse:
"""Retrieve the saved Microsoft access token and ID token for a member. After a successful OAuth login, Stytch will save the
issued access token and ID token from the identity provider. If a refresh token has been issued, Stytch will refresh the
Expand All @@ -122,12 +135,15 @@ async def microsoft_async(
Fields:
- organization_id: Globally unique UUID that identifies a specific Organization. The `organization_id` is critical to perform operations on an Organization, so be sure to preserve this value.
- member_id: Globally unique UUID that identifies a specific Member. The `member_id` is critical to perform operations on a Member, so be sure to preserve this value.
- include_refresh_token: Whether to return the refresh token Stytch has stored for the OAuth Provider. Defaults to false. **Important:** If your application exchanges the refresh token, Stytch may not be able to automatically refresh access tokens in the future.
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
"organization_id": organization_id,
"member_id": member_id,
}
if include_refresh_token is not None:
data["include_refresh_token"] = include_refresh_token

url = self.api_base.url_for(
"/v1/b2b/organizations/{organization_id}/members/{member_id}/oauth_providers/microsoft",
Expand Down
Loading

0 comments on commit 53b10f8

Please sign in to comment.