예제 #1
0
def logout_client():
    """
    Client-initiated logout
    """
    client = Client.get(key=request.args['client_id'])
    if client is None:
        # No such client. Possible CSRF. Don't logout and don't send them back
        flash(logout_errormsg, 'danger')
        return redirect(url_for('index'))
    if client.trusted:
        # This is a trusted client. Does the referring domain match?
        clienthost = urlparse.urlsplit(client.redirect_uri).hostname
        if request.referrer:
            if clienthost != urlparse.urlsplit(request.referrer).hostname:
                # Doesn't. Don't logout and don't send back
                flash(logout_errormsg, 'danger')
                return redirect(url_for('index'))
        # else: no referrer? Either stripped out by browser or a proxy, or this is a direct link.
        # We can't do anything about that, so assume it's a legit case.
        #
        # If there is a next destination, is it in the same domain?
        if 'next' in request.args:
            if clienthost != urlparse.urlsplit(request.args['next']).hostname:
                # Doesn't. Assume CSRF and redirect to index without logout
                flash(logout_errormsg, 'danger')
                return redirect(url_for('index'))
        # All good. Log them out and send them back
        logout_internal()
        return redirect(get_next_url(external=True))
    else:
        # We know this client, but it's not trusted. Send back without logout.
        return redirect(get_next_url(external=True))
예제 #2
0
def _client_login_inner():
    if request.authorization is None:
        return Response(u"Client credentials required.", 401, {"WWW-Authenticate": 'Basic realm="Client credentials"'})
    client = Client.get(key=request.authorization.username)
    if client is None or not client.secret_is(request.authorization.password):
        return Response(u"Invalid client credentials.", 401, {"WWW-Authenticate": 'Basic realm="Client credentials"'})
    g.client = client
예제 #3
0
파일: login.py 프로젝트: tuxdna/lastuser
def logout_client():
    """
    Client-initiated logout
    """
    client = Client.get(key=request.args['client_id'])
    if client is None:
        # No such client. Possible CSRF. Don't logout and don't send them back
        flash(logout_errormsg, 'danger')
        return redirect(url_for('index'))
    if client.trusted:
        # This is a trusted client. Does the referring domain match?
        clienthost = urlparse.urlsplit(client.redirect_uri).hostname
        if request.referrer:
            if clienthost != urlparse.urlsplit(request.referrer).hostname:
                # Doesn't. Don't logout and don't send back
                flash(logout_errormsg, 'danger')
                return redirect(url_for('index'))
        # else: no referrer? Either stripped out by browser or a proxy, or this is a direct link.
        # We can't do anything about that, so assume it's a legit case.
        #
        # If there is a next destination, is it in the same domain?
        if 'next' in request.args:
            if clienthost != urlparse.urlsplit(request.args['next']).hostname:
                # Doesn't. Assume CSRF and redirect to index without logout
                flash(logout_errormsg, 'danger')
                return redirect(url_for('index'))
        # All good. Log them out and send them back
        logout_internal()
        return redirect(get_next_url(external=True))
    else:
        # We know this client, but it's not trusted. Send back without logout.
        return redirect(get_next_url(external=True))
예제 #4
0
def _client_login_inner():
    if request.authorization is None or not request.authorization.username:
        return Response(u"Client credentials required.", 401,
            {'WWW-Authenticate': 'Basic realm="Client credentials"'})
    client = Client.get(key=request.authorization.username)
    if client is None or not client.secret_is(request.authorization.password):
        return Response(u"Invalid client credentials.", 401,
            {'WWW-Authenticate': 'Basic realm="Client credentials"'})
    g.client = client
예제 #5
0
def login_beacon_iframe(client_id, login_url):
    client = Client.get(key=client_id)
    if client is None:
        abort(404)
    if not client.host_matches(login_url):
        abort(400)
    return render_template('login_beacon.html', client=client, login_url=login_url), 200, {
        'Expires': 'Fri, 01 Jan 1990 00:00:00 GMT',
        'Cache-Control': 'private, max-age=86400'
        }
