@@ -26,13 +26,15 @@ def _get_default_options():
2626 'verify_nbf' : True ,
2727 'verify_iat' : True ,
2828 'verify_aud' : True ,
29+ 'verify_iss' : True
2930 }
3031
31- def encode (self , payload , key , algorithm = 'HS256' , headers = None , json_encoder = None ):
32+ def encode (self , payload , key , algorithm = 'HS256' , headers = None ,
33+ json_encoder = None ):
3234 # Check that we get a mapping
3335 if not isinstance (payload , Mapping ):
34- raise TypeError ('Expecting a mapping object, as json web token only '
35- 'support json objects.' )
36+ raise TypeError ('Expecting a mapping object, as JWT only supports '
37+ 'JSON objects as payloads .' )
3638
3739 # Payload
3840 for time_claim in ['exp' , 'iat' , 'nbf' ]:
@@ -81,52 +83,78 @@ def _validate_claims(self, payload, audience=None, issuer=None, leeway=0,
8183 now = timegm (datetime .utcnow ().utctimetuple ())
8284
8385 if 'iat' in payload and options .get ('verify_iat' ):
84- try :
85- iat = int (payload ['iat' ])
86- except ValueError :
87- raise DecodeError ('Issued At claim (iat) must be an integer.' )
88-
89- if iat > (now + leeway ):
90- raise InvalidIssuedAtError ('Issued At claim (iat) cannot be in'
91- ' the future.' )
86+ self ._validate_iat (payload , now , leeway )
9287
9388 if 'nbf' in payload and options .get ('verify_nbf' ):
94- try :
95- nbf = int (payload ['nbf' ])
96- except ValueError :
97- raise DecodeError ('Not Before claim (nbf) must be an integer.' )
98-
99- if nbf > (now + leeway ):
100- raise ImmatureSignatureError ('The token is not yet valid (nbf)' )
89+ self ._validate_nbf (payload , now , leeway )
10190
10291 if 'exp' in payload and options .get ('verify_exp' ):
103- try :
104- exp = int (payload ['exp' ])
105- except ValueError :
106- raise DecodeError ('Expiration Time claim (exp) must be an'
107- ' integer.' )
108-
109- if exp < (now - leeway ):
110- raise ExpiredSignatureError ('Signature has expired' )
111-
112- if 'aud' in payload and options .get ('verify_aud' ):
113- audience_claims = payload ['aud' ]
114- if isinstance (audience_claims , string_types ):
115- audience_claims = [audience_claims ]
116- if not isinstance (audience_claims , list ):
117- raise InvalidAudienceError ('Invalid claim format in token' )
118- if any (not isinstance (c , string_types ) for c in audience_claims ):
119- raise InvalidAudienceError ('Invalid claim format in token' )
120- if audience not in audience_claims :
121- raise InvalidAudienceError ('Invalid audience' )
122- elif audience is not None :
92+ self ._validate_exp (payload , now , leeway )
93+
94+ if options .get ('verify_iss' ):
95+ self ._validate_iss (payload , issuer )
96+
97+ if options .get ('verify_aud' ):
98+ self ._validate_aud (payload , audience )
99+
100+ def _validate_iat (self , payload , now , leeway ):
101+ try :
102+ iat = int (payload ['iat' ])
103+ except ValueError :
104+ raise DecodeError ('Issued At claim (iat) must be an integer.' )
105+
106+ if iat > (now + leeway ):
107+ raise InvalidIssuedAtError ('Issued At claim (iat) cannot be in'
108+ ' the future.' )
109+
110+ def _validate_nbf (self , payload , now , leeway ):
111+ try :
112+ nbf = int (payload ['nbf' ])
113+ except ValueError :
114+ raise DecodeError ('Not Before claim (nbf) must be an integer.' )
115+
116+ if nbf > (now + leeway ):
117+ raise ImmatureSignatureError ('The token is not yet valid (nbf)' )
118+
119+ def _validate_exp (self , payload , now , leeway ):
120+ try :
121+ exp = int (payload ['exp' ])
122+ except ValueError :
123+ raise DecodeError ('Expiration Time claim (exp) must be an'
124+ ' integer.' )
125+
126+ if exp < (now - leeway ):
127+ raise ExpiredSignatureError ('Signature has expired' )
128+
129+ def _validate_aud (self , payload , audience ):
130+ if audience is None and 'aud' not in payload :
131+ return
132+
133+ if audience is not None and 'aud' not in payload :
123134 # Application specified an audience, but it could not be
124135 # verified since the token does not contain a claim.
125136 raise InvalidAudienceError ('No audience claim in token' )
126137
127- if issuer is not None :
128- if payload .get ('iss' ) != issuer :
129- raise InvalidIssuerError ('Invalid issuer' )
138+ audience_claims = payload ['aud' ]
139+
140+ if isinstance (audience_claims , string_types ):
141+ audience_claims = [audience_claims ]
142+ if not isinstance (audience_claims , list ):
143+ raise InvalidAudienceError ('Invalid claim format in token' )
144+ if any (not isinstance (c , string_types ) for c in audience_claims ):
145+ raise InvalidAudienceError ('Invalid claim format in token' )
146+ if audience not in audience_claims :
147+ raise InvalidAudienceError ('Invalid audience' )
148+
149+ def _validate_iss (self , payload , issuer ):
150+ if issuer is None :
151+ return
152+
153+ if 'iss' not in payload :
154+ raise InvalidIssuerError ('Token does not contain an iss claim' )
155+
156+ if payload ['iss' ] != issuer :
157+ raise InvalidIssuerError ('Invalid issuer' )
130158
131159
132160_jwt_global_obj = PyJWT ()
0 commit comments