1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15- """Firebase Phone Number Verification (FPNV) module."""
15+ """Firebase Phone Number Verification (FPNV) module.
16+
17+ This module contains functions for verifying JWTs related to the Firebase
18+ Phone Number Verification (FPNV) service.
19+ """
1620from typing import Any , Dict
1721
1822import jwt
@@ -55,25 +59,40 @@ def __init__(self, claims):
5559
5660 @property
5761 def phone_number (self ):
58- """Returns the phone number associated with the token."""
62+ """Returns the phone number of the user.
63+ This corresponds to the 'sub' claim in the JWT.
64+ """
5965 return self .get ('sub' )
6066
6167 @property
6268 def issuer (self ):
63- """Returns the issuer of the token ."""
69+ """Returns the issuer identifier for the issuer of the response ."""
6470 return self .get ('iss' )
6571
6672 @property
6773 def audience (self ):
68- """Returns the audience of the token."""
74+ """Returns the audience for which this token is intended ."""
6975 return self .get ('aud' )
7076
77+ @property
78+ def exp (self ):
79+ """Returns the expiration time since the Unix epoch."""
80+ return self .get ('exp' )
81+
82+ @property
83+ def iat (self ):
84+ """Returns the issued-at time since the Unix epoch."""
85+ return self .get ('iat' )
86+
7187 @property
7288 def sub (self ):
7389 """Returns the sub (subject) of the token, which is the phone number."""
7490 return self .get ('sub' )
7591
76- # TODO: ADD ALL
92+ @property
93+ def claims (self ):
94+ """Returns the entire map of claims."""
95+ return self
7796
7897
7998class FpnvClient :
@@ -122,9 +141,9 @@ def verify_token(self, token) -> FpnvToken:
122141 try :
123142 claims = self ._verifier .verify (token )
124143 return FpnvToken (claims )
125- except Exception as error :
144+ except ValueError as error :
126145 raise InvalidArgumentError (
127- 'Failed to verify token: {0}' .format (error )
146+ 'Failed to verify token: {0}' .format (error ), cause = error
128147 )
129148
130149
@@ -166,19 +185,15 @@ def _validate_headers(self, headers: Any) -> None:
166185
167186 def _validate_payload (self , token : str , signing_key : str ) -> Dict [str , Any ]:
168187 """Decodes and verifies the token."""
169- _issuer = None
188+ expected_issuer = f' { _FPNV_ISSUER } { self . _project_id } '
170189 payload = {}
171190 try :
172- unsafe_payload = jwt .decode (token , options = {"verify_signature" : False })
173- _issuer = unsafe_payload .get ('iss' )
174-
175- if _issuer is None :
176- raise ValueError ('The provided FPNV token has no issuer.' )
177191 payload = jwt .decode (
178192 token ,
179193 signing_key ,
180194 algorithms = [_ALGORITHM_ES256 ],
181- audience = _issuer
195+ audience = expected_issuer ,
196+ issuer = expected_issuer
182197 )
183198 except InvalidSignatureError as exception :
184199 raise ValueError (
@@ -187,12 +202,12 @@ def _validate_payload(self, token: str, signing_key: str) -> Dict[str, Any]:
187202 except InvalidAudienceError as exception :
188203 raise ValueError (
189204 'The provided FPNV token has an incorrect "aud" (audience) claim. '
190- f'Expected payload to include { _issuer } .'
205+ f'Expected payload to include { expected_issuer } .'
191206 ) from exception
192207 except InvalidIssuerError as exception :
193208 raise ValueError (
194209 'The provided FPNV token has an incorrect "iss" (issuer) claim. '
195- f'Expected claim to include { _issuer } '
210+ f'Expected claim to include { expected_issuer } '
196211 ) from exception
197212 except ExpiredSignatureError as exception :
198213 raise ValueError (
@@ -221,7 +236,5 @@ class _Validators:
221236 @classmethod
222237 def check_string (cls , label : str , value : Any ):
223238 """Checks if the given value is a string."""
224- if value is None :
225- raise ValueError (f'{ label } "{ value } " must be a non-empty string.' )
226- if not isinstance (value , str ):
227- raise ValueError (f'{ label } "{ value } " must be a string.' )
239+ if not isinstance (value , str ) or not value :
240+ raise ValueError (f'{ label } must be a non-empty string.' )
0 commit comments