예제 #6
0
def login_beacon_json(client_id):
    client = Client.get(key=client_id)
    if client is None:
        abort(404)
    if g.user:
        token = client.authtoken_for(g.user)
    else:
        token = None
    response = jsonify({
        'hastoken': True if token else False
        })
    response.headers['Expires'] = 'Fri, 01 Jan 1990 00:00:00 GMT'
    response.headers['Cache-Control'] = 'private, max-age=300'
    return response
예제 #7
0
def logout_client():
    """
    Client-initiated logout
    """
    client = Client.get(key=request.args['client_id'])
    if client is None or not request.referrer or not client.host_matches(request.referrer):
        # No referrer or such client, or request didn't come from the client website.
        # Possible CSRF. Don't logout and don't send them back
        flash(current_app.config.get('LOGOUT_UNAUTHORIZED_MESSAGE') or logout_errormsg, 'danger')
        return redirect(url_for('index'))

    # If there is a next destination, is it in the same domain as the client?
    if 'next' in request.args:
        if not client.host_matches(request.args['next']):
            # Host doesn't match. Assume CSRF and redirect to index without logout
            flash(current_app.config.get('LOGOUT_UNAUTHORIZED_MESSAGE') or logout_errormsg, 'danger')
            return redirect(url_for('index'))
    # All good. Log them out and send them back
    logout_internal()
    db.session.commit()
    return redirect(get_next_url(external=True))
예제 #8
0
파일: oauth.py 프로젝트: sindhus/lastuser
def verifyscope(scope, client):
    """
    Verify if requested scope is valid for this client. Scope must be a list.
    """
    internal_resources = []  # Names of internal resources
    external_resources = {}  # resource_object: [action_object, ...]
    full_client_access = []  # Clients linked to namespace:* scope

    for item in scope:
        if item == '*':
            # The '*' resource (full access) is only available to trusted clients
            if not client.trusted:
                raise ScopeException(_(u"Full access is only available to trusted clients"))
        elif item in resource_registry:
            if resource_registry[item]['trusted'] and not client.trusted:
                raise ScopeException(_(u"The resource {scope} is only available to trusted clients").format(scope=item))
            internal_resources.append(item)
        else:

            # Validation 0: Is this an internal wildcard resource?
            if item.endswith('/*'):
                found_internal = False
                wildcard_base = item[:-2]
                for key in resource_registry:
                    if key == wildcard_base or key.startswith(wildcard_base + '/'):
                        if resource_registry[key]['trusted'] and not client.trusted:
                            # Skip over trusted resources if the client is not trusted
                            continue
                        internal_resources.append(key)
                        found_internal = True
                if found_internal:
                    continue  # Continue to next item in scope, skipping the following

            # Further validation is only required for non-internal resources
            # Validation 1: namespace:resource/action is properly formatted
            if ':' not in item:
                raise ScopeException(_(u"No namespace specified for external resource ‘{scope}’ in scope").format(scope=item))
            itemparts = item.split(':')
            if len(itemparts) != 2:
                raise ScopeException(_(u"Too many ‘:’ characters in ‘{scope}’ in scope").format(scope=item))
            namespace, subitem = itemparts
            if '/' in subitem:
                parts = subitem.split('/')
                if len(parts) != 2:
                    raise ScopeException(_(u"Too many ‘/’ characters in ‘{scope}’ in scope").format(scope=item))
                resource_name, action_name = parts
            else:
                resource_name = subitem
                action_name = None
            if resource_name == '*' and not action_name:
                resource_client = Client.get(namespace=namespace)
                if resource_client:
                    if resource_client.owner == client.owner:
                        full_client_access.append(resource_client)
                    else:
                        raise ScopeException(
                            _(u"This application does not have access to all resources of app ‘{client}’").format(
                                client=resource_client.title))
                else:
                    raise ScopeException(_(u"Unknown resource namespace ‘{namespace}’ in scope").format(
                        namespace=namespace))
            else:
                resource = Resource.get(name=resource_name, namespace=namespace)

                # Validation 2: Resource exists and client has access to it
                if not resource:
                    raise ScopeException(_(u"Unknown resource ‘{resource}’ under namespace ‘{namespace}’ in scope").format(resource=resource_name, namespace=namespace))
                if resource.restricted and resource.client.owner != client.owner:
                    raise ScopeException(
                        _(u"This application does not have access to resource ‘{resource}’ in scope").format(resource=resource_name))

                # Validation 3: Action is valid
                if action_name:
                    action = resource.get_action(action_name)
                    if not action:
                        raise ScopeException(_(u"Unknown action ‘{action}’ on resource ‘{resource}’ under namespace ‘{namespace}’").format(
                            action=action_name, resource=resource_name, namespace=namespace))
                    external_resources.setdefault(resource, []).append(action)
                else:
                    external_resources.setdefault(resource, [])

    internal_resources.sort()
    return internal_resources, external_resources, full_client_access
