def _pre_construct(self, response_args, request, **kwargs): _context = self.endpoint_context _access_code = request["code"].replace(' ', '+') _info = _context.sdb[_access_code] _authn_req = _info['authn_req'] try: _client_id = request['client_id'] except KeyError: _client_id = _authn_req['client_id'] if "openid" in _authn_req["scope"]: userinfo = userinfo_in_id_token_claims(_context, _info) try: _idtoken = sign_encrypt_id_token(_context, _info, str(_client_id), user_info=userinfo) except (JWEException, NoSuitableSigningKeys) as err: logger.warning(str(err)) return self.error_cls( error="invalid_request", error_description="Could not sign/encrypt id_token") _context.sdb.update_by_token(_access_code, id_token=_idtoken) response_args['id_token'] = _idtoken return response_args
def make(self, req, sess_info, authn_req=None, user_claims=False, **kwargs): _context = self.endpoint_context _sdb = _context.sdb if authn_req: _client_id = authn_req["client_id"] else: _client_id = req["client_id"] _cinfo = _context.cdb[_client_id] try: default_idtoken_claims = self.kwargs["default_claims"] except KeyError: default_idtoken_claims = None lifetime = self.kwargs.get("lifetime") userinfo = userinfo_in_id_token_claims(_context, sess_info, default_idtoken_claims) if user_claims: info = collect_user_info(_context, sess_info) if userinfo is None: userinfo = info else: userinfo.update(info) try: req_sid = _cinfo["frontchannel_logout_session_required"] except KeyError: try: req_sid = _cinfo["backchannel_logout_session_required"] except KeyError: req_sid = False if req_sid: xargs = { "sid": _context.sdb.get_sid_by_sub_and_client_id( sess_info["sub"], _client_id) } else: xargs = {} return self.sign_encrypt(sess_info, _client_id, sign=True, user_info=userinfo, lifetime=lifetime, extra_claims=xargs, **kwargs)
def make(self, req, sess_info, authn_req=None, user_claims=False, **kwargs): _context = self.endpoint_context _sdb = _context.sdb if authn_req: _client_id = authn_req["client_id"] else: _client_id = req["client_id"] _cinfo = _context.cdb[_client_id] default_idtoken_claims = dict(self.kwargs.get("default_claims", {})) lifetime = self.kwargs.get("lifetime") userinfo = userinfo_in_id_token_claims(_context, sess_info, default_idtoken_claims) if user_claims: info = collect_user_info(_context, sess_info) if userinfo is None: userinfo = info else: userinfo.update(info) # Should I add session ID req_sid = include_session_id(_context, _client_id, "back") or include_session_id( _context, _client_id, "front") if req_sid: xargs = { "sid": _context.sdb.get_sid_by_sub_and_client_id( sess_info["sub"], _client_id) } else: xargs = {} return self.sign_encrypt(sess_info, _client_id, sign=True, user_info=userinfo, lifetime=lifetime, extra_claims=xargs, **kwargs)
def create_authn_response(endpoint_context, request, sid): # create the response aresp = AuthorizationResponse() try: aresp["state"] = request["state"] except KeyError: pass if "response_type" in request and request["response_type"] == ["none"]: fragment_enc = False else: _sinfo = endpoint_context.sdb[sid] try: aresp["scope"] = request["scope"] except KeyError: pass rtype = set(request["response_type"][:]) handled_response_type = [] if len(rtype) == 1 and "code" in rtype: fragment_enc = False else: fragment_enc = True if "code" in request["response_type"]: _code = aresp["code"] = endpoint_context.sdb[sid]["code"] handled_response_type.append("code") else: endpoint_context.sdb.update(sid, code=None) _code = None if "token" in rtype: _dic = endpoint_context.sdb.upgrade_to_token(issue_refresh=False, key=sid) logger.debug("_dic: %s" % sanitize(_dic)) for key, val in _dic.items(): if key in aresp.parameters() and val is not None: aresp[key] = val handled_response_type.append("token") try: _access_token = aresp["access_token"] except KeyError: _access_token = None if "id_token" in request["response_type"]: user_info = userinfo_in_id_token_claims(endpoint_context, _sinfo) if request["response_type"] == ["id_token"]: # scopes should be returned here info = collect_user_info(endpoint_context, _sinfo) if user_info is None: user_info = info else: user_info.update(info) # client_info = endpoint_context.cdb[str(request["client_id"])] hargs = {} if {'code', 'id_token', 'token'}.issubset(rtype): hargs = {"code": _code, "access_token": _access_token} elif {'code', 'id_token'}.issubset(rtype): hargs = {"code": _code} elif {'id_token', 'token'}.issubset(rtype): hargs = {"access_token": _access_token} # or 'code id_token' try: id_token = sign_encrypt_id_token(endpoint_context, _sinfo, str(request["client_id"]), user_info=user_info, sign=True, **hargs) except (JWEException, NoSuitableSigningKeys) as err: logger.warning(str(err)) return AuthorizationErrorResponse( error="invalid_request", error_description="Could not sign/encrypt id_token") aresp["id_token"] = id_token _sinfo["id_token"] = id_token handled_response_type.append("id_token") not_handled = rtype.difference(handled_response_type) if not_handled: raise UnSupported("unsupported_response_type", list(not_handled)) return {'response_args': aresp, 'fragment_enc': fragment_enc}
def _access_token(self, req, **kwargs): _context = self.endpoint_context _sdb = _context.sdb _log_debug = logger.debug if req["grant_type"] != "authorization_code": return self.error_cls(error='invalid_request', error_description='Unknown grant_type') try: _access_code = req["code"].replace(' ', '+') except KeyError: # Missing code parameter - absolutely fatal return self.error_cls(error='invalid_request', error_description='Missing code') # Session might not exist or _access_code malformed try: _info = _sdb[_access_code] except KeyError: return self.error_cls(error="invalid_request", error_description="Code is invalid") _authn_req = _info['authn_req'] # assert that the code is valid if _context.sdb.is_session_revoked(_access_code): return self.error_cls(error="invalid_request", error_description="Session is revoked") # If redirect_uri was in the initial authorization request # verify that the one given here is the correct one. if "redirect_uri" in _authn_req: if req["redirect_uri"] != _authn_req["redirect_uri"]: return self.error_cls(error="invalid_request", error_description="redirect_uri mismatch") _log_debug("All checks OK") issue_refresh = False if "issue_refresh" in kwargs: issue_refresh = kwargs["issue_refresh"] # offline_access the default if nothing is specified permissions = _info.get('permission', ['offline_access']) if 'offline_access' in _authn_req['scope'] and 'offline_access' in permissions: issue_refresh = True try: _info = _sdb.upgrade_to_token(_access_code, issue_refresh=issue_refresh) except AccessCodeUsed as err: logger.error("%s" % err) # Should revoke the token issued to this access code _sdb.revoke_all_tokens(_access_code) return self.error_cls(error="access_denied", error_description="Access Code already used") if "openid" in _authn_req["scope"]: userinfo = userinfo_in_id_token_claims(_context, _info) try: _client_id = req['client_id'] except KeyError: _client_id = _authn_req['client_id'] try: _idtoken = sign_encrypt_id_token(_context, _info, _client_id, sign=True, user_info=userinfo) except (JWEException, NoSuitableSigningKeys) as err: logger.warning(str(err)) return self.error_cls( error="invalid_request", error_description="Could not sign/encrypt id_token") _sdb.update_by_token(_access_code, id_token=_idtoken) _info = _sdb[_access_code] return by_schema(AccessTokenResponse, **_info)