Skip to content

Commit

Permalink
feat: compliant authorize endpoint with redirect (#60)
Browse files Browse the repository at this point in the history
* test: update test to be compliant with new authorize endpoint

* chore: points to correct DIDRoom_microservices branch

after merging bring it back to main

* test(unit): update tests with new flow

* fix(wallet): the redirect endpoint is set by the external caller

* chore: DIDRoom_microservices main branch
  • Loading branch information
matteo-cristino authored Nov 6, 2024
1 parent 2917e06 commit fbe45c3
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 45 deletions.
18 changes: 18 additions & 0 deletions test/bats_utils
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,21 @@ function save_tmp_output {
export output=`cat $TMP/out`
cat $TMP/out | tee "$BATS_FILE_TMPDIR/$1"
}

# urlencode string
urlencode() {
local length="${#1}"
for (( i = 0; i < length; i++ )); do
local c="${1:i:1}"
case $c in
[a-zA-Z0-9.~_-]) printf "$c" ;;
*) printf '%%%02X' "'$c"
esac
done
}

# urldecode string
urldecode() {
local url_encoded="${1//+/ }"
printf '%b' "${url_encoded//%/\\x}"
}
27 changes: 14 additions & 13 deletions test/step_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ steps:
response_type: ${{captures.credential_parameters.response_type}}
token_endpoint: ${{captures.credential_parameters.token_endpoint}}
vct: ${{captures.credential_parameters.vct}}
redirect_uri: openid-credential-issuer://example.com/
captures:
code_verifier:
jsonpath: $.code_verifier
Expand Down Expand Up @@ -73,23 +74,22 @@ steps:
$.credential_configuration_id:
- eq: test_credential

- name: Simulate authhorize endpoint pt2 (call /ru_to_ac)
- name: Simulate authhorize endpoint pt2 (call /auhtorize_backend)
http:
url: http://${{env.as_host}}/ru_to_ac
url: http://${{env.as_host}}/authorize_backend
method: POST
json:
request_uri: ${{captures.request_uri}}
client_id: ${{captures.client_id}}
data:
id: "123456789"
headers:
Content-Type: application/x-www-form-urlencoded
followRedirects: false
body:
form_input_and_params=%7B%22params%22%3A%7B%22request_uri%22%3A%22${{captures.request_uri}}%22%2C%22client_id%22%3A%22${{captures.client_id}}%22%7D%2C%22data%22%3A%7B%22email%22%3A%22test%40email.com%22%2C%22password%22%3A%22password%22%7D%2C%22custom_code%22%3A%22test_credential%22%7D
captures:
code:
jsonpath: $.code
header: location
check:
status: 200
jsonpath:
$.code:
- isDefined: true
headers:
Location: /^openid-credential-issuer:\/\/example\.com\/\?code=.*$/
status: 302

- name: Call token and credential endpoints
http:
Expand All @@ -107,8 +107,9 @@ steps:
response_type: ${{captures.credential_parameters.response_type}}
token_endpoint: ${{captures.credential_parameters.token_endpoint}}
vct: ${{captures.credential_parameters.vct}}
code: ${{captures.code}}
code: "${{captures.code | url_encode | remove_first: 'openid-credential-issuer%3A%2F%2Fexample.com%2F%3Fcode%3D' | url_decode}}"
code_verifier: ${{captures.code_verifier}}
redirect_uri: openid-credential-issuer://example.com/
captures:
credential:
jsonpath: $.result.credential
Expand Down
19 changes: 9 additions & 10 deletions test/wallet.bats
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ load ./bats_utils
}

