Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/oauthlib/openid/connect/core/grant_types/base.py: 22%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

72 statements  

1import base64 

2import hashlib 

3import logging 

4import time 

5from json import loads 

6 

7from oauthlib.oauth2.rfc6749.errors import ( 

8 ConsentRequired, InvalidRequestError, LoginRequired, 

9) 

10 

11log = logging.getLogger(__name__) 

12 

13 

14class GrantTypeBase: 

15 

16 # Just proxy the majority of method calls through to the 

17 # proxy_target grant type handler, which will usually be either 

18 # the standard OAuth2 AuthCode or Implicit grant types. 

19 def __getattr__(self, attr): 

20 return getattr(self.proxy_target, attr) 

21 

22 def __setattr__(self, attr, value): 

23 proxied_attrs = {'refresh_token', 'response_types'} 

24 if attr in proxied_attrs: 

25 setattr(self.proxy_target, attr, value) 

26 else: 

27 super(OpenIDConnectBase, self).__setattr__(attr, value) 

28 

29 def validate_authorization_request(self, request): 

30 """Validates the OpenID Connect authorization request parameters. 

31 

32 :returns: (list of scopes, dict of request info) 

33 """ 

34 return self.proxy_target.validate_authorization_request(request) 

35 

36 def _inflate_claims(self, request): 

37 # this may be called multiple times in a single request so make sure we only de-serialize the claims once 

38 if request.claims and not isinstance(request.claims, dict): 

39 # specific claims are requested during the Authorization Request and may be requested for inclusion 

40 # in either the id_token or the UserInfo endpoint response 

41 # see http://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter 

42 try: 

43 request.claims = loads(request.claims) 

44 except Exception as ex: 

45 raise InvalidRequestError(description="Malformed claims parameter", 

46 uri="http://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter") 

47 

48 def id_token_hash(self, value, hashfunc=hashlib.sha256): 

49 """ 

50 Its value is the base64url encoding of the left-most half of the 

51 hash of the octets of the ASCII representation of the access_token 

52 value, where the hash algorithm used is the hash algorithm used in 

53 the alg Header Parameter of the ID Token's JOSE Header. 

54 

55 For instance, if the alg is RS256, hash the access_token value 

56 with SHA-256, then take the left-most 128 bits and 

57 base64url-encode them. 

58 For instance, if the alg is HS512, hash the code value with 

59 SHA-512, then take the left-most 256 bits and base64url-encode 

60 them. The c_hash value is a case-sensitive string. 

61 

62 Example of hash from OIDC specification (bound to a JWS using RS256): 

63 

64 code: 

65 Qcb0Orv1zh30vL1MPRsbm-diHiMwcLyZvn1arpZv-Jxf_11jnpEX3Tgfvk 

66 

67 c_hash: 

68 LDktKdoQak3Pk0cnXxCltA 

69 """ 

70 digest = hashfunc(value.encode()).digest() 

71 left_most = len(digest) // 2 

72 return base64.urlsafe_b64encode(digest[:left_most]).decode().rstrip("=") 

73 

74 def add_id_token(self, token, token_handler, request, nonce=None): 

75 """ 

76 Construct an initial version of id_token, and let the 

77 request_validator sign or encrypt it. 

78 

79 The initial version can contain the fields below, accordingly 

80 to the spec: 

81 - aud 

82 - iat 

83 - nonce 

84 - at_hash 

85 - c_hash 

86 """ 

87 # Treat it as normal OAuth 2 auth code request if openid is not present 

88 if not request.scopes or 'openid' not in request.scopes: 

89 return token 

90 

91 # Only add an id token on auth/token step if asked for. 

92 if request.response_type and 'id_token' not in request.response_type: 

93 return token 

94 

95 # Implementation mint its own id_token without help. 

96 id_token = self.request_validator.get_id_token(token, token_handler, request) 

97 if id_token: 

98 token['id_token'] = id_token 

99 return token 

100 

101 # Fallback for asking some help from oauthlib framework. 

102 # Start with technicals fields bound to the specification. 

103 id_token = {} 

104 id_token['aud'] = request.client_id 

105 id_token['iat'] = int(time.time()) 

106 

107 # nonce is REQUIRED when response_type value is: 

108 # - id_token token (Implicit) 

109 # - id_token (Implicit) 

110 # - code id_token (Hybrid) 

111 # - code id_token token (Hybrid) 

112 # 

113 # nonce is OPTIONAL when response_type value is: 

114 # - code (Authorization Code) 

