Skip to content

Commit

Permalink
OIDC improvements (#220)
Browse files Browse the repository at this point in the history
* OIDC improvements

* bump version
  • Loading branch information
vincent-stytch authored Oct 9, 2024
1 parent 1db6365 commit f9487c9
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 4 deletions.
43 changes: 43 additions & 0 deletions stytch/b2b/api/organizations_members.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
DeleteTOTPRequestOptions,
DeleteTOTPResponse,
GetResponse,
OIDCProvidersResponse,
ReactivateRequestOptions,
ReactivateResponse,
SearchRequestOptions,
Expand Down Expand Up @@ -640,6 +641,48 @@ async def dangerously_get_async(
res = await self.async_client.get(url, data, headers)
return GetResponse.from_json(res.response.status, res.json)

def oidc_providers(
self,
organization_id: str,
member_id: str,
include_refresh_token: Optional[bool] = None,
) -> OIDCProvidersResponse:
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}/oidc_providers",
data,
)
res = self.sync_client.get(url, data, headers)
return OIDCProvidersResponse.from_json(res.response.status_code, res.json)

async def oidc_providers_async(
self,
organization_id: str,
member_id: str,
include_refresh_token: Optional[bool] = None,
) -> OIDCProvidersResponse:
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}/oidc_providers",
data,
)
res = await self.async_client.get(url, data, headers)
return OIDCProvidersResponse.from_json(res.response.status, res.json)

