Esempio n. 1
0
def handler(event, _context):
    """Handle the signout event."""
    request = event['Records'][0]['cf']['request']
    domain_name = request['headers']['host'][0]['value']
    extracted = extract_and_parse_cookies(
        request['headers'],
        CONFIG.get('client_id')
    )

    if not extracted.get('idToken'):
        return {
            'body': "Bad Request",
            'status': "400",
            'statusDescription': "Bad Request",
            'headers': CONFIG.get('cloud_front_headers')
        }

    tokens = {
        'id_token': extracted.get('idToken'),
        'access_token': extracted.get('accessToken'),
        'refresh_token': extracted.get('refreshToken'),
    }
    query_string = {
        'logout_uri': 'https://%s%s' % (domain_name, CONFIG.get('redirect_path_sign_out')),
        'client_id': CONFIG.get('client_id')
    }

    headers = {
        # Redirect the user to logout
        'location': [
            {
                'key': 'location',
                'value': 'https://%s/logout?%s' % (
                    CONFIG.get('cognito_auth_domain'),
                    urlencode(query_string)
                )
            }
        ],
        'set-cookie': get_cookie_headers(
            CONFIG.get("client_id"),
            CONFIG.get("oauth_scopes"),
            tokens,
            domain_name,
            CONFIG.get('cookie_settings'),
            # Make sure we expire all the tokens during retrieval
            expire_all_tokens=True
        )
    }
    headers.update(CONFIG.get('cloud_front_headers'))

    return {
        'status': '307',
        'statusDescription': 'Temporary Redirect',
        'headers': headers
    }
Esempio n. 2
0
def handler(event, _context):
    """Handle the signout event."""
    request = event["Records"][0]["cf"]["request"]
    domain_name = request["headers"]["host"][0]["value"]
    extracted = extract_and_parse_cookies(request["headers"],
                                          CONFIG.get("client_id"))

    if not extracted.get("idToken"):
        return {
            "body": "Bad Request",
            "status": "400",
            "statusDescription": "Bad Request",
            "headers": CONFIG.get("cloud_front_headers"),
        }

    tokens = {
        "id_token": extracted.get("idToken"),
        "access_token": extracted.get("accessToken"),
        "refresh_token": extracted.get("refreshToken"),
    }
    query_string = {
        "logout_uri":
        "https://%s%s" % (domain_name, CONFIG.get("redirect_path_sign_out")),
        "client_id":
        CONFIG.get("client_id"),
    }

    headers = {
        # Redirect the user to logout
        "location": [{
            "key":
            "location",
            "value":
            "https://%s/logout?%s" %
            (CONFIG.get("cognito_auth_domain"), urlencode(query_string)),
        }],
        "set-cookie":
        get_cookie_headers(
            CONFIG.get("client_id"),
            CONFIG.get("oauth_scopes"),
            tokens,
            domain_name,
            CONFIG.get("cookie_settings"),
            # Make sure we expire all the tokens during retrieval
            expire_all_tokens=True,
        ),
    }
    headers.update(CONFIG.get("cloud_front_headers"))

    return {
        "status": "307",
        "statusDescription": "Temporary Redirect",
        "headers": headers,
    }
