示例#1
0
def portier_login(request):
    """Helper to redirect client towards Portier login form."""
    nonce = persist_nonce(request)
    form_url = '{broker_uri}/auth?{query_args}'
    broker_uri = portier_conf(request, 'broker_uri')

    query_args = urlencode({
        'login_hint':
        request.validated['email'],
        'scope':
        portier_conf(request, 'requested_scope'),
        'nonce':
        nonce,
        'response_type':
        'id_token',
        'response_mode':
        'form_post',
        # Get the data from the config because the request might only
        # have local network information and not the public facing ones.
        'client_id':
        '{scheme}://{host}'.format(
            scheme=request.registry.settings['http_scheme'],
            host=request.registry.settings['http_host']),
        'redirect_uri':
        request.route_url(verify.name),
    })

    location = form_url.format(broker_uri=broker_uri, query_args=query_args)
    return httpexceptions.HTTPFound(location=location)
示例#2
0
def authorized_redirect(req, **kwargs):
    authorized = aslist(portier_conf(req, 'webapp.authorized_domains'))
    if 'redirect' not in req.validated:
        return True
    domain = urlparse(req.validated['redirect']).netloc

    if not any((fnmatch(domain, auth) for auth in authorized)):
        req.errors.add('querystring', 'redirect',
                       'redirect URL is not authorized')
def portier_ping(request):
    """Verify if the portier server is ready."""
    server_url = portier_conf(request, 'broker_uri')

    portier = None

    if server_url is not None:
        portier = False
        try:
            conf_url = urljoin(server_url, '/.well-known/openid-configuration')
            timeout = float(portier_conf(request, 'heartbeat_timeout_seconds'))
            r = requests.get(conf_url, timeout=timeout)
            r.raise_for_status()
            portier = True
        except requests.exceptions.HTTPError:
            pass

    return portier
示例#4
0
def portier_verify(request):
    """Helper to redirect client towards Portier login form."""
    broker_uri = portier_conf(request, 'broker_uri')
    token = request.validated['body']['id_token']
    # Get the data from the config because the request might only
    # have local network information and not the public facing ones.
    audience = '{scheme}://{host}'.format(
        scheme=request.registry.settings['http_scheme'],
        host=request.registry.settings['http_host'])

    try:
        email, stored_redirect = get_verified_email(
            broker_url=broker_uri,
            token=token,
            audience=audience,
            issuer=broker_uri,
            cache=request.registry.cache)
    except ValueError as exc:
        error_details = 'Portier token validation failed: %s' % exc
        return http_error(httpexceptions.HTTPBadRequest(),
                          errno=ERRORS.INVALID_AUTH_TOKEN,
                          error='Invalid Auth Token',
                          message=error_details)

    # Generate a random token
    user_token = codecs.encode(os.urandom(32), 'hex').decode('utf-8')

    # Encrypt the email with the token
    encrypted_email = encrypt(email, user_token)

    # Generate a user ID from the token
    hmac_secret = request.registry.settings['userid_hmac_secret']
    userID = utils.hmac_digest(hmac_secret, user_token)

    # Store the encrypted user ID with the token
    session_ttl = portier_conf(request, 'session_ttl_seconds')
    request.registry.cache.set('portier:' + userID, encrypted_email,
                               session_ttl)

    location = '%s%s' % (stored_redirect, user_token)
    return httpexceptions.HTTPFound(location=location)
示例#5
0
def persist_nonce(request):
    """Persist arbitrary string in cache.
    It will be matched when the user returns from the OAuth server login
    page.
    """
    nonce = uuid.uuid4().hex
    redirect_url = request.validated['redirect']
    expiration = float(portier_conf(request, 'cache_ttl_seconds'))

    cache = request.registry.cache
    cache.set("portier:nonce:%s" % nonce, redirect_url, expiration)

    return nonce