def render_GET(self, request): session = {} oidconsumer = consumer.Consumer(session, None) request = oidconsumer.begin(self.provider) request.addExtension(sreg.SRegRequest( required=['nickname', 'fullname', 'email', 'timezone'])) request.addExtension(teams.TeamsRequest(requested=self.groups)) request.addExtension(cla.CLARequest( requested=[cla.CLA_URI_FEDORA_DONE])) trust_root = self.root_url return_to = self.root_url + '_openid_handle/' if request.shouldSendRedirect(): redirect_url = request.redirectURL(trust_root, return_to, False) request.redirect(redirect_url) else: return request.htmlMarkup( trust_root, return_to, form_tag_attrs={'id': 'openid_message'}, immediate=False) try: request.finish() except RuntimeError: # this occurs when the client has already disconnected; ignore # it (see #2027) log.msg("http client disconnected before results were sent")
def login(self, return_url=None, cancel_url=None, groups=None): """Tries to log in a user. Sets the user information on :attr:`flask.g.fas_user`. Will set 0 to :attr:`flask.g.fas_session_id, for compatibility with flask_fas. :kwarg username: Not used, but accepted for compatibility with the flask_fas module :kwarg password: Not used, but accepted for compatibility with the flask_fas module :kwarg return_url: The URL to forward the user to after login :kwarg groups: A string or a list of group the user should belong to to be authentified. :returns: True if the user was succesfully authenticated. :raises: Might raise an redirect to the OpenID endpoint """ if groups is None: groups = ['_FAS_ALL_GROUPS_'] if return_url is None: return_url = flask.request.args.get('next', flask.request.url) session = {} oidconsumer = consumer.Consumer(session, None) try: request = oidconsumer.begin(self.app.config['FAS_OPENID_ENDPOINT']) except consumer.DiscoveryFailure: # VERY strange, as this means it could not discover an OpenID # endpoint at FAS_OPENID_ENDPOINT return 'discoveryfailure' if request is None: # Also very strange, as this means the discovered OpenID # endpoint is no OpenID endpoint return 'no-request' if isinstance(groups, basestring): groups = [groups] request.addExtension( sreg.SRegRequest( required=['nickname', 'fullname', 'email', 'timezone'])) request.addExtension(pape.Request([])) request.addExtension(teams.TeamsRequest(requested=groups)) request.addExtension( cla.CLARequest(requested=[cla.CLA_URI_FEDORA_DONE])) trust_root = self.normalize_url(flask.request.url_root) return_to = trust_root + '_flask_fas_openid_handler/' flask.session['FLASK_FAS_OPENID_RETURN_URL'] = return_url flask.session['FLASK_FAS_OPENID_CANCEL_URL'] = cancel_url if request.shouldSendRedirect(): redirect_url = request.redirectURL(trust_root, return_to, False) return flask.redirect(redirect_url) else: return request.htmlMarkup(trust_root, return_to, form_tag_attrs={'id': 'openid_message'}, immediate=False)
def process_incoming_request(context, request, incoming_openid_url): settings = request.registry.settings log.info('OpenID URL supplied by user: %s' % incoming_openid_url) openid_consumer = consumer.Consumer(request.session, None) try: openid_request = openid_consumer.begin(incoming_openid_url) ax_required = get_ax_required_from_settings(settings) ax_optional = get_ax_optional_from_settings(settings) log.info('ax_required: %s' % ax_required) log.info('ax_optional: %s' % ax_optional) if len(ax_required.values()) or len(ax_optional.values()): fetch_request = ax.FetchRequest() for value in ax_required.values(): fetch_request.add(ax.AttrInfo(value, required=True)) for value in ax_optional.values(): fetch_request.add(ax.AttrInfo(value, required=False)) openid_request.addExtension(fetch_request) sreg_required = get_sreg_required_from_settings(settings) sreg_optional = get_sreg_optional_from_settings(settings) log.info('sreg_required: %s' % sreg_required) log.info('sreg_optional: %s' % sreg_optional) if len(sreg_required) or len(sreg_optional): sreq = sreg.SRegRequest(required=sreg_required, optional=sreg_optional) openid_request.addExtension(sreq) # Default is magic which requests all groups from FAS-OpenID >= 0.2.0 groups = request.registry.settings.get('openid.groups', '_FAS_ALL_GROUPS_') if isinstance(groups, six.string_types): groups = groups.split() openid_request.addExtension(teams.TeamsRequest(requested=groups)) openid_request.addExtension( cla.CLARequest(requested=[cla.CLA_URI_FEDORA_DONE])) except consumer.DiscoveryFailure as exc: # eventually no openid server could be found return error_to_login_form(request, 'Error in discovery: %s' % exc[0]) except KeyError as exc: # TODO: when does that happen, why does plone.openid use "pass" here? return error_to_login_form(request, 'Error in discovery: %s' % exc[0]) # not sure this can still happen but we are making sure. # should actually been handled by the DiscoveryFailure exception above if openid_request is None: return error_to_login_form( request, 'No OpenID services found for %s' % incoming_openid_url) #Not sure what the point of setting this to anything else is realm_name = settings.get('openid.realm_name', request.host_url) return_url = request.path_url redirect_url = openid_request.redirectURL(realm_name, return_url) log.info('Realm Name: %s' % realm_name) log.info('Return URL from provider will be: %s' % return_url) log.info('Redirecting to: %s' % redirect_url) return HTTPFound(location=redirect_url)
def handle_initial_request(request): groups = ['sysadmin-releng', 'sysadmin-main'] session = {} oidconsumer = consumer.Consumer(session, None) try: req = oidconsumer.begin('https://id.fedoraproject.org') except consumer.DiscoveryFailure: # VERY strange, as this means it could not discover an OpenID # endpoint at FAS_OPENID_ENDPOINT return 'discoveryfailure' if req is None: # Also very strange, as this means the discovered OpenID # endpoint is no OpenID endpoint return 'no-req' req.addExtension(sreg.SRegRequest( required=['nickname', 'fullname', 'email', 'timezone'])) req.addExtension(pape.Request([])) req.addExtension(teams.TeamsRequest(requested=groups)) req.addExtension(cla.CLARequest( requested=[cla.CLA_URI_FEDORA_DONE])) # Use the django HTTPRequest for this trust_root = request.build_absolute_uri('/') return_to = request.build_absolute_uri() + "?type=fas-openid" # Success or fail, redirect to the base. ¯\_(ツ)_/¯ return_url = cancel_url = request.build_absolute_uri('/') request.session['FAS_OPENID_RETURN_URL'] = return_url request.session['FAS_OPENID_CANCEL_URL'] = cancel_url # the django rest framework requires that we use the json route here return dict(form=req.htmlMarkup(trust_root, return_to, form_tag_attrs={'id': 'openid_message'}, immediate=False))
def login(self, username=None, password=None, return_url=None, cancel_url=None, groups=['_FAS_ALL_GROUPS_']): """ Copied from the FAS Flask OpenID Auth Plugin with modifications to be compatible with a separate frontend application. """ if return_url is None: if 'next' in flask.request.args.values(): return_url = flask.request.args.values['next'] else: return_url = flask.request.url_root return_to_same_app = self._check_safe_root(return_url) session = {} oidconsumer = consumer.Consumer(session, None) try: request = oidconsumer.begin(self.app.config['FAS_OPENID_ENDPOINT']) except consumer.DiscoveryFailure as exc: # VERY strange, as this means it could not discover an OpenID # endpoint at FAS_OPENID_ENDPOINT log.warn(exc) return 'discoveryfailure' if request is None: # Also very strange, as this means the discovered OpenID # endpoint is no OpenID endpoint return 'no-request' if isinstance(groups, six.string_types): groups = [groups] request.addExtension( sreg.SRegRequest( required=['nickname', 'fullname', 'email', 'timezone'])) request.addExtension(pape.Request([])) request.addExtension(teams.TeamsRequest(requested=groups)) request.addExtension( cla.CLARequest(requested=[cla.CLA_URI_FEDORA_DONE])) ax_req = ax.FetchRequest() ax_req.add( ax.AttrInfo( type_uri='http://fedoauth.org/openid/schema/GPG/keyid')) ax_req.add( ax.AttrInfo(type_uri='http://fedoauth.org/openid/schema/SSH/key', count='unlimited')) request.addExtension(ax_req) trust_root = self.normalize_url(flask.request.url_root) return_to = trust_root + '_flask_fas_openid_handler/' flask.session['FLASK_FAS_OPENID_RETURN_URL'] = return_url flask.session['FLASK_FAS_OPENID_CANCEL_URL'] = cancel_url flask.session.modified = True if request_wants_json(): output = request.getMessage(trust_root, return_to=return_to).toPostArgs() output['server_url'] = request.endpoint.server_url return flask.jsonify(output) elif request.shouldSendRedirect(): redirect_url = request.redirectURL(trust_root, return_to, False) return flask.redirect(redirect_url) elif not return_to_same_app: return_to = os.environ['CLIENT_URL'] + '/_flask_fas_openid_handler/' redirect_url = request.redirectURL(os.environ['CLIENT_URL'], return_to, False) return redirect_url else: return request.htmlMarkup(trust_root, return_to, form_tag_attrs={'id': 'openid_message'}, immediate=False)
def login(self, username=None, password=None, return_url=None, cancel_url=None, groups=['_FAS_ALL_GROUPS_']): """Tries to log in a user. Sets the user information on :attr:`flask.g.fas_user`. Will set 0 to :attr:`flask.g.fas_session_id, for compatibility with flask_fas. :kwarg username: Not used, but accepted for compatibility with the flask_fas module :kwarg password: Not used, but accepted for compatibility with the flask_fas module :kwarg return_url: The URL to forward the user to after login :kwarg groups: A string or a list of group the user should belong to to be authentified. :returns: True if the user was succesfully authenticated. :raises: Might raise an redirect to the OpenID endpoint """ if return_url is None: if 'next' in flask.request.args.values(): return_url = flask.request.args.values['next'] else: return_url = flask.request.url_root # This makes sure that we only allow stuff where # ?next= value is in a safe root (the application # root) return_url = (self._check_safe_root(return_url) or flask.request.url_root) session = {} oidconsumer = consumer.Consumer(session, None) try: request = oidconsumer.begin(self.app.config['FAS_OPENID_ENDPOINT']) except consumer.DiscoveryFailure as exc: # VERY strange, as this means it could not discover an OpenID # endpoint at FAS_OPENID_ENDPOINT log.warn(exc) return 'discoveryfailure' if request is None: # Also very strange, as this means the discovered OpenID # endpoint is no OpenID endpoint return 'no-request' if isinstance(groups, six.string_types): groups = [groups] # Some applications pass the group list as a set. Convert to a list in # case we need to append to it (see below). if isinstance(groups, set): groups = list(groups) # In the new AAA system, we know a user has signed the FPCA by looking # a group membership. We must therefore always request the # corresponding group. if "_FAS_ALL_GROUPS_" not in groups: groups.append("signed_fpca") request.addExtension( sreg.SRegRequest( required=['nickname', 'fullname', 'email', 'timezone'])) request.addExtension(pape.Request([])) request.addExtension(teams.TeamsRequest(requested=groups)) request.addExtension( cla.CLARequest(requested=[cla.CLA_URI_FEDORA_DONE])) ax_req = ax.FetchRequest() ax_req.add( ax.AttrInfo( type_uri='http://fedoauth.org/openid/schema/GPG/keyid')) ax_req.add( ax.AttrInfo(type_uri='http://fedoauth.org/openid/schema/SSH/key', count='unlimited')) request.addExtension(ax_req) trust_root = self.normalize_url(flask.request.url_root) return_to = trust_root + '_flask_fas_openid_handler/' flask.session['FLASK_FAS_OPENID_RETURN_URL'] = return_url flask.session['FLASK_FAS_OPENID_CANCEL_URL'] = cancel_url if request_wants_json(): output = request.getMessage(trust_root, return_to=return_to).toPostArgs() output['server_url'] = request.endpoint.server_url return flask.jsonify(output) elif request.shouldSendRedirect(): redirect_url = request.redirectURL(trust_root, return_to, False) return flask.redirect(redirect_url) else: return request.htmlMarkup(trust_root, return_to, form_tag_attrs={'id': 'openid_message'}, immediate=False)
class FAS(object): def __init__(self, app=None): self.app = app if self.app is not None: self._init_app(app) def _init_app(self, app): app.config.setdefault('FAS_OPENID_ENDPOINT', 'http://id.fedoraproject.org/') app.config.setdefault('FAS_OPENID_CHECK_CERT', True) if not self.app.config['FAS_OPENID_CHECK_CERT']: setDefaultFetcher(Urllib2Fetcher()) @app.route('/_flask_fas_openid_handler/', methods=['GET', 'POST']) def flask_fas_openid_handler(): return self._handle_openid_request() app.before_request(self._check_session) def _handle_openid_request(self): return_url = flask.session['FLASK_FAS_OPENID_RETURN_URL'] cancel_url = flask.session['FLASK_FAS_OPENID_CANCEL_URL'] base_url = self.normalize_url(flask.request.base_url) oidconsumer = consumer.Consumer(flask.session, None) info = oidconsumer.complete(flask.request.values, base_url) display_identifier = info.getDisplayIdentifier() if info.status == consumer.FAILURE and display_identifier: return 'FAILURE. display_identifier: %s' % display_identifier elif info.status == consumer.CANCEL: if cancel_url: return flask.redirect(cancel_url) return 'OpenID request was cancelled' elif info.status == consumer.SUCCESS: sreg_resp = sreg.SRegResponse.fromSuccessResponse(info) pape_resp = pape.Response.fromSuccessResponse(info) teams_resp = teams.TeamsResponse.fromSuccessResponse(info) cla_resp = cla.CLAResponse.fromSuccessResponse(info) user = { 'fullname': '', 'username': '', 'email': '', 'timezone': '', 'cla_done': False, 'groups': [] } if not sreg_resp: # If we have no basic info, be gone with them! return flask.redirect(cancel_url) user['username'] = sreg_resp.get('nickname') user['fullname'] = sreg_resp.get('fullname') user['email'] = sreg_resp.get('email') user['timezone'] = sreg_resp.get('timezone') if cla_resp: user['cla_done'] = cla.CLA_URI_FEDORA_DONE in cla_resp.clas if teams_resp: user['groups'] = frozenset( teams_resp.teams ) # The groups do not contain the cla_ groups flask.session['FLASK_FAS_OPENID_USER'] = user flask.session.modified = True return flask.redirect(return_url) else: return 'Strange state: %s' % info.status def _check_session(self): if not 'FLASK_FAS_OPENID_USER' in flask.session or flask.session[ 'FLASK_FAS_OPENID_USER'] is None: flask.g.fas_user = None else: user = flask.session['FLASK_FAS_OPENID_USER'] # Add approved_memberships to provide backwards compatibility # New applications should only use g.fas_user.groups user['approved_memberships'] = [] for group in user['groups']: membership = dict() membership['name'] = group user['approved_memberships'].append(Bunch.fromDict(membership)) flask.g.fas_user = Bunch.fromDict(user) flask.g.fas_session_id = 0 def login(self, username=None, password=None, return_url=None, cancel_url=None, groups=['_FAS_ALL_GROUPS_']): """Tries to log in a user. Sets the user information on :attr:`flask.g.fas_user`. Will set 0 to :attr:`flask.g.fas_session_id, for compatibility with flask_fas. :arg username: Not used, but accepted for compatibility with the flask_fas module :arg password: Not used, but accepted for compatibility with the flask_fas module :arg return_url: The URL to forward the user to after login :arg groups: A string or a list of group the user should belong to to be authentified. :returns: True if the user was succesfully authenticated. :raises: Might raise an redirect to the OpenID endpoint """ if return_url is None: if 'next' in flask.request.args.values(): return_url = flask.request.args.values['next'] else: return_url = flask.request.url oidconsumer = consumer.Consumer(flask.session, None) try: request = oidconsumer.begin(self.app.config['FAS_OPENID_ENDPOINT']) except consumer.DiscoveryFailure, exc: # VERY strange, as this means it could not discover an OpenID endpoint at FAS_OPENID_ENDPOINT return 'discoveryfailure' if request is None: # Also very strange, as this means the discovered OpenID endpoint is no OpenID endpoint return 'no-request' if isinstance(groups, basestring): groups = [groups] request.addExtension( sreg.SRegRequest( required=['nickname', 'fullname', 'email', 'timezone'])) request.addExtension(pape.Request([])) request.addExtension(teams.TeamsRequest(requested=groups)) request.addExtension( cla.CLARequest(requested=[cla.CLA_URI_FEDORA_DONE])) trust_root = self.normalize_url(flask.request.url_root) return_to = trust_root + '_flask_fas_openid_handler/' flask.session['FLASK_FAS_OPENID_RETURN_URL'] = return_url flask.session['FLASK_FAS_OPENID_CANCEL_URL'] = cancel_url if request.shouldSendRedirect(): redirect_url = request.redirectURL(trust_root, return_to, False) return flask.redirect(redirect_url) else: return request.htmlMarkup(trust_root, return_to, form_tag_attrs={'id': 'openid_message'}, immediate=False)