예제 #9
0
def verifyscope(scope, client):
    """
    Verify if requested scope is valid for this client. Scope must be a list.
    """
    internal_resources = []  # Names of internal resources
    external_resources = {}  # resource_object: [action_object, ...]
    full_client_access = []  # Clients linked to namespace:* scope

    for item in scope:
        if item == '*':
            # The '*' resource (full access) is only available to trusted clients
            if not client.trusted:
                raise ScopeException(_(u"Full access is only available to trusted clients"))
        elif item in resource_registry:
            if resource_registry[item]['trusted'] and not client.trusted:
                raise ScopeException(_(u"The resource {scope} is only available to trusted clients").format(scope=item))
            internal_resources.append(item)
        else:

            # Validation 0: Is this an internal wildcard resource?
            if item.endswith('/*'):
                found_internal = False
                wildcard_base = item[:-2]
                for key in resource_registry:
                    if key == wildcard_base or key.startswith(wildcard_base + '/'):
                        if resource_registry[key]['trusted'] and not client.trusted:
                            # Skip over trusted resources if the client is not trusted
                            continue
                        internal_resources.append(key)
                        found_internal = True
                if found_internal:
                    continue  # Continue to next item in scope, skipping the following

            # Further validation is only required for non-internal resources
            # Validation 1: namespace:resource/action is properly formatted
            if ':' not in item:
                raise ScopeException(_(u"No namespace specified for external resource ‘{scope}’ in scope").format(scope=item))
            itemparts = item.split(':')
            if len(itemparts) != 2:
                raise ScopeException(_(u"Too many ‘:’ characters in ‘{scope}’ in scope").format(scope=item))
            namespace, subitem = itemparts
            if '/' in subitem:
                parts = subitem.split('/')
                if len(parts) != 2:
                    raise ScopeException(_(u"Too many ‘/’ characters in ‘{scope}’ in scope").format(scope=item))
                resource_name, action_name = parts
            else:
                resource_name = subitem
                action_name = None
            if resource_name == '*' and not action_name:
                resource_client = Client.get(namespace=namespace)
                if resource_client:
                    if resource_client.owner == client.owner:
                        full_client_access.append(resource_client)
                    else:
                        raise ScopeException(
                            _(u"This application does not have access to all resources of app ‘{client}’").format(
                                client=resource_client.title))
                else:
                    raise ScopeException(_(u"Unknown resource namespace ‘{namespace}’ in scope").format(
                        namespace=namespace))
            else:
                resource = Resource.get(name=resource_name, namespace=namespace)

                # Validation 2: Resource exists and client has access to it
                if not resource:
                    raise ScopeException(_(u"Unknown resource ‘{resource}’ under namespace ‘{namespace}’ in scope").format(resource=resource_name, namespace=namespace))
                if resource.restricted and resource.client.owner != client.owner:
                    raise ScopeException(
                        _(u"This application does not have access to resource ‘{resource}’ in scope").format(resource=resource_name))

                # Validation 3: Action is valid
                if action_name:
                    action = resource.get_action(action_name)
                    if not action:
                        raise ScopeException(_(u"Unknown action ‘{action}’ on resource ‘{resource}’ under namespace ‘{namespace}’").format(
                            action=action_name, resource=resource_name, namespace=namespace))
                    external_resources.setdefault(resource, []).append(action)
                else:
                    external_resources.setdefault(resource, [])

    internal_resources.sort()
    return internal_resources, external_resources, full_client_access