Skip to content

Commit

Permalink
Add DFP endpoints (#228)
Browse files Browse the repository at this point in the history
  • Loading branch information
jennifer-stytch authored Jan 6, 2025
1 parent be97337 commit 68dc147
Show file tree
Hide file tree
Showing 18 changed files with 495 additions and 18 deletions.
4 changes: 2 additions & 2 deletions stytch/b2b/api/rbac.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def policy(
When using the backend SDKs, the RBAC Policy will be cached to allow for local evaluations, eliminating the need for an extra request to Stytch. The policy will be refreshed if an authorization check is requested and the RBAC policy was last updated more than 5 minutes ago.
Resources and Roles can be created and managed within the [Dashboard](/dashboard/rbac). Additionally, [Role assignment](https://stytch.com/docs/b2b/guides/rbac/role-assignment) can be programmatically managed through certain Stytch API endpoints.
Resources and Roles can be created and managed within the [Dashboard](https://stytch.com/docs/dashboard/rbac). Additionally, [Role assignment](https://stytch.com/docs/b2b/guides/rbac/role-assignment) can be programmatically managed through certain Stytch API endpoints.
Check out the [RBAC overview](https://stytch.com/docs/b2b/guides/rbac/overview) to learn more about Stytch's RBAC permissioning model.
Expand All @@ -48,7 +48,7 @@ async def policy_async(
When using the backend SDKs, the RBAC Policy will be cached to allow for local evaluations, eliminating the need for an extra request to Stytch. The policy will be refreshed if an authorization check is requested and the RBAC policy was last updated more than 5 minutes ago.
Resources and Roles can be created and managed within the [Dashboard](/dashboard/rbac). Additionally, [Role assignment](https://stytch.com/docs/b2b/guides/rbac/role-assignment) can be programmatically managed through certain Stytch API endpoints.
Resources and Roles can be created and managed within the [Dashboard](https://stytch.com/docs/dashboard/rbac). Additionally, [Role assignment](https://stytch.com/docs/b2b/guides/rbac/role-assignment) can be programmatically managed through certain Stytch API endpoints.
Check out the [RBAC overview](https://stytch.com/docs/b2b/guides/rbac/overview) to learn more about Stytch's RBAC permissioning model.
Expand Down
4 changes: 2 additions & 2 deletions stytch/b2b/api/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ def migrate(
session_duration_minutes: Optional[int] = None,
session_custom_claims: Optional[Dict[str, Any]] = None,
) -> MigrateResponse:
"""Migrate a session from an external OIDC compliant endpoint. Stytch will call the external UserInfo endpoint defined in your Stytch Project settings in the [Dashboard](/dashboard), and then perform a lookup using the `session_token`. If the response contains a valid email address, Stytch will attempt to match that email address with an existing in your and create a Stytch Session. You will need to create the member before using this endpoint.
"""Migrate a session from an external OIDC compliant endpoint. Stytch will call the external UserInfo endpoint defined in your Stytch Project settings in the [Dashboard](https://stytch.com/docs/dashboard), and then perform a lookup using the `session_token`. If the response contains a valid email address, Stytch will attempt to match that email address with an existing in your and create a Stytch Session. You will need to create the member before using this endpoint.
Fields:
- session_token: The authorization token Stytch will pass in to the external userinfo endpoint.
Expand Down Expand Up @@ -482,7 +482,7 @@ async def migrate_async(
session_duration_minutes: Optional[int] = None,
session_custom_claims: Optional[Dict[str, Any]] = None,
) -> MigrateResponse:
"""Migrate a session from an external OIDC compliant endpoint. Stytch will call the external UserInfo endpoint defined in your Stytch Project settings in the [Dashboard](/dashboard), and then perform a lookup using the `session_token`. If the response contains a valid email address, Stytch will attempt to match that email address with an existing in your and create a Stytch Session. You will need to create the member before using this endpoint.
"""Migrate a session from an external OIDC compliant endpoint. Stytch will call the external UserInfo endpoint defined in your Stytch Project settings in the [Dashboard](https://stytch.com/docs/dashboard), and then perform a lookup using the `session_token`. If the response contains a valid email address, Stytch will attempt to match that email address with an existing in your and create a Stytch Session. You will need to create the member before using this endpoint.
Fields:
- session_token: The authorization token Stytch will pass in to the external userinfo endpoint.
Expand Down
8 changes: 8 additions & 0 deletions stytch/b2b/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from stytch.b2b.api.sessions import Sessions
from stytch.b2b.api.sso import SSO
from stytch.b2b.api.totps import TOTPs
from stytch.consumer.api.fraud import Fraud
from stytch.consumer.api.m2m import M2M
from stytch.consumer.api.project import Project
from stytch.core.client_base import ClientBase
Expand All @@ -42,13 +43,15 @@ def __init__(
environment: Optional[str] = None,
suppress_warnings: bool = False,
async_session: Optional[aiohttp.ClientSession] = None,
fraud_environment: Optional[str] = None,
):
super().__init__(
project_id=project_id,
secret=secret,
environment=environment,
suppress_warnings=suppress_warnings,
async_session=async_session,
fraud_environment=fraud_environment,
)

policy_cache = PolicyCache(
Expand All @@ -64,6 +67,11 @@ def __init__(
sync_client=self.sync_client,
async_client=self.async_client,
)
self.fraud = Fraud(
api_base=self.fraud_api_base,
sync_client=self.sync_client,
async_client=self.async_client,
)
self.m2m = M2M(
api_base=self.api_base,
sync_client=self.sync_client,
Expand Down
2 changes: 1 addition & 1 deletion stytch/b2b/models/rbac.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class Policy(pydantic.BaseModel):
class PolicyResponse(ResponseBase):
"""Response type for `RBAC.policy`.
Fields:
- policy: The RBAC Policy document that contains all defined Roles and Resources – which are managed in the [Dashboard](/dashboard/rbac). Read more about these entities and how they work in our [RBAC overview](https://stytch.com/docs/b2b/guides/rbac/overview).
- policy: The RBAC Policy document that contains all defined Roles and Resources – which are managed in the [Dashboard](https://stytch.com/docs/dashboard/rbac). Read more about these entities and how they work in our [RBAC overview](https://stytch.com/docs/b2b/guides/rbac/overview).
""" # noqa

policy: Optional[Policy] = None
31 changes: 31 additions & 0 deletions stytch/consumer/api/fraud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# !!!
# WARNING: This file is autogenerated
# Only modify code within MANUAL() sections
# or your changes may be overwritten later!
# !!!

from __future__ import annotations

from stytch.consumer.api.fraud_fingerprint import Fingerprint
from stytch.consumer.api.fraud_rules import Rules
from stytch.core.api_base import ApiBase
from stytch.core.http.client import AsyncClient, SyncClient


class Fraud:
def __init__(
self, api_base: ApiBase, sync_client: SyncClient, async_client: AsyncClient
) -> None:
self.api_base = api_base
self.sync_client = sync_client
self.async_client = async_client
self.fingerprint = Fingerprint(
api_base=self.api_base,
sync_client=self.sync_client,
async_client=self.async_client,
)
self.rules = Rules(
api_base=self.api_base,
sync_client=self.sync_client,
async_client=self.async_client,
)
89 changes: 89 additions & 0 deletions stytch/consumer/api/fraud_fingerprint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# !!!
# WARNING: This file is autogenerated
# Only modify code within MANUAL() sections
# or your changes may be overwritten later!
# !!!

from __future__ import annotations

from typing import Any, Dict, Optional, Union

from stytch.consumer.models.fraud import Metadata
from stytch.consumer.models.fraud_fingerprint import LookupResponse
from stytch.core.api_base import ApiBase
from stytch.core.http.client import AsyncClient, SyncClient


class Fingerprint:
def __init__(
self, api_base: ApiBase, sync_client: SyncClient, async_client: AsyncClient
) -> None:
self.api_base = api_base
self.sync_client = sync_client
self.async_client = async_client

def lookup(
self,
telemetry_id: str,
external_metadata: Optional[Union[Metadata, Dict[str, Any]]] = None,
) -> LookupResponse:
"""Lookup the associated fingerprint for the `telemetry_id` returned from the `GetTelemetryID` function. Learn more about the different fingerprint types and verdicts in our [DFP guide](https://stytch.com/docs/fraud/guides/device-fingerprinting/overview).
Make a decision based on the returned `verdict`:
* `ALLOW` - This is a known valid device grouping or device profile that is part of the default `ALLOW` listed set of known devices by Stytch. This grouping is made up of verified device profiles that match the characteristics of known/authentic traffic origins.
* `BLOCK` - This is a known bad or malicious device profile that is undesirable and should be blocked from completing the privileged action in question.
* `CHALLENGE` - This is an unknown or potentially malicious device that should be put through increased friction such as 2FA or other forms of extended user verification before allowing the privileged action to proceed.
If the `telemetry_id` is not found, we will return a 404 `telemetry_id_not_found` [error](https://stytch.com/docs/fraud/api/errors/404#telemetry_id_not_found). We recommend treating 404 errors as a `BLOCK`, since it could be a sign of an attacker trying to bypass DFP protections by generating fake telemetry IDs.
Fields:
- telemetry_id: The telemetry ID associated with the fingerprint getting looked up.
- external_metadata: External identifiers that you wish to associate with the given telemetry ID. You will be able to search for fingerprint results by these identifiers in the DFP analytics dashboard. External metadata fields may not exceed 65 characters. They may only contain alphanumerics and the characters `_` `-` `+` `.` or `@`.
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
"telemetry_id": telemetry_id,
}
if external_metadata is not None:
data["external_metadata"] = (
external_metadata
if isinstance(external_metadata, dict)
else external_metadata.dict()
)

url = self.api_base.url_for("/v1/fingerprint/lookup", data)
res = self.sync_client.post(url, data, headers)
return LookupResponse.from_json(res.response.status_code, res.json)

async def lookup_async(
self,
telemetry_id: str,
external_metadata: Optional[Metadata] = None,
) -> LookupResponse:
"""Lookup the associated fingerprint for the `telemetry_id` returned from the `GetTelemetryID` function. Learn more about the different fingerprint types and verdicts in our [DFP guide](https://stytch.com/docs/fraud/guides/device-fingerprinting/overview).
Make a decision based on the returned `verdict`:
* `ALLOW` - This is a known valid device grouping or device profile that is part of the default `ALLOW` listed set of known devices by Stytch. This grouping is made up of verified device profiles that match the characteristics of known/authentic traffic origins.
* `BLOCK` - This is a known bad or malicious device profile that is undesirable and should be blocked from completing the privileged action in question.
* `CHALLENGE` - This is an unknown or potentially malicious device that should be put through increased friction such as 2FA or other forms of extended user verification before allowing the privileged action to proceed.
If the `telemetry_id` is not found, we will return a 404 `telemetry_id_not_found` [error](https://stytch.com/docs/fraud/api/errors/404#telemetry_id_not_found). We recommend treating 404 errors as a `BLOCK`, since it could be a sign of an attacker trying to bypass DFP protections by generating fake telemetry IDs.
Fields:
- telemetry_id: The telemetry ID associated with the fingerprint getting looked up.
- external_metadata: External identifiers that you wish to associate with the given telemetry ID. You will be able to search for fingerprint results by these identifiers in the DFP analytics dashboard. External metadata fields may not exceed 65 characters. They may only contain alphanumerics and the characters `_` `-` `+` `.` or `@`.
""" # noqa
headers: Dict[str, str] = {}
data: Dict[str, Any] = {
"telemetry_id": telemetry_id,
}
if external_metadata is not None:
data["external_metadata"] = (
external_metadata
if isinstance(external_metadata, dict)
else external_metadata.dict()
)

url = self.api_base.url_for("/v1/fingerprint/lookup", data)
res = await self.async_client.post(url, data, headers)
return LookupResponse.from_json(res.response.status, res.json)
Loading

0 comments on commit 68dc147

Please sign in to comment.