Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/oauthlib/oauth2/rfc6749/errors.py: 63%

145 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:22 +0000

1""" 

2oauthlib.oauth2.rfc6749.errors 

3~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

4 

5Error used both by OAuth 2 clients and providers to represent the spec 

6defined error responses for all four core grant types. 

7""" 

8import json 

9 

10from oauthlib.common import add_params_to_uri, urlencode 

11 

12 

13class OAuth2Error(Exception): 

14 error = None 

15 status_code = 400 

16 description = '' 

17 

18 def __init__(self, description=None, uri=None, state=None, 

19 status_code=None, request=None): 

20 """ 

21 :param description: A human-readable ASCII [USASCII] text providing 

22 additional information, used to assist the client 

23 developer in understanding the error that occurred. 

24 Values for the "error_description" parameter 

25 MUST NOT include characters outside the set 

26 x20-21 / x23-5B / x5D-7E. 

27 

28 :param uri: A URI identifying a human-readable web page with information 

29 about the error, used to provide the client developer with 

30 additional information about the error. Values for the 

31 "error_uri" parameter MUST conform to the URI- Reference 

32 syntax, and thus MUST NOT include characters outside the set 

33 x21 / x23-5B / x5D-7E. 

34 

35 :param state: A CSRF protection value received from the client. 

36 

37 :param status_code: 

38 

39 :param request: OAuthlib request. 

40 :type request: oauthlib.common.Request 

41 """ 

42 if description is not None: 

43 self.description = description 

44 

45 message = '({}) {}'.format(self.error, self.description) 

46 if request: 

47 message += ' ' + repr(request) 

48 super().__init__(message) 

49 

50 self.uri = uri 

51 self.state = state 

52 

53 if status_code: 

54 self.status_code = status_code 

55 

56 if request: 

57 self.redirect_uri = request.redirect_uri 

58 self.client_id = request.client_id 

59 self.scopes = request.scopes 

60 self.response_type = request.response_type 

61 self.response_mode = request.response_mode 

62 self.grant_type = request.grant_type 

63 if not state: 

64 self.state = request.state 

65 else: 

66 self.redirect_uri = None 

67 self.client_id = None 

68 self.scopes = None 

69 self.response_type = None 

70 self.response_mode = None 

71 self.grant_type = None 

72 

73 def in_uri(self, uri): 

74 fragment = self.response_mode == "fragment" 

75 return add_params_to_uri(uri, self.twotuples, fragment) 

76 

77 @property 

78 def twotuples(self): 

79 error = [('error', self.error)] 

80 if self.description: 

81 error.append(('error_description', self.description)) 

82 if self.uri: 

83 error.append(('error_uri', self.uri)) 

84 if self.state: 

85 error.append(('state', self.state)) 

86 return error 

87 

88 @property 

89 def urlencoded(self): 

90 return urlencode(self.twotuples) 

91 

92 @property 

93 def json(self): 

94 return json.dumps(dict(self.twotuples)) 

95 

96 @property 

97 def headers(self): 

98 if self.status_code == 401: 

99 """ 

100 https://tools.ietf.org/html/rfc6750#section-3 

101 

102 All challenges defined by this specification MUST use the auth-scheme 

103 value "Bearer". This scheme MUST be followed by one or more 

104 auth-param values. 

105 """ 

106 authvalues = ['error="{}"'.format(self.error)] 

107 if self.description: 

108 authvalues.append('error_description="{}"'.format(self.description)) 

109 if self.uri: 

110 authvalues.append('error_uri="{}"'.format(self.uri)) 

111 return {"WWW-Authenticate": "Bearer " + ", ".join(authvalues)} 

112 return {} 

113 

114 

115class TokenExpiredError(OAuth2Error): 

116 error = 'token_expired' 

117 

118 

119class InsecureTransportError(OAuth2Error): 

120 error = 'insecure_transport' 

121 description = 'OAuth 2 MUST utilize https.' 

122 

123 

124class MismatchingStateError(OAuth2Error): 

125 error = 'mismatching_state' 

126 description = 'CSRF Warning! State not equal in request and response.' 

127 

128 

129class MissingCodeError(OAuth2Error): 

130 error = 'missing_code' 

131 

132 

133class MissingTokenError(OAuth2Error): 

134 error = 'missing_token' 

135 

136 

137class MissingTokenTypeError(OAuth2Error): 

138 error = 'missing_token_type' 

139 

140 