Esempio n. 3
0
def handler(event, _context):
    """Handle the authorization refresh.

    Keyword Args:
        event: The Lambda Event
    """
    request = event['Records'][0]['cf']['request']
    domain_name = request['headers']['host'][0]['value']
    redirected_from_uri = 'https://%s' % domain_name

    try:
        parsed_qs = parse_qs(request.get('querystring'))
        requested_uri = parsed_qs.get('requestedUri')[0]
        current_nonce = parsed_qs.get('nonce')[0]
        # Add the requested uri path to the main
        redirected_from_uri += requested_uri or ""

        cookies = extract_and_parse_cookies(request.get('headers'),
                                            CONFIG.get('client_id'))

        tokens = {
            'id_token': cookies.get('idToken'),
            'access_token': cookies.get('accessToken'),
            'refresh_token': cookies.get('refreshToken')
        }

        validate_refresh_request(current_nonce, cookies.get('nonce'), tokens)

        try:
            # Request new tokens based on the refresh_token
            body = {
                'grant_type': 'refresh_token',
                'client_id': CONFIG.get('client_id'),
                'refresh_token': tokens.get('refresh_token')
            }
            res = http_post_with_retry(
                ('https://%s/oauth2/token' %
                 CONFIG.get('cognito_auth_domain')), body,
                {'Content-Type': 'application/x-www-form-urlencoded'})
            tokens['id_token'] = res.get('id_token')
            tokens['access_token'] = res.get('access_token')
        except Exception as err:  # pylint: disable=broad-except
            LOGGER.error(err)
            # Otherwise clear the refresh token
            tokens['refresh_token'] = ""

        headers = {
            'location': [{
                'key': 'location',
                'value': redirected_from_uri
            }],
            'set-cookie':
            get_cookie_headers(CONFIG.get('client_id'),
                               CONFIG.get('oauth_scopes'), tokens, domain_name,
                               CONFIG.get('cookie_settings'))
        }
        headers.update(CONFIG.get('cloud_front_headers'))

        # Redirect the user back to their requested uri
        # with new tokens at hand
        return {
            'status': '307',
            'statusDescription': 'Temporary Redirect',
            'headers': headers
        }

    # Send a basic html error response and inform the user
    # why refresh was unsuccessful
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.info(err)
        LOGGER.info(traceback.print_exc())

        headers = {
            "content-type": [{
                "key": "Content-Type",
                "value": "text/html; charset=UTF-8"
            }]
        }
        headers.update(CONFIG.get('cloud_front_headers'))

        return {
            'body': create_error_html("Bad Request", err, redirected_from_uri),
            'status': '400',
            'headers': headers
        }
Esempio n. 4
0
def handler(event, _context):
    """Handle the request passed in.

    Keyword Args:
        event (Dict[str, Any]): The Lambda Event
    """
    request = event['Records'][0]['cf']['request']
    domain_name = request['headers']['host'][0]['value']
    querystring = request.get('querystring')
    request_query_string = ("?%s" % querystring) if querystring else ""
    requested_uri = '%s%s' % (request['uri'], request_query_string)
    nonce = generate_nonce()

    try:
        # Extract the cookies received from Cognito
        extracted = extract_and_parse_cookies(request['headers'],
                                              CONFIG['client_id'])
        token_user_name = extracted.get('tokenUserName')
        id_token = extracted.get('idToken')
        refresh_token = extracted.get('refreshToken')

        # If the token user name or id token are missing then we need
        # new credentials
        if not token_user_name or not id_token:
            msg = "No valid credentials present in cookies"
            LOGGER.error(msg)
            raise Exception(msg)

        # Get the expiration date from the id token.
        decoded_token = decode_token(id_token)
        expiration = decoded_token.get('exp')
        exp_date = datetime.datetime.fromtimestamp(expiration)
        now = datetime.datetime.now()

        # If we have a refresh token and the expiration date has passed
        # then forward the user to the refresh agent
        if now > exp_date and refresh_token:
            headers = {
                # Redirect the user to the refresh agent
                'location': [{
                    'key':
                    'location',
                    'value':
                    'https://%s%s?%s' %
                    (domain_name, CONFIG.get('redirect_path_auth_refresh'),
                     urlencode({
                         'requestedUri': requested_uri,
                         'nonce': nonce
                     }))
                }],
                'set-cookie': [
                    # Set the Nonce Cookie
                    {
                        'key':
                        'set-cookie',
                        'value':
                        'spa-auth-edge-nonce=%s; %s' %
                        (quote_plus(nonce),
                         CONFIG.get('cookie_settings').get('nonce'))
                    }
                ]
            }
            # Add all CloudFrontHeaders
            headers.update(CONFIG.get('cloud_front_headers'))
            return {
                'status': '307',
                'statusDescription': 'Temporary Redirect',
                'headers': headers
            }

        # Validate the token information against the Cognito JWKS
        validate_jwt(id_token, CONFIG.get('token_jwks_uri'),
                     CONFIG.get('token_issuer'), CONFIG.get('client_id'))

        return request
    # We need new authorization. Get the user over to Cognito
    except Exception:  # noqa pylint: disable=broad-except
        pkce, pkce_hash = generate_pkce_verifier()
        payload = {
            'redirect_uri':
            'https://%s%s' % (domain_name, CONFIG['redirect_path_sign_in']),
            'response_type':
            'code',
            'client_id':
            CONFIG["client_id"],
            'state':
            base64.urlsafe_b64encode(
                bytes(
                    json.dumps({
                        "nonce": nonce,
                        "requestedUri": requested_uri
                    }).encode())),
            'scope':
            " ".join(CONFIG['oauth_scopes']),
            'code_challenge_method':
            "S256",
            'code_challenge':
            pkce_hash
        }
        login_query_string = urlencode(payload, quote_via=quote_plus)
        headers = CONFIG.get('cloud_front_headers')
        headers['location'] = [{
            'key':
            'location',
            'value':
            'https://%s/oauth2/authorize?%s' %
            (CONFIG['cognito_auth_domain'], login_query_string)
        }]
        headers['set-cookie'] = [
            # Set Nonce Cookie
            {
                'key':
                'set-cookie',
                'value':
                'spa-auth-edge-nonce=%s; %s' %
                (quote_plus(nonce), CONFIG.get('cookie_settings',
                                               {}).get('nonce'))
            },
            # Set PKCE Cookie
            {
                'key':
                'set-cookie',
                'value':
                'spa-auth-edge-pkce=%s; %s' %
                (quote_plus(pkce), CONFIG.get('cookie_settings',
                                              {}).get('nonce'))
            },
        ]

        # Redirect user to the Cognito Login
        return {
            'status': '307',
            'statusDescription': 'Temporary Redirect',
            'headers': headers
        }
