xref: /aosp_15_r20/external/tink/python/tink/jwt/_json_util.py (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1# Copyright 2021 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Defines an Invalid JWT Error."""
15
16import json
17from typing import Any
18
19from tink.jwt import _jwt_error
20
21
22def json_dumps(json_data: Any) -> str:
23  return json.dumps(json_data, separators=(',', ':'))
24
25
26def _validate_str(value: str) -> None:
27  """Uses encode('utf8') to check if value is a valid string."""
28  _ = value.encode('utf8')
29
30
31def _validate_value(value: Any) -> None:
32  """Validates strings in a JSON object value."""
33  # We don't need to check strings inside dicts, because json.loads will call
34  # _dict_with_validation for these.
35  if isinstance(value, str):
36    _validate_str(value)
37  if isinstance(value, list):
38    for item in value:
39      if isinstance(item, str):
40        _validate_str(item)
41
42
43def _dict_with_validation(pairs):
44  """Validates pairs and returns a dict."""
45  keys = set()
46  for key, value in pairs:
47    _validate_str(key)
48    if key in keys:
49      raise _jwt_error.JwtInvalidError(
50          'Failed to parse JSON string, duplicated key')
51    keys.add(key)
52    _validate_value(value)
53  return dict(pairs)
54
55
56def json_loads(json_text: str) -> Any:
57  """Does the same as json.loads, but with some additional validation."""
58  try:
59    return json.loads(json_text, object_pairs_hook=_dict_with_validation)
60  except json.decoder.JSONDecodeError:
61    raise _jwt_error.JwtInvalidError('Failed to parse JSON string')
62  except RecursionError:
63    raise _jwt_error.JwtInvalidError(
64        'Failed to parse JSON string, too many recursions')
65  except UnicodeEncodeError:
66    raise _jwt_error.JwtInvalidError('invalid character')
67