@test "Holder post to authz_server/par [call_par.zen]" {
jq_insert "redirect_uri" "openid-credential-offer://example.com/" holder_qr_to_well-known.output.json
zexe $WALLET/call_par.zen $WALLET/call_par.keys.json holder_qr_to_well-known.output.json
save_tmp_output call_par.output.json
url=$(jq_extract_raw "authorization_server_endpoint_par" call_par.output.json)
Expand All @@ -60,29 +61,27 @@ load ./bats_utils
authorization_endpoint=$(jq_extract_raw "authorization_endpoint" call_par.output.json)
baseUrl=${authorization_endpoint%"authorize"}
ru_to_toc=${baseUrl}ru_to_toc
ru_to_ac=${baseUrl}ru_to_ac
authorize_backend=${baseUrl}authorize_backend
client_id=$(jq_extract_raw "client_id" call_par.output.json)
request_uri=$(jq_extract_raw "request_uri" post_par.output.json)
data_toc="{\"request_uri\": \"${request_uri}\", \"client_id\": \"${client_id}\"}"
curl -X POST $ru_to_toc -H 'Content-Type: application/json' -d ''"$(echo $data_toc)"'' 1> $TMP/out
save_tmp_output ru_to_toc.output.json
assert_output '{"auth_details":[{"credential_configuration_id":"test_credential","locations":["http://localhost:3001/credential_issuer"],"type":"openid_credential","claims":[]}],"credential_configuration_id":"test_credential"}'
cci=$(jq_extract_raw "credential_configuration_id" ru_to_toc.output.json)
echo '{"email": "email@email.com", "password": "password"}' > $TMP/out
echo "form_input_and_params=$(urlencode '{"params":{"request_uri":"'"${request_uri}"'","client_id":"'"${client_id}"'"},"data":{"email":"email@email.com","password":"password"},"custom_code":"'"${cci}"'"}')" > $TMP/out
save_tmp_output form.data.json
zexe $DIR/didroom_microservices/authz_server/custom_code/$cci.zen $DIR/didroom_microservices/authz_server/custom_code/$cci.keys.json form.data.json
save_tmp_output custom_code.output.json
jq_insert 'request_uri' $request_uri custom_code.output.json
jq_insert 'client_id' $client_id custom_code.output.json
curl -X POST $ru_to_ac -H 'Content-Type: application/json' -d ''"$(cat $BATS_FILE_TMPDIR/custom_code.output.json)"'' 1> $TMP/out
save_tmp_output ru_to_ac.output.json
curl -sS -D - -X POST $authorize_backend -H 'Content-Type: application/x-www-form-urlencoded' -d ''"$(cat $BATS_FILE_TMPDIR/form.data.json)"'' -o /dev/null 1> $TMP/out
save_tmp_output authorize.output.json
assert_output --partial 'HTTP/1.1 302'
assert_output --partial 'Location: openid-credential-offer://example.com/?code='
}