141class FatalClientError(OAuth2Error): 

142 """ 

143 Errors during authorization where user should not be redirected back. 

144 

145 If the request fails due to a missing, invalid, or mismatching 

146 redirection URI, or if the client identifier is missing or invalid, 

147 the authorization server SHOULD inform the resource owner of the 

148 error and MUST NOT automatically redirect the user-agent to the 

149 invalid redirection URI. 

150 

151 Instead the user should be informed of the error by the provider itself. 

152 """ 

153 pass 

154 

155 

156class InvalidRequestFatalError(FatalClientError): 

157 """ 

158 For fatal errors, the request is missing a required parameter, includes 

159 an invalid parameter value, includes a parameter more than once, or is 

160 otherwise malformed. 

161 """ 

162 error = 'invalid_request' 

163 

164 

165class InvalidRedirectURIError(InvalidRequestFatalError): 

166 description = 'Invalid redirect URI.' 

167 

168 

169class MissingRedirectURIError(InvalidRequestFatalError): 

170 description = 'Missing redirect URI.' 

171 

172 

173class MismatchingRedirectURIError(InvalidRequestFatalError): 

174 description = 'Mismatching redirect URI.' 

175 

176 

177class InvalidClientIdError(InvalidRequestFatalError): 

178 description = 'Invalid client_id parameter value.' 

179 

180 

181class MissingClientIdError(InvalidRequestFatalError): 

182 description = 'Missing client_id parameter.' 

183 

184 

185class InvalidRequestError(OAuth2Error): 

186 """ 

187 The request is missing a required parameter, includes an invalid 

188 parameter value, includes a parameter more than once, or is 

189 otherwise malformed. 

190 """ 

191 error = 'invalid_request' 

192 

193 

194class MissingResponseTypeError(InvalidRequestError): 

195 description = 'Missing response_type parameter.' 

196 

197 

198class MissingCodeChallengeError(InvalidRequestError): 

199 """ 

200 If the server requires Proof Key for Code Exchange (PKCE) by OAuth 

201 public clients and the client does not send the "code_challenge" in 

202 the request, the authorization endpoint MUST return the authorization 

203 error response with the "error" value set to "invalid_request". The 

204 "error_description" or the response of "error_uri" SHOULD explain the 

205 nature of error, e.g., code challenge required. 

206 """ 

207 description = 'Code challenge required.' 

208 

209 

210class MissingCodeVerifierError(InvalidRequestError): 

211 """ 

212 The request to the token endpoint, when PKCE is enabled, has 

213 the parameter `code_verifier` REQUIRED. 

214 """ 

215 description = 'Code verifier required.' 

216 

217 

218class AccessDeniedError(OAuth2Error): 

219 """ 

220 The resource owner or authorization server denied the request. 

221 """ 

222 error = 'access_denied' 

223 

224 

225class UnsupportedResponseTypeError(OAuth2Error): 

226 """ 

227 The authorization server does not support obtaining an authorization 

228 code using this method. 

229 """ 

230 error = 'unsupported_response_type' 

231 

232 

233class UnsupportedCodeChallengeMethodError(InvalidRequestError): 

234 """ 

235 If the server supporting PKCE does not support the requested 

236 transformation, the authorization endpoint MUST return the 

237 authorization error response with "error" value set to 

238 "invalid_request". The "error_description" or the response of 

239 "error_uri" SHOULD explain the nature of error, e.g., transform 

240 algorithm not supported. 

241 """ 

242 description = 'Transform algorithm not supported.' 

243 

244 

245class InvalidScopeError(OAuth2Error): 

246 """ 

247 The requested scope is invalid, unknown, or malformed, or 

248 exceeds the scope granted by the resource owner. 

249 

250 https://tools.ietf.org/html/rfc6749#section-5.2 

251 """ 

252 error = 'invalid_scope' 

253 

254 

255class ServerError(OAuth2Error): 

256 """ 

257 The authorization server encountered an unexpected condition that 

258 prevented it from fulfilling the request. (This error code is needed 

259 because a 500 Internal Server Error HTTP status code cannot be returned 

260 to the client via a HTTP redirect.) 

261 """ 

262 error = 'server_error' 

263 

264 

265class TemporarilyUnavailableError(OAuth2Error): 

266 """ 

267 The authorization server is currently unable to handle the request 

268 due to a temporary overloading or maintenance of the server. 

269 (This error code is needed because a 503 Service Unavailable HTTP 

270 status code cannot be returned to the client via a HTTP redirect.) 

271 """ 

272 error = 'temporarily_unavailable' 

273 

274 

275class InvalidClientError(FatalClientError): 

276 """ 

277 Client authentication failed (e.g. unknown client, no client 

278 authentication included, or unsupported authentication method). 

279 The authorization server MAY return an HTTP 401 (Unauthorized) status 

280 code to indicate which HTTP authentication schemes are supported. 

281 If the client attempted to authenticate via the "Authorization" request 

282 header field, the authorization server MUST respond with an 

283 HTTP 401 (Unauthorized) status code, and include the "WWW-Authenticate" 

284 response header field matching the authentication scheme used by the 

285 client. 

286 """ 

287 error = 'invalid_client' 

288 status_code = 401 

289 

290 

291class InvalidGrantError(OAuth2Error): 

292 """ 

293 The provided authorization grant (e.g. authorization code, resource 

294 owner credentials) or refresh token is invalid, expired, revoked, does 

295 not match the redirection URI used in the authorization request, or was 

296 issued to another client. 

297 

298 https://tools.ietf.org/html/rfc6749#section-5.2 

299 """ 

300 error = 'invalid_grant' 

301 status_code = 400 

302 

303 

304class UnauthorizedClientError(OAuth2Error): 

305 """ 

306 The authenticated client is not authorized to use this authorization 

307 grant type. 

308 """ 

309 error = 'unauthorized_client' 

310 

311 

312class UnsupportedGrantTypeError(OAuth2Error): 

313 """ 

314 The authorization grant type is not supported by the authorization 

315 server. 

316 """ 

317 error = 'unsupported_grant_type' 

318 

319 

320class UnsupportedTokenTypeError(OAuth2Error): 

321 """ 

322 The authorization server does not support the hint of the 

323 presented token type. I.e. the client tried to revoke an access token 

324 on a server not supporting this feature. 

325 """ 

326 error = 'unsupported_token_type' 

327 

328 

329class InvalidTokenError(OAuth2Error): 

330 """ 

331 The access token provided is expired, revoked, malformed, or 

332 invalid for other reasons. The resource SHOULD respond with 

333 the HTTP 401 (Unauthorized) status code. The client MAY 

334 request a new access token and retry the protected resource 

335 request. 

336 """ 

337 error = 'invalid_token' 

338 status_code = 401 

339 description = ("The access token provided is expired, revoked, malformed, " 

340 "or invalid for other reasons.") 

341 

342 

343class InsufficientScopeError(OAuth2Error): 

344 """ 

345 The request requires higher privileges than provided by the 

346 access token. The resource server SHOULD respond with the HTTP 

347 403 (Forbidden) status code and MAY include the "scope" 

348 attribute with the scope necessary to access the protected 

349 resource. 

350 """ 

351 error = 'insufficient_scope' 

352 status_code = 403 

353 description = ("The request requires higher privileges than provided by " 

354 "the access token.") 

355 

356 

357class ConsentRequired(OAuth2Error): 

358 """ 

359 The Authorization Server requires End-User consent. 

360 

361 This error MAY be returned when the prompt parameter value in the 

362 Authentication Request is none, but the Authentication Request cannot be 

363 completed without displaying a user interface for End-User consent. 

364 """ 

365 error = 'consent_required' 

366 

367 

368class LoginRequired(OAuth2Error): 

369 """ 

370 The Authorization Server requires End-User authentication. 

371 

372 This error MAY be returned when the prompt parameter value in the 

373 Authentication Request is none, but the Authentication Request cannot be 

374 completed without displaying a user interface for End-User authentication. 

375 """ 

376 error = 'login_required' 

377 

378 

379class CustomOAuth2Error(OAuth2Error): 

380 """ 

381 This error is a placeholder for all custom errors not described by the RFC. 

382 Some of the popular OAuth2 providers are using custom errors. 

383 """ 

384 def __init__(self, error, *args, **kwargs): 

385 self.error = error 

386 super().__init__(*args, **kwargs) 

387 

388 

389def raise_from_error(error, params=None): 

390 import inspect 

391 import sys 

392 kwargs = { 

393 'description': params.get('error_description'), 

394 'uri': params.get('error_uri'), 

395 'state': params.get('state') 

396 } 

397 for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass): 

398 if cls.error == error: 

399 raise cls(**kwargs) 

400 raise CustomOAuth2Error(error=error, **kwargs)