def unlink_retired_email(
self,
organization_id: str,
Expand Down
16 changes: 16 additions & 0 deletions stytch/b2b/api/sso_oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ def update_connection(
identity_provider: Optional[
Union[UpdateConnectionRequestIdentityProvider, str]
] = None,
custom_scopes: Optional[str] = None,
attribute_mapping: Optional[Dict[str, Any]] = None,
method_options: Optional[UpdateConnectionRequestOptions] = None,
) -> UpdateConnectionResponse:
"""Updates an existing OIDC connection.
Expand Down Expand Up @@ -136,6 +138,8 @@ def update_connection(
- userinfo_url: The location of the IDP's [UserInfo Endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo). This will be provided by the IdP.
- jwks_url: The location of the IdP's JSON Web Key Set, used to verify credentials issued by the IdP. This will be provided by the IdP.
- identity_provider: The identity provider of this connection. For OIDC, the accepted values are `generic`, `okta`, and `microsoft-entra`. For SAML, the accepted values are `generic`, `okta`, `microsoft-entra`, and `google-workspace`.
- custom_scopes: Include a space-separated list of custom scopes that you'd like to include. Note that this list must be URL encoded, e.g. the spaces must be expressed as %20.
- attribute_mapping: An object that represents the attributes used to identify a Member. This object will map the IdP-defined User attributes to Stytch-specific values, which will appear on the member's Trusted Metadata.
""" # noqa
headers: Dict[str, str] = {}
if method_options is not None:
Expand All @@ -162,6 +166,10 @@ def update_connection(
data["jwks_url"] = jwks_url
if identity_provider is not None:
data["identity_provider"] = identity_provider
if custom_scopes is not None:
data["custom_scopes"] = custom_scopes
if attribute_mapping is not None:
data["attribute_mapping"] = attribute_mapping

url = self.api_base.url_for(
"/v1/b2b/sso/oidc/{organization_id}/connections/{connection_id}", data
Expand All @@ -182,6 +190,8 @@ async def update_connection_async(
userinfo_url: Optional[str] = None,
jwks_url: Optional[str] = None,
identity_provider: Optional[UpdateConnectionRequestIdentityProvider] = None,
custom_scopes: Optional[str] = None,
attribute_mapping: Optional[Dict[str, Any]] = None,
method_options: Optional[UpdateConnectionRequestOptions] = None,
) -> UpdateConnectionResponse:
"""Updates an existing OIDC connection.
Expand Down Expand Up @@ -215,6 +225,8 @@ async def update_connection_async(
- userinfo_url: The location of the IDP's [UserInfo Endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo). This will be provided by the IdP.
- jwks_url: The location of the IdP's JSON Web Key Set, used to verify credentials issued by the IdP. This will be provided by the IdP.
- identity_provider: The identity provider of this connection. For OIDC, the accepted values are `generic`, `okta`, and `microsoft-entra`. For SAML, the accepted values are `generic`, `okta`, `microsoft-entra`, and `google-workspace`.
- custom_scopes: Include a space-separated list of custom scopes that you'd like to include. Note that this list must be URL encoded, e.g. the spaces must be expressed as %20.
- attribute_mapping: An object that represents the attributes used to identify a Member. This object will map the IdP-defined User attributes to Stytch-specific values, which will appear on the member's Trusted Metadata.
""" # noqa
headers: Dict[str, str] = {}
if method_options is not None:
Expand All @@ -241,6 +253,10 @@ async def update_connection_async(
data["jwks_url"] = jwks_url
if identity_provider is not None:
data["identity_provider"] = identity_provider
if custom_scopes is not None:
data["custom_scopes"] = custom_scopes
if attribute_mapping is not None:
data["attribute_mapping"] = attribute_mapping

url = self.api_base.url_for(
"/v1/b2b/sso/oidc/{organization_id}/connections/{connection_id}", data
Expand Down
4 changes: 2 additions & 2 deletions stytch/b2b/api/sso_saml.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def update_connection(
[RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role assignment.
Before adding any group implicit role assignments, you must add a "groups" key to your SAML connection's
`attribute_mapping`. Make sure that your IdP is configured to correctly send the group information.
- alternative_audience_uri: An alternative URL to use for the Audience Restriction. This value can be used when you wish to migrate an existing SAML integration to Stytch with zero downtime.
- alternative_audience_uri: An alternative URL to use for the Audience Restriction. This value can be used when you wish to migrate an existing SAML integration to Stytch with zero downtime. Read our [SSO migration guide](https://stytch.com/docs/b2b/guides/migrations/additional-migration-considerations) for more info.
- identity_provider: The identity provider of this connection. For OIDC, the accepted values are `generic`, `okta`, and `microsoft-entra`. For SAML, the accepted values are `generic`, `okta`, `microsoft-entra`, and `google-workspace`.
""" # noqa
headers: Dict[str, str] = {}
Expand Down Expand Up @@ -223,7 +223,7 @@ async def update_connection_async(
[RBAC guide](https://stytch.com/docs/b2b/guides/rbac/role-assignment) for more information about role assignment.
Before adding any group implicit role assignments, you must add a "groups" key to your SAML connection's
`attribute_mapping`. Make sure that your IdP is configured to correctly send the group information.
- alternative_audience_uri: An alternative URL to use for the Audience Restriction. This value can be used when you wish to migrate an existing SAML integration to Stytch with zero downtime.
- alternative_audience_uri: An alternative URL to use for the Audience Restriction. This value can be used when you wish to migrate an existing SAML integration to Stytch with zero downtime. Read our [SSO migration guide](https://stytch.com/docs/b2b/guides/migrations/additional-migration-considerations) for more info.
- identity_provider: The identity provider of this connection. For OIDC, the accepted values are `generic`, `okta`, and `microsoft-entra`. For SAML, the accepted values are `generic`, `okta`, `microsoft-entra`, and `google-workspace`.
""" # noqa
headers: Dict[str, str] = {}
Expand Down
10 changes: 10 additions & 0 deletions stytch/b2b/models/organizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ class OAuthRegistration(pydantic.BaseModel):
locale: Optional[str] = None


class OIDCProviderInfo(pydantic.BaseModel):
provider_subject: str
id_token: str
access_token: str
access_token_expires_in: int
scopes: List[str]
connection_id: str
refresh_token: Optional[str] = None


class Organization(pydantic.BaseModel):
"""
Fields:
Expand Down
11 changes: 10 additions & 1 deletion stytch/b2b/models/organizations_members.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@

import pydantic

from stytch.b2b.models.organizations import Member, Organization, ResultsMetadata
from stytch.b2b.models.organizations import (
Member,
OIDCProviderInfo,
Organization,
ResultsMetadata,
)
from stytch.core.response_base import ResponseBase
from stytch.shared.method_options import Authorization

Expand Down Expand Up @@ -233,6 +238,10 @@ class GetResponse(ResponseBase):
organization: Organization


class OIDCProvidersResponse(ResponseBase):
registrations: List[OIDCProviderInfo]


class ReactivateResponse(ResponseBase):
"""Response type for `Members.reactivate`.
Fields:
Expand Down
2 changes: 2 additions & 0 deletions stytch/b2b/models/sso.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class OIDCConnection(pydantic.BaseModel):
userinfo_url: str
jwks_url: str
identity_provider: str
custom_scopes: str
attribute_mapping: Optional[Dict[str, Any]] = None


class SAMLConnectionImplicitRoleAssignment(pydantic.BaseModel):
Expand Down
7 changes: 7 additions & 0 deletions stytch/consumer/models/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class AuthenticationFactorDeliveryMethod(str, enum.Enum):
IMPORTED_AUTH0 = "imported_auth0"
OAUTH_EXCHANGE_SLACK = "oauth_exchange_slack"
OAUTH_EXCHANGE_HUBSPOT = "oauth_exchange_hubspot"
OAUTH_EXCHANGE_GITHUB = "oauth_exchange_github"


class AuthenticationFactorType(str, enum.Enum):
Expand Down Expand Up @@ -155,6 +156,10 @@ class GitLabOAuthFactor(pydantic.BaseModel):
email_id: Optional[str] = None


class GithubOAuthExchangeFactor(pydantic.BaseModel):
email_id: str


class GithubOAuthFactor(pydantic.BaseModel):
id: str
provider_subject: str
Expand Down Expand Up @@ -388,6 +393,7 @@ class AuthenticationFactor(pydantic.BaseModel):
- hubspot_oauth_factor: (no documentation yet)
- slack_oauth_exchange_factor: (no documentation yet)
- hubspot_oauth_exchange_factor: (no documentation yet)
- github_oauth_exchange_factor: (no documentation yet)
""" # noqa

type: AuthenticationFactorType
Expand Down Expand Up @@ -431,6 +437,7 @@ class AuthenticationFactor(pydantic.BaseModel):
hubspot_oauth_factor: Optional[HubspotOAuthFactor] = None
slack_oauth_exchange_factor: Optional[SlackOAuthExchangeFactor] = None
hubspot_oauth_exchange_factor: Optional[HubspotOAuthExchangeFactor] = None
github_oauth_exchange_factor: Optional[GithubOAuthExchangeFactor] = None


class Session(pydantic.BaseModel):
Expand Down
2 changes: 1 addition & 1 deletion stytch/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "11.5.0"
__version__ = "11.6.0"

0 comments on commit f9487c9

Please sign in to comment.