115 # - code token (Hybrid) 

116 if nonce is not None: 

117 id_token["nonce"] = nonce 

118 

119 # at_hash is REQUIRED when response_type value is: 

120 # - id_token token (Implicit) 

121 # - code id_token token (Hybrid) 

122 # 

123 # at_hash is OPTIONAL when: 

124 # - code (Authorization code) 

125 # - code id_token (Hybrid) 

126 # - code token (Hybrid) 

127 # 

128 # at_hash MAY NOT be used when: 

129 # - id_token (Implicit) 

130 if "access_token" in token: 

131 id_token["at_hash"] = self.id_token_hash(token["access_token"]) 

132 

133 # c_hash is REQUIRED when response_type value is: 

134 # - code id_token (Hybrid) 

135 # - code id_token token (Hybrid) 

136 # 

137 # c_hash is OPTIONAL for others. 

138 if "code" in token: 

139 id_token["c_hash"] = self.id_token_hash(token["code"]) 

140 

141 # Call request_validator to complete/sign/encrypt id_token 

142 token['id_token'] = self.request_validator.finalize_id_token(id_token, token, token_handler, request) 

143 

144 return token 

145 

146 def openid_authorization_validator(self, request): 

147 """Perform OpenID Connect specific authorization request validation. 

148 

149 nonce 

150 OPTIONAL. String value used to associate a Client session with 

151 an ID Token, and to mitigate replay attacks. The value is 

152 passed through unmodified from the Authentication Request to 

153 the ID Token. Sufficient entropy MUST be present in the nonce 

154 values used to prevent attackers from guessing values 

155 

156 display 

157 OPTIONAL. ASCII string value that specifies how the 

158 Authorization Server displays the authentication and consent 

159 user interface pages to the End-User. The defined values are: 

160 

161 page - The Authorization Server SHOULD display the 

162 authentication and consent UI consistent with a full User 

163 Agent page view. If the display parameter is not specified, 

164 this is the default display mode. 

165 

166 popup - The Authorization Server SHOULD display the 

167 authentication and consent UI consistent with a popup User 

168 Agent window. The popup User Agent window should be of an 

169 appropriate size for a login-focused dialog and should not 

170 obscure the entire window that it is popping up over. 

171 

172 touch - The Authorization Server SHOULD display the 

173 authentication and consent UI consistent with a device that 

174 leverages a touch interface. 

175 

176 wap - The Authorization Server SHOULD display the 

177 authentication and consent UI consistent with a "feature 

178 phone" type display. 

179 

180 The Authorization Server MAY also attempt to detect the 

181 capabilities of the User Agent and present an appropriate 

182 display. 

183 

184 prompt 

185 OPTIONAL. Space delimited, case sensitive list of ASCII string 

186 values that specifies whether the Authorization Server prompts 

187 the End-User for reauthentication and consent. The defined 

188 values are: 

189 

190 none - The Authorization Server MUST NOT display any 

191 authentication or consent user interface pages. An error is 

192 returned if an End-User is not already authenticated or the 

193 Client does not have pre-configured consent for the 

194 requested Claims or does not fulfill other conditions for 

195 processing the request. The error code will typically be 

196 login_required, interaction_required, or another code 

197 defined in Section 3.1.2.6. This can be used as a method to 

198 check for existing authentication and/or consent. 

199 

200 login - The Authorization Server SHOULD prompt the End-User 

201 for reauthentication. If it cannot reauthenticate the 

202 End-User, it MUST return an error, typically 

203 login_required. 

204 

205 consent - The Authorization Server SHOULD prompt the 

206 End-User for consent before returning information to the 

207 Client. If it cannot obtain consent, it MUST return an 

208 error, typically consent_required. 

209 

210 select_account - The Authorization Server SHOULD prompt the 

211 End-User to select a user account. This enables an End-User 

212 who has multiple accounts at the Authorization Server to 

213 select amongst the multiple accounts that they might have 

214 current sessions for. If it cannot obtain an account 

215 selection choice made by the End-User, it MUST return an 

216 error, typically account_selection_required. 

217 

218 The prompt parameter can be used by the Client to make sure 

219 that the End-User is still present for the current session or 

220 to bring attention to the request. If this parameter contains 

221 none with any other value, an error is returned. 

222 

223 max_age 

224 OPTIONAL. Maximum Authentication Age. Specifies the allowable 

225 elapsed time in seconds since the last time the End-User was 

226 actively authenticated by the OP. If the elapsed time is 

227 greater than this value, the OP MUST attempt to actively 

228 re-authenticate the End-User. (The max_age request parameter 

229 corresponds to the OpenID 2.0 PAPE [OpenID.PAPE] max_auth_age 

230 request parameter.) When max_age is used, the ID Token returned 

231 MUST include an auth_time Claim Value. 

232 

233 ui_locales 

234 OPTIONAL. End-User's preferred languages and scripts for the 

235 user interface, represented as a space-separated list of BCP47 

236 [RFC5646] language tag values, ordered by preference. For 

237 instance, the value "fr-CA fr en" represents a preference for 

238 French as spoken in Canada, then French (without a region 

239 designation), followed by English (without a region 

240 designation). An error SHOULD NOT result if some or all of the 

241 requested locales are not supported by the OpenID Provider. 

242 

243 id_token_hint 

244 OPTIONAL. ID Token previously issued by the Authorization 

245 Server being passed as a hint about the End-User's current or 

246 past authenticated session with the Client. If the End-User 

247 identified by the ID Token is logged in or is logged in by the 

248 request, then the Authorization Server returns a positive 

249 response; otherwise, it SHOULD return an error, such as 

250 login_required. When possible, an id_token_hint SHOULD be 

251 present when prompt=none is used and an invalid_request error 

252 MAY be returned if it is not; however, the server SHOULD 

253 respond successfully when possible, even if it is not present. 

254 The Authorization Server need not be listed as an audience of 

255 the ID Token when it is used as an id_token_hint value. If the 

256 ID Token received by the RP from the OP is encrypted, to use it 

257 as an id_token_hint, the Client MUST decrypt the signed ID 

258 Token contained within the encrypted ID Token. The Client MAY 

259 re-encrypt the signed ID token to the Authentication Server 

260 using a key that enables the server to decrypt the ID Token, 

261 and use the re-encrypted ID token as the id_token_hint value. 

262 

263 login_hint 

264 OPTIONAL. Hint to the Authorization Server about the login 

265 identifier the End-User might use to log in (if necessary). 

266 This hint can be used by an RP if it first asks the End-User 

267 for their e-mail address (or other identifier) and then wants 

268 to pass that value as a hint to the discovered authorization 

269 service. It is RECOMMENDED that the hint value match the value 

270 used for discovery. This value MAY also be a phone number in 

271 the format specified for the phone_number Claim. The use of 

272 this parameter is left to the OP's discretion. 

273 

274 acr_values 

275 OPTIONAL. Requested Authentication Context Class Reference 

276 values. Space-separated string that specifies the acr values 

277 that the Authorization Server is being requested to use for 

278 processing this Authentication Request, with the values 

279 appearing in order of preference. The Authentication Context 

280 Class satisfied by the authentication performed is returned as 

281 the acr Claim Value, as specified in Section 2. The acr Claim 

282 is requested as a Voluntary Claim by this parameter. 

283 """ 

