Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/espn.py (Python)

Code before:
        if 'Authorization' not in headers:
            headers['Authorization'] = f'Bearer {self._API_KEY}'
        parse = urllib.parse.urlencode if path == 'token' else json.dumps
        return self._download_json(
            f'https://espn.api.edge.bamgrid.com/{path}', video_id, headers=headers, data=parse(payload).encode())

    def _real_extract(self, url):
        video_id = self._match_id(url)
        cdn_data = self._download_json(
            f'https://watch-cdn.product.api.espn.com/api/product/v3/watchespn/web/playback/event?id={video_id}',
            video_id)
        video_data = cdn_data['playbackState']

        # ESPN+ subscription required, through cookies
        if 'DTC' in video_data.get('sourceId'):
            cookie = self._get_cookies(url).get('ESPN-ONESITE.WEB-PROD.token')
            if not cookie:
                self.raise_login_required(method='cookies')

            jwt = re.search(r'=(.*)\|', cookie.value).group(1)
            import requests
            id_token = requests.post('https://registerdisney.go.com/jgc/v6/client/ESPN-ONESITE.WEB-PROD/guest/refresh-auth',
                                     json={
                                         'refreshToken': json.loads(base64.urlsafe_b64decode(f'{jwt}==='))['refresh_token'],
                                     },
                                     ).json()['data']['token']['id_token']

            assertion = self._call_bamgrid_api(
                'devices', video_id,
                headers={'Content-Type': 'application/json; charset=UTF-8'},
                payload={
                    'deviceFamily': 'android',
                    'applicationRuntime': 'android',
                    'deviceProfile': 'tv',
                    'attributes': {},
                })['assertion']
            token = self._call_bamgrid_api(
                'token', video_id, payload={
                    'subject_token': assertion,
                    'subject_token_type': 'urn:bamtech:params:oauth:token-type:device',
                    'platform': 'android',
                    'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
                })['access_token']

            assertion = self._call_bamgrid_api(
                'accounts/grant', video_id, payload={'id_token': id_token},
                headers={
                    'Authorization': token,
                    'Content-Type': 'application/json; charset=UTF-8',
                })['assertion']
            token = self._call_bamgrid_api(

Review comment (security):
Is the "jwt" in the cookie actually a JWT? or is it only the payload of a JWT (without a header or signature)?

If it's a full JWT, you could use `jwt_decode_hs256` from utils:

```suggestion
            id_token = self._download_json(
                'https://registerdisney.go.com/jgc/v6/client/ESPN-ONESITE.WEB-PROD/guest/refresh-auth',
                None, headers={'Content-Type': 'application/json'}, data=json.dumps({
                    'refreshToken': jwt_decode_hs256(jwt)['refresh_token'],
                }).encode())['data']['token']['id_token']
```

&nbsp;

otherwise I think this should work:

```suggestion
            id_token = self._download_json(
                'https://registerdisney.go.com/jgc/v6/client/ESPN-ONESITE.WEB-PROD/guest/refresh-auth',
                None, headers={'Content-Type': 'application/json'}, data=json.dumps({
                    'refreshToken': json.loads(base64.urlsafe_b64decode(f'{jwt}==='))['refresh_token'],
                }).encode())['data']['token']['id_token']
```


Code after:
        if 'Authorization' not in headers:
            headers['Authorization'] = f'Bearer {self._API_KEY}'
        parse = urllib.parse.urlencode if path == 'token' else json.dumps
        return self._download_json(
            f'https://espn.api.edge.bamgrid.com/{path}', video_id, headers=headers, data=parse(payload).encode())

    def _real_extract(self, url):
        video_id = self._match_id(url)
        cdn_data = self._download_json(
            f'https://watch-cdn.product.api.espn.com/api/product/v3/watchespn/web/playback/event?id={video_id}',
            video_id)
        video_data = cdn_data['playbackState']

        # ESPN+ subscription required, through cookies
        if 'DTC' in video_data.get('sourceId'):
            cookie = self._get_cookies(url).get('ESPN-ONESITE.WEB-PROD.token')
            if not cookie:
                self.raise_login_required(method='cookies')

            jwt = self._search_regex(r'=([^|]+)\|', cookie.value, 'cookie jwt')
            id_token = self._download_json(
                'https://registerdisney.go.com/jgc/v6/client/ESPN-ONESITE.WEB-PROD/guest/refresh-auth',
                None, 'Refreshing token', headers={'Content-Type': 'application/json'}, data=json.dumps({
                    'refreshToken': json.loads(base64.urlsafe_b64decode(f'{jwt}==='))['refresh_token'],
                }).encode())['data']['token']['id_token']

            assertion = self._call_bamgrid_api(
                'devices', video_id,
                headers={'Content-Type': 'application/json; charset=UTF-8'},
                payload={
                    'deviceFamily': 'android',
                    'applicationRuntime': 'android',
                    'deviceProfile': 'tv',
                    'attributes': {},
                })['assertion']
            token = self._call_bamgrid_api(
                'token', video_id, payload={
                    'subject_token': assertion,
                    'subject_token_type': 'urn:bamtech:params:oauth:token-type:device',
                    'platform': 'android',
                    'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
                })['access_token']

            assertion = self._call_bamgrid_api(
                'accounts/grant', video_id, payload={'id_token': id_token},
                headers={
                    'Authorization': token,
                    'Content-Type': 'application/json; charset=UTF-8',
                })['assertion']
            token = self._call_bamgrid_api(
                'token', video_id, payload={