From 42ac602a0a0b14d767e6942c196b1f7dfeb87db5 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Fri, 6 Dec 2024 20:09:59 +0800 Subject: [PATCH] Use base64url encoding for oauth2 state parameter (#342) Signed-off-by: Huabing Zhao --- single-page-app/verify.sh | 60 ++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/single-page-app/verify.sh b/single-page-app/verify.sh index 582917dd..6e188e69 100755 --- a/single-page-app/verify.sh +++ b/single-page-app/verify.sh @@ -118,14 +118,14 @@ test_auth () { "${proxy_scheme}://localhost:${proxy_port}" \ "${curl_args[@]}" - # To enhance security,the nonce will always be used in the OAuth2 flow once PR https://github.com/envoyproxy/envoy/pull/35919 is merged. - # Nonce-less verification will remain for backward compatibility with previous releases. - # TODO: zhaohuabing - Remove the nonce-less verification after a reasonable transition period, such as one year. - run_log "Check whether the nonce is used in the OAuth2 filter" - SUPPORT_NONCE="false" + # State has been changed to be a base64url encoded json object in #37473. + # TODO(zhaohuabing): Remove the following code after #37473 is merged and become stable. + run_log "Check whether the state is a base64url encoded json object" + BASE64URL_PREFIX="eyJ1cmwiOi" # The state is prefixed with this string when it is a base64url encoded json object ({"url":) + STATE_BASE64URL_ENCODE="false" # Whether the state is a base64url encoded json object LOCATION=$(_curl "${curl_args[@]}" --head "${proxy_scheme}://localhost:${proxy_port}/login" | grep location) - if [[ "$LOCATION" == *"nonce%3D"* ]]; then - SUPPORT_NONCE="true" + if [[ "$LOCATION" == *"$BASE64URL_PREFIX"* ]]; then + STATE_BASE64URL_ENCODE="true" fi run_log "Inititiate login" @@ -133,50 +133,52 @@ test_auth () { "HTTP/1.1 302 Found" \ "${proxy_scheme}://localhost:${proxy_port}/login" \ "${curl_args[@]}" - if [[ "$SUPPORT_NONCE" == "true" ]]; then + if [[ "$STATE_BASE64URL_ENCODE" == "true" ]]; then responds_with_header \ - "location: http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3D${proxy_scheme}%253A%252F%252Flocalhost%253A${proxy_port}%252Flogin%26nonce%3D" \ - "${proxy_scheme}://localhost:${proxy_port}/login" \ - "${curl_args[@]}" - responds_with_header \ - "set-cookie: OauthNonce=" \ + "location: http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${BASE64URL_PREFIX}" \ "${proxy_scheme}://localhost:${proxy_port}/login" \ "${curl_args[@]}" else responds_with_header \ - "location: http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Flogin" \ + "location: http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3D${proxy_scheme}%253A%252F%252Flocalhost%253A${proxy_port}%252Flogin%26nonce%3D" \ "${proxy_scheme}://localhost:${proxy_port}/login" \ "${curl_args[@]}" fi + responds_with_header \ + "set-cookie: OauthNonce=" \ + "${proxy_scheme}://localhost:${proxy_port}/login" \ + "${curl_args[@]}" + + encoded_state=$(echo -n "{\"url\":\"${proxy_scheme}://localhost:${proxy_port}/login\",\"nonce\":\"12345678\"}" | basenc --base64url --wrap=0 | sed 's/=//g') run_log "Fetch the myhub authorization page" - if [[ "$SUPPORT_NONCE" == "true" ]]; then + if [[ "$STATE_BASE64URL_ENCODE" == "true" ]]; then responds_with_header \ "HTTP/1.1 302 Found" \ - "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3D${proxy_scheme}%253A%252F%252Flocalhost%253A${proxy_port}%252Flogin%26nonce%3D12345678" \ + "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${encoded_state}" \ "${curl_args[@]}" responds_with_header \ "Location: ${proxy_scheme}://localhost:${proxy_port}/authorize?code=" \ - "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3D${proxy_scheme}%253A%252F%252Flocalhost%253A${proxy_port}%252Flogin%26nonce%3D12345678" \ + "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${encoded_state}" \ "${curl_args[@]}" else responds_with_header \ "HTTP/1.1 302 Found" \ - "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Flogin" \ + "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3D${proxy_scheme}%253A%252F%252Flocalhost%253A${proxy_port}%252Flogin%26nonce%3D12345678" \ "${curl_args[@]}" responds_with_header \ "Location: ${proxy_scheme}://localhost:${proxy_port}/authorize?code=" \ - "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Flogin" \ + "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3D${proxy_scheme}%253A%252F%252Flocalhost%253A${proxy_port}%252Flogin%26nonce%3D12345678" \ "${curl_args[@]}" fi run_log "Return to the app and receive creds" - if [[ "$SUPPORT_NONCE" == "true" ]]; then + if [[ "$STATE_BASE64URL_ENCODE" == "true" ]]; then + CODE=$(_curl "${curl_args[@]}" --head "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${encoded_state}" | grep Location | cut -d= -f2 | cut -d\& -f1) + RESPONSE=$(_curl "${curl_args[@]}" --cookie "OauthNonce=12345678" --head "${proxy_scheme}://localhost:${proxy_port}/authorize?code=$CODE&state=${encoded_state}") + else CODE=$(_curl "${curl_args[@]}" --head "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3D${proxy_scheme}%253A%252F%252Flocalhost%253A${proxy_port}%252Flogin%26nonce%3D12345678" | grep Location | cut -d= -f2 | cut -d\& -f1) RESPONSE=$(_curl "${curl_args[@]}" --cookie "OauthNonce=12345678" --head "${proxy_scheme}://localhost:${proxy_port}/authorize?code=$CODE&state=url%3D${proxy_scheme}%253A%252F%252Flocalhost%253A${proxy_port}%252Flogin%26nonce%3D12345678") - else - CODE=$(_curl "${curl_args[@]}" --head "http://localhost:${PORT_MYHUB}/authorize?client_id=0123456789&redirect_uri=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Flogin" | grep Location | cut -d= -f2 | cut -d\& -f1) - RESPONSE=$(_curl "${curl_args[@]}" --head "${proxy_scheme}://localhost:${proxy_port}/authorize?code=$CODE&state=${proxy_scheme}%3A%2F%2Flocalhost%3A${proxy_port}%2Flogin") fi echo "$RESPONSE" | grep "HTTP/1.1 302 Found" echo "$RESPONSE" | grep "location: ${proxy_scheme}://localhost:${proxy_port}/login" @@ -326,16 +328,16 @@ run_log "Inititiate dev login (Github)" responds_with_header \ "HTTP/1.1 302 Found" \ "http://localhost:${PORT_DEV_PROXY}/login" -if [[ "$SUPPORT_NONCE" == "true" ]]; then +if [[ "$STATE_BASE64URL_ENCODE" == "true" ]]; then responds_with_header \ - "location: https://github.com/login/oauth/authorize?client_id=XXX&redirect_uri=http%3A%2F%2Flocalhost%3A${PORT_DEV_PROXY}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3Dhttp%253A%252F%252Flocalhost%253A${PORT_DEV_PROXY}%252Flogin%26nonce%3D" \ + "location: https://github.com/login/oauth/authorize?client_id=XXX&redirect_uri=http%3A%2F%2Flocalhost%3A${PORT_DEV_PROXY}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${BASE64URL_PREFIX}" \ "http://localhost:${PORT_DEV_PROXY}/login" responds_with_header \ "set-cookie: OauthNonce=" \ "http://localhost:${PORT_DEV_PROXY}/login" else responds_with_header \ - "location: https://github.com/login/oauth/authorize?client_id=XXX&redirect_uri=http%3A%2F%2Flocalhost%3A${PORT_DEV_PROXY}%2Fauthorize&response_type=code&scope=user%3Aemail&state=http%3A%2F%2Flocalhost%3A${PORT_DEV_PROXY}%2Flogin" \ + "location: https://github.com/login/oauth/authorize?client_id=XXX&redirect_uri=http%3A%2F%2Flocalhost%3A${PORT_DEV_PROXY}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3Dhttp%253A%252F%252Flocalhost%253A${PORT_DEV_PROXY}%252Flogin%26nonce%3D" \ "http://localhost:${PORT_DEV_PROXY}/login" fi @@ -344,9 +346,9 @@ responds_with \ "Envoy single page app example" \ "https://localhost:${PORT_PROXY}" \ -k -if [[ "$SUPPORT_NONCE" == "true" ]]; then +if [[ "$STATE_BASE64URL_ENCODE" == "true" ]]; then responds_with_header \ - "location: https://github.com/login/oauth/authorize?client_id=XXX&redirect_uri=https%3A%2F%2Flocalhost%3A${PORT_PROXY}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3Dhttps%253A%252F%252Flocalhost%253A${PORT_PROXY}%252Flogin%26nonce%3D" \ + "location: https://github.com/login/oauth/authorize?client_id=XXX&redirect_uri=https%3A%2F%2Flocalhost%3A${PORT_PROXY}%2Fauthorize&response_type=code&scope=user%3Aemail&state=${BASE64URL_PREFIX}" \ "https://localhost:${PORT_PROXY}/login" \ -k responds_with_header \ @@ -355,7 +357,7 @@ if [[ "$SUPPORT_NONCE" == "true" ]]; then -k else responds_with_header \ - "location: https://github.com/login/oauth/authorize?client_id=XXX&redirect_uri=https%3A%2F%2Flocalhost%3A${PORT_PROXY}%2Fauthorize&response_type=code&scope=user%3Aemail&state=https%3A%2F%2Flocalhost%3A${PORT_PROXY}%2Flogin" \ + "location: https://github.com/login/oauth/authorize?client_id=XXX&redirect_uri=https%3A%2F%2Flocalhost%3A${PORT_PROXY}%2Fauthorize&response_type=code&scope=user%3Aemail&state=url%3Dhttps%253A%252F%252Flocalhost%253A${PORT_PROXY}%252Flogin%26nonce%3D" \ "https://localhost:${PORT_PROXY}/login" \ -k fi