Esempio n. 5
0
def handler(event, _context):
    """Handle the authorization parsing.

    Keyword Args:
        event (Any): The Lambda Event
    """
    request = event['Records'][0]['cf']['request']
    domain_name = request['headers']['host'][0]['value']
    redirected_from_uri = 'https://%s' % domain_name

    # Attempt to parse the request and retrieve authorization
    # tokens to integrate with our header cookies
    try:
        qsp = parse_qs(request.get('querystring'))
        # Authorization code given by Cognito
        code = qsp.get('code')
        # The requested URI and current nonce information
        state = json.loads(
            base64.urlsafe_b64decode(qsp.get('state')[0]).decode())

        # Missing required components
        if not code or not state:
            msg = 'Invalid query string. ' + \
                  'Your query string should include parameters "state" and "code"'
            LOGGER.info(msg)
            raise Exception(msg)

        current_nonce = state.get('nonce')
        requested_uri = state.get('requestedUri')
        redirected_from_uri = requested_uri or "/"
        # Get all the cookies from the headers
        cookies = extract_and_parse_cookies(request.get('headers'),
                                            CONFIG.get('client_id'))
        # Retrieve the original nonce value as well as our PKCE code
        original_nonce = cookies.get('nonce')
        pkce = cookies.get('pkce')

        # If we're missing one of the nonces, or they don't match, cause an error
        if not current_nonce or not original_nonce or current_nonce != original_nonce:
            # No original nonce? CSRF violation
            if not original_nonce:
                msg = "Your browser didn't send the nonce cookie along, " + \
                      "but it is required for security (prevent CSRF)"
                LOGGER.error(msg)
                raise Exception(msg)
            # Nonce's don't match
            msg = "Nonce Mismatch"
            LOGGER.error(msg)
            raise Exception(msg)

        payload = {
            'grant_type':
            'authorization_code',
            'client_id':
            CONFIG.get('client_id'),
            'redirect_uri':
            'https://%s%s' %
            (domain_name, CONFIG.get('redirect_path_sign_in')),
            'code':
            code[0],
            'code_verifier':
            pkce
        }

        # Request tokens from our Cognito Authorization Domain
        tokens = http_post_with_retry(
            ('https://%s/oauth2/token' % CONFIG.get('cognito_auth_domain')),
            payload, {"Content-Type": "application/x-www-form-urlencoded"})

        if not tokens:
            raise Exception('Was not able to obtain tokens from Cognito')

        headers = {
            'location': [{
                'key': 'location',
                'value': redirected_from_uri
            }],
            'set-cookie':
            get_cookie_headers(CONFIG.get("client_id"),
                               CONFIG.get("oauth_scopes"), tokens, domain_name,
                               CONFIG.get('cookie_settings'))
        }
        headers.update(CONFIG.get('cloud_front_headers'))
        # Redirect user to the originally requested uri with the
        # token header cookies
        response = {
            'status': '307',
            'statusDescription': 'Temporary Redirect',
            'headers': headers
        }
        return response
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error(err)
        LOGGER.error(traceback.print_exc())

        headers = CONFIG.get('cloud_front_headers')
        headers['content-type'] = [{
            'key': 'Content-Type',
            'value': 'text/html; charset=UTF-8'
        }]

        # Inform user of bad request and reason
        return {
            'body': create_error_html("Bad Request", err, redirected_from_uri),
            'status': '400',
            'headers': headers
        }