284 

285 # Treat it as normal OAuth 2 auth code request if openid is not present 

286 if not request.scopes or 'openid' not in request.scopes: 

287 return {} 

288 

289 prompt = request.prompt if request.prompt else [] 

290 if hasattr(prompt, 'split'): 

291 prompt = prompt.strip().split() 

292 prompt = set(prompt) 

293 

294 if 'none' in prompt: 

295 

296 if len(prompt) > 1: 

297 msg = "Prompt none is mutually exclusive with other values." 

298 raise InvalidRequestError(request=request, description=msg) 

299 

300 if not self.request_validator.validate_silent_login(request): 

301 raise LoginRequired(request=request) 

302 

303 if not self.request_validator.validate_silent_authorization(request): 

304 raise ConsentRequired(request=request) 

305 

306 self._inflate_claims(request) 

307 

308 if not self.request_validator.validate_user_match( 

309 request.id_token_hint, request.scopes, request.claims, request): 

310 msg = "Session user does not match client supplied user." 

311 raise LoginRequired(request=request, description=msg) 

312 

313 ui_locales = request.ui_locales if request.ui_locales else [] 

314 if hasattr(ui_locales, 'split'): 

315 ui_locales = ui_locales.strip().split() 

316 

317 request_info = { 

318 'display': request.display, 

319 'nonce': request.nonce, 

320 'prompt': prompt, 

321 'ui_locales': ui_locales, 

322 'id_token_hint': request.id_token_hint, 

323 'login_hint': request.login_hint, 

324 'claims': request.claims 

325 } 

326 

327 return request_info 

328 

329 

330OpenIDConnectBase = GrantTypeBase