@test "Holder post to authz_server/token [pre_token.zen]" {
credential_parameters=$(jq_extract_raw "credential_parameters" holder_qr_to_well-known.output.json)
code=$(jq_extract_raw "code" ru_to_ac.output.json)
code=$(grep -oP '(?<=Location: openid-credential-offer://example.com/\?code=)[^\s]+' $BATS_FILE_TMPDIR/authorize.output.json)
code_verifier=$(jq_extract_raw "code_verifier" call_par.output.json)
echo "{\"credential_parameters\": ${credential_parameters}, \"code\": \"$code\", \"code_verifier\": \"$code_verifier\"}" > $TMP/out
echo "{\"credential_parameters\": ${credential_parameters}, \"code\": \"$code\", \"code_verifier\": \"$code_verifier\", \"redirect_uri\": \"openid-credential-offer://example.com/\"}" > $TMP/out
save_tmp_output pre_token.data.json
zexe $WALLET/pre_token.zen $WALLET/call_token_and_credential.keys.json pre_token.data.json
save_tmp_output pre_token.output.json
Expand Down
5 changes: 1 addition & 4 deletions wallet/call_par.keys.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
"oauth_flow_parameters": {
"Authorization": "BEARER ",
"jwt-body-params": {
"state": "xyz",
"redirectUris": [
"https://didroom.com/"
]
"state": "xyz"
}
},
"r.request_uri_path": "result.request_uri",
Expand Down
7 changes: 1 addition & 6 deletions wallet/call_par.zen
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Scenario 'w3c' : create JWS

# data
Given I have a 'string dictionary' named 'credential_parameters'
Given I have a 'string' named 'redirect_uri'

# keys
Given I have a 'string dictionary' named 'jwt-body-params' inside 'oauth_flow_parameters'
Expand Down Expand Up @@ -61,14 +62,8 @@ When I rename the 'jws signature' to 'client_secret'


# - pickup stuff from jwt-body
When I pickup from path 'jwt-body-params.redirectUris'
When I pickup from path 'jwt-body-params.state'

# - fix redirectUris
When I create the copy of element '1' from array 'redirectUris'
When I rename the 'copy' to 'redirect_uri'


# - create par post body
When I create the 'string dictionary' named 'data'
and I move 'response_type' in 'data'
Expand Down
8 changes: 3 additions & 5 deletions wallet/call_token_and_credential.keys.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
"oauth_flow_parameters": {
"Authorization": "BEARER ",
"jwt-body-params": {
"state": "xyz",
"redirectUris": [
"https://didroom.com/"
]
"state": "xyz"
}
},
"token_headers": {
Expand All @@ -37,6 +34,7 @@
"c_nonce_path": "c_nonce",
"data_path": "data",
"headers_path": "headers",
"zen_pre_token": "scenario 'w3c': DPoP\n\n# keys\nGiven I have a 'keyring' \nGiven I have a 'string' named 'client_id'\nGiven I have a 'string dictionary' named 'jwt-body-params' inside 'oauth_flow_parameters'\n\n# data\nGiven I have a 'string' named 'grant_type' inside 'credential_parameters'\nGiven I have a 'string' named 'token_endpoint' inside 'credential_parameters'\nGiven I have a 'string' named 'code_verifier'\nGiven I have a 'string' named 'code'\n\nWhen I pickup from path 'jwt-body-params.redirectUris'\nWhen I create the copy of element '1' from array 'redirectUris'\nWhen I rename the 'copy' to 'redirect_uri'\n\nWhen I create jwk of es256 public key \n\nWhen I create the random 'ramdom_jti'\nWhen I write the string '' in 'jti'\nWhen I append the 'url64' of 'ramdom_jti' to 'jti'\n\nWhen I copy 'token_endpoint' to 'token_endpoint_copy'\nWhen I rename the 'token_endpoint_copy' to 'htu'\n\n# jti: randomBytes(16).toString('base64url'),\n# htm: 'POST',\n# htu: 'https://server.example.com/token',\n\nWhen I create the timestamp\nWhen I rename the 'timestamp' to 'iat'\n\nWhen I set 'htm' to 'POST' as 'string'\nWhen I set 'alg' to 'ES256' as 'string'\nWhen I set 'typ' to 'dpop+jwt' as 'string'\n\nWhen I create the 'string dictionary' named 'DPoP-payload'\nWhen I move 'iat' in 'DPoP-payload'\nWhen I move 'jti' in 'DPoP-payload'\nWhen I move 'htu' in 'DPoP-payload'\nWhen I move 'htm' in 'DPoP-payload'\n\nWhen I create the 'string dictionary' named 'DPoP-header'\nWhen I move 'alg' in 'DPoP-header'\nWhen I move 'typ' in 'DPoP-header'\nWhen I move 'jwk' in 'DPoP-header'\n\nWhen I create the jws signature of header 'DPoP-header' and payload 'DPoP-payload'\n\nWhen I rename the 'jws signature' to 'DPoP'\n\nWhen I create the 'string dictionary' named 'data'\nand I move 'DPoP' in 'data'\nand I move 'client_id' in 'data'\nand I move 'code' in 'data'\nand I move 'redirect_uri' in 'data'\nand I move 'code_verifier' in 'data'\nand I move 'grant_type' in 'data'\n\nThen print the 'data'\nThen print the 'token_endpoint'\n",
"redirect_uri_path": "redirect_uri",
"zen_pre_token": "scenario 'w3c': DPoP\n\n# keys\nGiven I have a 'keyring'\nGiven I have a 'string' named 'client_id'\nGiven I have a 'string dictionary' named 'jwt-body-params' inside 'oauth_flow_parameters'\n\n# data\nGiven I have a 'string' named 'grant_type' inside 'credential_parameters'\nGiven I have a 'string' named 'token_endpoint' inside 'credential_parameters'\nGiven I have a 'string' named 'code_verifier'\nGiven I have a 'string' named 'code'\nGiven I have a 'string' named 'redirect_uri'\n\nWhen I create jwk of es256 public key\n\nWhen I create the random 'ramdom_jti'\nWhen I write the string '' in 'jti'\nWhen I append the 'url64' of 'ramdom_jti' to 'jti'\n\nWhen I copy 'token_endpoint' to 'token_endpoint_copy'\nWhen I rename the 'token_endpoint_copy' to 'htu'\n\n# jti: randomBytes(16).toString('base64url'),\n# htm: 'POST',\n# htu: 'https://server.example.com/token',\n\nWhen I create the timestamp\nWhen I rename the 'timestamp' to 'iat'\n\nWhen I set 'htm' to 'POST' as 'string'\nWhen I set 'alg' to 'ES256' as 'string'\nWhen I set 'typ' to 'dpop+jwt' as 'string'\n\nWhen I create the 'string dictionary' named 'DPoP-payload'\nWhen I move 'iat' in 'DPoP-payload'\nWhen I move 'jti' in 'DPoP-payload'\nWhen I move 'htu' in 'DPoP-payload'\nWhen I move 'htm' in 'DPoP-payload'\n\nWhen I create the 'string dictionary' named 'DPoP-header'\nWhen I move 'alg' in 'DPoP-header'\nWhen I move 'typ' in 'DPoP-header'\nWhen I move 'jwk' in 'DPoP-header'\n\nWhen I create the jws signature of header 'DPoP-header' and payload 'DPoP-payload'\n\nWhen I rename the 'jws signature' to 'DPoP'\n\nWhen I create the 'string dictionary' named 'data'\nand I move 'DPoP' in 'data'\nand I move 'client_id' in 'data'\nand I move 'code' in 'data'\nand I move 'redirect_uri' in 'data'\nand I move 'code_verifier' in 'data'\nand I move 'grant_type' in 'data'\n\nThen print the 'data'\nThen print the 'token_endpoint'\n",
"zen_pre_credential": "scenario 'w3c': DPoP\n\n# keys\nGiven I have a 'keyring'\nGiven I have a 'string' named 'client_id'\nGiven I have a 'string' named 'Authorization' inside 'oauth_flow_parameters'\n\n# data\nGiven I have a 'string' named 'format' inside 'credential_parameters'\nGiven I have a 'string' named 'vct' inside 'credential_parameters'\nGiven I have a 'string' named 'credential_endpoint' inside 'credential_parameters'\nGiven I have a 'string' named 'credential_issuer' inside 'credential_parameters'\n\nGiven I have a 'string' named 'access_token'\nGiven I have a 'string' named 'c_nonce'\n\n\nWhen I create jwk of es256 public key\n\nWhen I copy 'credential_issuer' to 'aud'\n\n## 1. Create proof-payload\n\nWhen I create the 'string dictionary' named 'proof-payload'\n\nWhen I create the timestamp\nWhen I rename the 'timestamp' to 'iat'\n\nWhen I move 'iat' in 'proof-payload'\n\nWhen I rename the 'client_id' to 'iss'\nWhen I move 'iss' in 'proof-payload'\nWhen I move 'aud' in 'proof-payload'\n\nWhen I rename the 'c_nonce' to 'nonce'\nWhen I move 'nonce' in 'proof-payload'\n\n## end 1.\n\n## 2. create proof-header\n\nWhen I create the 'string dictionary' named 'proof-header'\nWhen I set 'alg' to 'ES256' as 'string'\nWhen I set 'typ' to 'open4vci-proof+jwt' as 'string'\n\nWhen I move 'alg' in 'proof-header'\nWhen I move 'typ' in 'proof-header'\nWhen I move 'jwk' in 'proof-header'\n\n## end 2,\n\n# 3. create jws from proof-header and proof-payload and create proof\n\nWhen I create the 'string dictionary' named 'proof'\n\nWhen I create the jws signature of header 'proof-header' and payload 'proof-payload'\nWhen I rename the 'jws signature' to 'jwt'\n\nWhen I move 'jwt' in 'proof'\nWhen I set 'proof_type' to 'jwt' as 'string'\nWhen I move 'proof_type' in 'proof'\n\n## end 3.\nWhen I create the 'string dictionary' named 'headers'\nWhen I append 'access_token' to 'Authorization'\nand I move 'Authorization' in 'headers'\n\nWhen I create the 'string dictionary' named 'data'\nand I move 'proof' in 'data'\nand I move 'vct' in 'data'\nand I move 'format' in 'data'\n\nThen print the 'data'\nThen print the 'credential_endpoint'\nThen print the 'headers'\n"
}
8 changes: 7 additions & 1 deletion wallet/call_token_and_credential.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,15 @@
},
"code_verifier": {
"type": "string"
},
"redirect_uri": {
"type": "string"
}
},
"required": [
"credential_parameters"
"credential_parameters",
"code",
"code_verifier",
"redirect_uri"
]
}
2 changes: 2 additions & 0 deletions wallet/call_token_and_credential.zen
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Given I send object 'keys' and send path 'oauth_flow_parameters_path' and send v
Given I send object 'data' and send path 'code_path' and send value 'code' and manipulate and set
Given I send object 'data' and send path 'code_verifier_path' and send value 'code_verifier' and manipulate and set
Given I send object 'data' and send path 'credential_parameters_path' and send value 'credential_parameters' and manipulate and set
Given I send object 'data' and send path 'redirect_uri_path' and send value 'redirect_uri' and manipulate and set

#######
# execute zen_pre_token
#######
Expand Down
9 changes: 3 additions & 6 deletions wallet/pre_token.zen
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ scenario 'w3c': DPoP
Scenario 'http': application/x-www-form-urlencoded

# keys
Given I have a 'keyring'
Given I have a 'keyring'
Given I have a 'string' named 'client_id'
Given I have a 'string dictionary' named 'jwt-body-params' inside 'oauth_flow_parameters'

Expand All @@ -11,12 +11,9 @@ Given I have a 'string' named 'grant_type' inside 'credential_parameters'
Given I have a 'string' named 'token_endpoint' inside 'credential_parameters'
Given I have a 'string' named 'code_verifier'
Given I have a 'string' named 'code'
Given I have a 'string' named 'redirect_uri'

When I pickup from path 'jwt-body-params.redirectUris'
When I create the copy of element '1' from array 'redirectUris'
When I rename the 'copy' to 'redirect_uri'

When I create jwk of es256 public key
When I create jwk of es256 public key

When I create the random 'ramdom_jti'
When I write the string '' in 'jti'
Expand Down

0 comments on commit fbe45c3

Please sign in to comment.