Esempio n. 6
0
def handler(event, _context):
    """Handle the authorization parsing.

    Args:
        event (Any): The Lambda Event.
        _context (Any): Lambda context object.

    """
    request = event["Records"][0]["cf"]["request"]
    domain_name = request["headers"]["host"][0]["value"]
    redirected_from_uri = "https://%s" % domain_name
    id_token = None

    # Attempt to parse the request and retrieve authorization
    # tokens to integrate with our header cookies
    try:
        # Get all the cookies from the headers
        cookies = extract_and_parse_cookies(request.get("headers"),
                                            CONFIG["client_id"])
        id_token = cookies["id_token"]
        code, pkce, requested_uri = validate_querystring_and_cookies(
            request, cookies)
        redirected_from_uri += requested_uri

        # Request tokens from our Cognito Authorization Domain
        body = {
            "grant_type":
            "authorization_code",
            "client_id":
            CONFIG["client_id"],
            "redirect_uri":
            "https://%s%s" %
            (domain_name, CONFIG.get("redirect_path_sign_in")),
            "code":
            code[0],
            "code_verifier":
            pkce,
        }
        tokens = http_post_with_retry(
            COGNITO_TOKEN_ENDPOINT,
            body,
            {"Content-Type": "application/x-www-form-urlencoded"},
        )

        if not tokens:
            raise Exception("Was not able to obtain tokens from Cognito")

        # Validate the token information against the Cognito JWKS
        # (and ensure group membership, if applicable)
        validate_and_check_id_token(
            tokens["id_token"],
            CONFIG["token_jwks_uri"],
            CONFIG["token_issuer"],
            CONFIG["client_id"],
            CONFIG.get("required_group"),
        )

        # Redirect user to the originally requested uri with the
        # token header cookies
        response = {
            "status": "307",
            "statusDescription": "Temporary Redirect",
            "headers": {
                "location": [{
                    "key": "location",
                    "value": redirected_from_uri
                }],
                "set-cookie":
                generate_cookie_headers(
                    "new_tokens",
                    CONFIG.get("client_id"),
                    CONFIG.get("oauth_scopes"),
                    tokens,
                    domain_name,
                    CONFIG.get("cookie_settings"),
                ),
                **CONFIG.get("cloud_front_headers", {}),
            },
        }
        return response
    except Exception as err:  # pylint: disable=broad-except
        if id_token:
            # ID token found; checking if it is valid
            try:
                validate_and_check_id_token(
                    id_token,
                    CONFIG["token_jwks_uri"],
                    CONFIG["token_issuer"],
                    CONFIG["client_id"],
                    CONFIG.get("required_group"),
                )
                # Token is valid; return user to where they came from
                return {
                    "status": "307",
                    "statusDescription": "Temporary Redirect",
                    "headers": {
                        "location": [{
                            "key": "location",
                            "value": redirected_from_uri
                        }],
                        **CONFIG.get("cloud_front_headers", {}),
                    },
                }
            except Exception as err:  # pylint: disable=broad-except
                LOGGER.debug("Id token not valid")
                LOGGER.debug(err)

        if isinstance(err, RequiresConfirmationError):
            html_params = [
                "Confirm sign-in",
                "We need your confirmation to sign you (%s)" % str(err),
                redirected_from_uri,
                "Confirm",
            ]
        elif isinstance(err, MissingRequiredGroupError):
            html_params = [
                "Not Authorized",
                "Your user is not authorized for this site. Please contact the admin.",
                redirected_from_uri,
                "Try Again",
            ]
        else:
            html_params = [
                "Sign-in issue",
                "Sign-in unsuccessful because of a technical problem: %s" %
                str(err),
                redirected_from_uri,
                "Try Again",
            ]

        # Inform user of bad request and reason
        return {
            "body": create_error_html(*html_params),
            "status": "200",
            "headers": {
                **CONFIG.get("cloud_front_headers", {}),
                "content-type": [{
                    "key": "Content-Type",
                    "value": "text/html; charset=UTF-8"
                }],
            },
        }
