| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -424,6 +424,40 @@ def test_get_profile_and_token_returns_expected_workosprofile_object( | |||
| 424 | 424 | assert profile_and_token.access_token == "01DY34ACQTM3B1CSX1YSZ8Z00D" | |
| 425 | 425 | assert profile_and_token.profile.to_dict() == mock_profile | |
| 426 | 426 | ||
| 427 | + def test_get_profile_and_token_from_id_token_returns_expected_workosprofile_object( | ||
| 428 | + self, setup_with_client_id, mock_profile, mock_request_method | ||
| 429 | + ): | ||
| 430 | + response_dict = { | ||
| 431 | + "profile": { | ||
| 432 | + "object": "profile", | ||
| 433 | + "id": mock_profile["id"], | ||
| 434 | + "email": mock_profile["email"], | ||
| 435 | + "first_name": mock_profile["first_name"], | ||
| 436 | + "groups": mock_profile["groups"], | ||
| 437 | + "organization_id": mock_profile["organization_id"], | ||
| 438 | + "connection_id": mock_profile["connection_id"], | ||
| 439 | + "connection_type": mock_profile["connection_type"], | ||
| 440 | + "last_name": mock_profile["last_name"], | ||
| 441 | + "idp_id": mock_profile["idp_id"], | ||
| 442 | + "raw_attributes": { | ||
| 443 | + "email": mock_profile["raw_attributes"]["email"], | ||
| 444 | + "first_name": mock_profile["raw_attributes"]["first_name"], | ||
| 445 | + "last_name": mock_profile["raw_attributes"]["last_name"], | ||
| 446 | + "groups": mock_profile["raw_attributes"]["groups"], | ||
| 447 | + }, | ||
| 448 | + }, | ||
| 449 | + "access_token": "01DY34ACQTM3B1CSX1YSZ8Z00D", | ||
| 450 | + } | ||
| 451 | + | ||
| 452 | + mock_request_method("post", response_dict, 200) | ||
| 453 | + | ||
| 454 | + profile_and_token = self.sso.get_profile_and_token_from_id_token( | ||
| 455 | + "eyJhbGciOiJSUzI1NiJ9.id.token", "org_01EHQMYV6MBK39QC5PZXHY59C3" | ||
| 456 | + ) | ||
| 457 | + | ||
| 458 | + assert profile_and_token.access_token == "01DY34ACQTM3B1CSX1YSZ8Z00D" | ||
| 459 | + assert profile_and_token.profile.to_dict() == mock_profile | ||
| 460 | + | ||
| 427 | 461 | def test_get_profile_and_token_without_first_name_or_last_name_returns_expected_workosprofile_object( | |
| 428 | 462 | self, setup_with_client_id, mock_magic_link_profile, mock_request_method | |
| 429 | 463 | ): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | 13 | __package_url__ = "https://github.com/workos-inc/workos-python" | |
| 14 | 14 | ||
| 15 | - __version__ = "4.15.0" | ||
| 15 | + __version__ = "4.16.0" | ||
| 16 | 16 | ||
| 17 | 17 | __author__ = "WorkOS" | |
| 18 | 18 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,6 +24,8 @@ | |||
| 24 | 24 | PROFILE_PATH = "sso/profile" | |
| 25 | 25 | ||
| 26 | 26 | OAUTH_GRANT_TYPE = "authorization_code" | |
| 27 | + TOKEN_EXCHANGE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:token-exchange" | ||
| 28 | + ID_TOKEN_SUBJECT_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:id_token" | ||
| 27 | 29 | ||
| 28 | 30 | RESPONSE_LIMIT = 10 | |
| 29 | 31 | ||
@@ -162,6 +164,39 @@ def get_profile_and_token(self, code): | |||
| 162 | 164 | ||
| 163 | 165 | return WorkOSProfileAndToken.construct_from_response(response) | |
| 164 | 166 | ||
| 167 | + def get_profile_and_token_from_id_token(self, id_token, organization_id): | ||
| 168 | + """Exchange an externally issued OIDC ID token for a Profile and Token | ||
| 169 | + | ||
| 170 | + For flows where the user authenticates natively with the identity | ||
| 171 | + provider (for example a mobile app using MSAL against Microsoft Entra) | ||
| 172 | + and no browser redirect occurs. The ID token is exchanged for the same | ||
| 173 | + WorkOS profile the authorization code flow would return. The connection | ||
| 174 | + must have an ID token trust configured for the token's issuer and | ||
| 175 | + audience. | ||
| 176 | + | ||
| 177 | + Args: | ||
| 178 | + id_token (str): The OIDC ID token issued to the client. | ||
| 179 | + organization_id (str): The organization whose connection the ID | ||
| 180 | + token should be validated against. | ||
| 181 | + | ||
| 182 | + Returns: | ||
| 183 | + WorkOSProfileAndToken: WorkOSProfileAndToken object representing the User | ||
| 184 | + """ | ||
| 185 | + params = { | ||
| 186 | + "client_id": workos.client_id, | ||
| 187 | + "client_secret": workos.api_key, | ||
| 188 | + "grant_type": TOKEN_EXCHANGE_GRANT_TYPE, | ||
| 189 | + "subject_token": id_token, | ||
| 190 | + "subject_token_type": ID_TOKEN_SUBJECT_TOKEN_TYPE, | ||
| 191 | + "organization_id": organization_id, | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + response = self.request_helper.request( | ||
| 195 | + TOKEN_PATH, method=REQUEST_METHOD_POST, params=params | ||
| 196 | + ) | ||
| 197 | + | ||
| 198 | + return WorkOSProfileAndToken.construct_from_response(response) | ||
| 199 | + | ||
| 165 | 200 | def get_connection(self, connection): | |
| 166 | 201 | """Gets details for a single Connection | |
| 167 | 202 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments