Performs the authorization code grant with PKCE OAuth2.0 flow
| 3538 | |
| 3539 | |
| 3540 | class SSOTokenFetcherAuth(BaseSSOTokenFetcher): |
| 3541 | """Performs the authorization code grant with PKCE OAuth2.0 flow""" |
| 3542 | |
| 3543 | _AUTH_GRANT_TYPES = ('authorization_code', 'refresh_token') |
| 3544 | _AUTH_GRANT_DEFAULT_SCOPE = 'sso:account:access' |
| 3545 | _USER_AGENT_EXTRA = 'md/sso#auth' |
| 3546 | |
| 3547 | def __init__( |
| 3548 | self, |
| 3549 | sso_region, |
| 3550 | client_creator, |
| 3551 | parsed_globals, |
| 3552 | auth_code_fetcher, |
| 3553 | cache=None, |
| 3554 | on_pending_authorization=None, |
| 3555 | time_fetcher=None, |
| 3556 | ): |
| 3557 | super().__init__( |
| 3558 | sso_region, |
| 3559 | client_creator, |
| 3560 | parsed_globals, |
| 3561 | cache, |
| 3562 | on_pending_authorization, |
| 3563 | time_fetcher, |
| 3564 | ) |
| 3565 | |
| 3566 | self._auth_code_fetcher = auth_code_fetcher |
| 3567 | |
| 3568 | # Generate the PKCE pair |
| 3569 | self.code_verifier = ''.join( |
| 3570 | secrets.choice(string.ascii_letters + string.digits + '-._~') |
| 3571 | for _ in range(64) |
| 3572 | ) |
| 3573 | self.code_challenge = base64.urlsafe_b64encode( |
| 3574 | hashlib.sha256(self.code_verifier.encode()).digest() |
| 3575 | ).decode() |
| 3576 | |
| 3577 | def _register_client(self, session_name, scopes, redirect_uri, issuer_url): |
| 3578 | register_kwargs = { |
| 3579 | 'clientName': self._generate_client_name(session_name), |
| 3580 | 'clientType': self._CLIENT_REGISTRATION_TYPE, |
| 3581 | 'grantTypes': self._AUTH_GRANT_TYPES, |
| 3582 | 'redirectUris': [redirect_uri], |
| 3583 | 'issuerUrl': issuer_url, |
| 3584 | 'scopes': scopes or [self._AUTH_GRANT_DEFAULT_SCOPE], |
| 3585 | } |
| 3586 | |
| 3587 | response = self._client.register_client(**register_kwargs) |
| 3588 | |
| 3589 | expires_at = response['clientSecretExpiresAt'] |
| 3590 | expires_at = datetime.datetime.fromtimestamp(expires_at, tzutc()) |
| 3591 | registration = { |
| 3592 | 'clientId': response['clientId'], |
| 3593 | 'clientSecret': response['clientSecret'], |
| 3594 | 'expiresAt': expires_at, |
| 3595 | 'scopes': register_kwargs['scopes'], |
| 3596 | 'grantTypes': register_kwargs['grantTypes'], |
| 3597 | } |