Esempio n. 7
0
def handler(event, _context):
    """Handle the request passed in.

    Args:
        event (Dict[str, Any]): The Lambda Event.
        _context (Any): Lambda context object.

    """
    request = event["Records"][0]["cf"]["request"]
    domain_name = request["headers"]["host"][0]["value"]
    querystring = request.get("querystring")
    request_query_string = ("?%s" % querystring) if querystring else ""
    requested_uri = "%s%s" % (request["uri"], request_query_string)

    try:
        # Extract the cookies received from Cognito
        extracted = extract_and_parse_cookies(request["headers"],
                                              CONFIG["client_id"])
        token_user_name = extracted["token_user_name"]
        id_token = extracted["id_token"]
        refresh_token = extracted["refresh_token"]

        # If the token user name or id token are missing then we need
        # new credentials
        if not token_user_name or not id_token:
            msg = "No valid credentials present in cookies"
            LOGGER.error(msg)
            raise Exception(msg)

        # Get the expiration date from the id token.
        decoded_token = decode_token(id_token)
        expiration = decoded_token.get("exp")
        exp_date = datetime.datetime.fromtimestamp(expiration)
        now = datetime.datetime.now()

        # If we have a refresh token and the expiration date has passed
        # then forward the user to the refresh agent
        if now > (exp_date - datetime.timedelta(minutes=10)) and refresh_token:
            nonce = generate_nonce()
            response = {
                "status": "307",
                "statusDescription": "Temporary Redirect",
                "headers": {
                    # Redirect the user to the refresh agent
                    "location": [{
                        "key":
                        "location",
                        "value":
                        "https://%s%s?%s" % (
                            domain_name,
                            CONFIG.get("redirect_path_auth_refresh"),
                            urlencode({
                                "requestedUri": requested_uri,
                                "nonce": nonce
                            }),
                        ),
                    }],
                    "set-cookie": [
                        # Set the Nonce Cookie
                        {
                            "key":
                            "set-cookie",
                            "value":
                            "spa-auth-edge-nonce=%s; %s" % (
                                quote_plus(nonce),
                                CONFIG.get("cookie_settings").get("nonce"),
                            ),
                        },
                        {
                            "key":
                            "set-cookie",
                            "value":
                            "spa-auth-edge-nonce-hmac=%s; %s" % (
                                quote_plus(
                                    sign(nonce,
                                         CONFIG["nonce_signing_secret"])),
                                CONFIG.get("cookie_settings").get("nonce"),
                            ),
                        },
                    ],
                    **CONFIG.get("cloud_front_headers", {}),
                },
            }
            return response

        # Validate the token information against the Cognito JWKS
        validate_jwt(
            id_token,
            CONFIG["token_jwks_uri"],
            CONFIG["token_issuer"],
            CONFIG["client_id"],
        )

        return request
    except Exception:  # noqa pylint: disable=broad-except
        # We need new authorization. Get the user over to Cognito
        nonce = generate_nonce()
        state = {
            "nonce": nonce,
            "nonceHmac": sign(nonce, CONFIG["nonce_signing_secret"]),
            **generate_pkce_verifier(),
        }
        login_query_string = urlencode(
            {
                "redirect_uri":
                "https://%s%s" %
                (domain_name, CONFIG["redirect_path_sign_in"]),
                "response_type":
                "code",
                "client_id":
                CONFIG["client_id"],
                "state":
                base64.urlsafe_b64encode(
                    bytes(
                        json.dumps({
                            "nonce": state["nonce"],
                            "requestedUri": requested_uri
                        }).encode())),
                "scope":
                " ".join(CONFIG["oauth_scopes"]),
                "code_challenge_method":
                "S256",
                "code_challenge":
                state["pkceHash"],
            },
            quote_via=quote_plus,
        )
        # Redirect user to the Cognito Login
        response = {
            "status": "307",
            "statusDescription": "Temporary Redirect",
            "headers": {
                "location": [{
                    "key":
                    "location",
                    "value":
                    "https://%s/oauth2/authorize?%s" %
                    (CONFIG["cognito_auth_domain"], login_query_string),
                }],
                "set-cookie": [
                    {
                        "key":
                        "set-cookie",
                        "value":
                        "spa-auth-edge-nonce=%s; %s" % (
                            quote_plus(state["nonce"]),
                            CONFIG.get("cookie_settings", {}).get("nonce"),
                        ),
                    },
                    {
                        "key":
                        "set-cookie",
                        "value":
                        "spa-auth-edge-nonce-hmac=%s; %s" % (
                            quote_plus(state["nonceHmac"]),
                            CONFIG.get("cookie_settings", {}).get("nonce"),
                        ),
                    },
                    {
                        "key":
                        "set-cookie",
                        "value":
                        "spa-auth-edge-pkce=%s; %s" % (
                            quote_plus(state["pkce"]),
                            CONFIG.get("cookie_settings", {}).get("nonce"),
                        ),
                    },
                ],
                **CONFIG.get("cloud_front_headers", {}),
            },
        }
        return response
Esempio n. 8
0
def handler(event, _context):
    """Handle the authorization parsing.

    Args:
        event (Any): The Lambda Event.
        _context (Any): Lambda context object.

    """
    request = event["Records"][0]["cf"]["request"]
    domain_name = request["headers"]["host"][0]["value"]
    redirected_from_uri = "https://%s" % domain_name

    # Attempt to parse the request and retrieve authorization
    # tokens to integrate with our header cookies
    try:
        qsp = parse_qs(request.get("querystring"))
        # Authorization code given by Cognito
        code = qsp.get("code")
        # The requested URI and current nonce information
        state = json.loads(base64.urlsafe_b64decode(qsp.get("state")[0]).decode())

        # Missing required components
        if not code or not state:
            msg = (
                "Invalid query string. "
                'Your query string should include parameters "state" and "code"'
            )
            LOGGER.info(msg)
            raise Exception(msg)

        current_nonce = state.get("nonce")
        requested_uri = state.get("requestedUri")
        redirected_from_uri = requested_uri or "/"
        # Get all the cookies from the headers
        cookies = extract_and_parse_cookies(
            request.get("headers"), CONFIG.get("client_id")
        )
        # Retrieve the original nonce value as well as our PKCE code
        original_nonce = cookies.get("nonce")
        pkce = cookies.get("pkce")

        # If we're missing one of the nonces, or they don't match, cause an error
        if not current_nonce or not original_nonce or current_nonce != original_nonce:
            # No original nonce? CSRF violation
            if not original_nonce:
                msg = (
                    "Your browser didn't send the nonce cookie along, "
                    "but it is required for security (prevent CSRF)"
                )
                LOGGER.error(msg)
                raise Exception(msg)
            # Nonce's don't match
            msg = "Nonce Mismatch"
            LOGGER.error(msg)
            raise Exception(msg)

        payload = {
            "grant_type": "authorization_code",
            "client_id": CONFIG.get("client_id"),
            "redirect_uri": "https://%s%s"
            % (domain_name, CONFIG.get("redirect_path_sign_in")),
            "code": code[0],
            "code_verifier": pkce,
        }

        # Request tokens from our Cognito Authorization Domain
        tokens = http_post_with_retry(
            ("https://%s/oauth2/token" % CONFIG.get("cognito_auth_domain")),
            payload,
            {"Content-Type": "application/x-www-form-urlencoded"},
        )

        if not tokens:
            raise Exception("Was not able to obtain tokens from Cognito")

        headers = {
            "location": [{"key": "location", "value": redirected_from_uri}],
            "set-cookie": get_cookie_headers(
                CONFIG.get("client_id"),
                CONFIG.get("oauth_scopes"),
                tokens,
                domain_name,
                CONFIG.get("cookie_settings"),
            ),
        }
        headers.update(CONFIG.get("cloud_front_headers"))
        # Redirect user to the originally requested uri with the
        # token header cookies
        response = {
            "status": "307",
            "statusDescription": "Temporary Redirect",
            "headers": headers,
        }
        return response
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.error(err)
        LOGGER.error(traceback.print_exc())

        headers = CONFIG.get("cloud_front_headers")
        headers["content-type"] = [
            {"key": "Content-Type", "value": "text/html; charset=UTF-8"}
        ]

        # Inform user of bad request and reason
        return {
            "body": create_error_html("Bad Request", err, redirected_from_uri),
            "status": "400",
            "headers": headers,
        }
Esempio n. 9
0
def handler(event, _context):
    """Handle the signout event."""
    request = event["Records"][0]["cf"]["request"]
    domain_name = request["headers"]["host"][0]["value"]
    extracted = extract_and_parse_cookies(request["headers"],
                                          CONFIG["client_id"])

    if not extracted["id_token"]:
        response = {
            "body":
            create_error_html(
                "Signed out",
                "You are already signed out",
                "https://%s%s" %
                (domain_name, CONFIG["redirect_path_sign_out"]),
                "Proceed",
            ),
            "status":
            "200",
            "headers": {
                "content-type": [{
                    "key": "Content-Type",
                    "value": "text/html; charset=UTF-8"
                }],
                **CONFIG.get("cloud_front_headers", {}),
            },
        }
        return response

    tokens = {
        "id_token": extracted["id_token"],
        "access_token": extracted["access_token"],
        "refresh_token": extracted["refresh_token"],
    }
    query_string = {
        "logout_uri":
        "https://%s%s" % (domain_name, CONFIG["redirect_path_sign_out"]),
        "client_id":
        CONFIG["client_id"],
    }

    response = {
        "status": "307",
        "statusDescription": "Temporary Redirect",
        "headers": {
            # Redirect the user to logout
            "location": [{
                "key":
                "location",
                "value":
                "https://%s/logout?%s" %
                (CONFIG.get("cognito_auth_domain"), urlencode(query_string)),
            }],
            "set-cookie":
            generate_cookie_headers(
                "sign_out",
                CONFIG.get("client_id"),
                CONFIG.get("oauth_scopes"),
                tokens,
                domain_name,
                CONFIG.get("cookie_settings"),
            ),
            **CONFIG.get("cloud_front_headers", {}),
        },
    }
    return response
Esempio n. 10
0
def handler(event, _context):
    """Handle the authorization refresh.

    Args:
        event: The Lambda Event.
        _context (Any): Lambda context object.

    """
    request = event["Records"][0]["cf"]["request"]
    domain_name = request["headers"]["host"][0]["value"]
    redirected_from_uri = "https://%s" % domain_name

    try:
        parsed_qs = parse_qs(request.get("querystring"))
        requested_uri = parsed_qs.get("requestedUri")[0]
        current_nonce = parsed_qs.get("nonce")[0]
        # Add the requested uri path to the main
        redirected_from_uri += requested_uri or ""

        cookies = extract_and_parse_cookies(
            request.get("headers"), CONFIG.get("client_id")
        )

        tokens = {
            "id_token": cookies.get("idToken"),
            "access_token": cookies.get("accessToken"),
            "refresh_token": cookies.get("refreshToken"),
        }

        validate_refresh_request(current_nonce, cookies.get("nonce"), tokens)

        try:
            # Request new tokens based on the refresh_token
            body = {
                "grant_type": "refresh_token",
                "client_id": CONFIG.get("client_id"),
                "refresh_token": tokens.get("refresh_token"),
            }
            res = http_post_with_retry(
                ("https://%s/oauth2/token" % CONFIG.get("cognito_auth_domain")),
                body,
                {"Content-Type": "application/x-www-form-urlencoded"},
            )
            tokens["id_token"] = res.get("id_token")
            tokens["access_token"] = res.get("access_token")
        except Exception as err:  # pylint: disable=broad-except
            LOGGER.error(err)
            # Otherwise clear the refresh token
            tokens["refresh_token"] = ""

        headers = {
            "location": [{"key": "location", "value": redirected_from_uri}],
            "set-cookie": get_cookie_headers(
                CONFIG.get("client_id"),
                CONFIG.get("oauth_scopes"),
                tokens,
                domain_name,
                CONFIG.get("cookie_settings"),
            ),
        }
        headers.update(CONFIG.get("cloud_front_headers"))

        # Redirect the user back to their requested uri
        # with new tokens at hand
        return {
            "status": "307",
            "statusDescription": "Temporary Redirect",
            "headers": headers,
        }

    # Send a basic html error response and inform the user
    # why refresh was unsuccessful
    except Exception as err:  # pylint: disable=broad-except
        LOGGER.info(err)
        LOGGER.info(traceback.print_exc())

        headers = {
            "content-type": [
                {"key": "Content-Type", "value": "text/html; charset=UTF-8"}
            ]
        }
        headers.update(CONFIG.get("cloud_front_headers"))

        return {
            "body": create_error_html("Bad Request", err, redirected_from_uri),
            "status": "400",
            "headers": headers,
        }