Skip to main content
European CommissionEBSI European Blockchain

URL Encoding

The following URL Encoding definitions are used for the protocol related to OID4VP, OID4VCI and SIOPv2.
Last updated on

The codec will be used for URI and URL components, and for HTTP Request and Response payloads carrying Content-Type of application/x-www-form-urlencoded.

Codec baseline

The baseline will be Percent Encoding with flavor of application/x-www-form-urlencoded. Decoding is the encoding in reverse.

application/x-www-form-urlencoded encodes ' ' (space) as '+' (plus), newline is encoded as '%0D%0A', all except unreserved characters must be encoded with percent encoding in UTF-8 representation.

Hierarchical and primitive values

All hierarchical data structures must have a second encoding to fit into a single key=value pair, this applies for all top level values containing a data structure. The encoding is simple representation of JSON object or of JSON array as UTF-8 string.

Primitive values are encoded as is, without JSON representation.

Examples

Authorisation Request as JSON Object
{
response_type: "code",
scope: "openid",
client_id: "did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r",
authorization_details: [{
type: "openid_credential",
format:"jwt_vc",
types:[
"VerifiableCredential",
"VerifiableAttestation",
"CTWalletInTime"
]
}],
redirect_uri: "openid:",
nonce: "glkFFoisdfEui43",
code_challenge: "YjI0ZTQ4NTBhMzJmMmZhNjZkZDFkYzVhNzlhNGMyZDdjZDlkMTM4YTY4NjcyMTA5M2Q2OWQ3YjNjOGJlZDBlMSAgLQo=",
code_challenge_method: "S256",
client_metadata: {
vp_formats_supported: {
jwt_vp: {
alg: ["ES256"]
},
jwt_vc: {
alg: ["ES256"]
}
},
response_types_supported: [
"vp_token",
"id_token"
],
authorization_endpoint: "openid:"
}
};
Authorisation Request as URL Encoded
response_type=code
&scope=openid
&client_id=did%3Akey%3Az2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9KbsEYvdrjxMjQ4tpnje9BDBTzuNDP3knn6qLZErzd4bJ5go2CChoPjd5GAH3zpFJP5fuwSk66U5Pq6EhF4nKnHzDnznEP8fX99nZGgwbAh1o7Gj1X52Tdhf7U4KTk66xsA5r
&authorization_details=%5B%7B%22type%22%3A%22openid_credential%22%2C%22format%22%3A%22jwt_vc%22%2C%22types%22%3A%5B%22VerifiableCredential%22%2C%22VerifiableAttestation%22%2C%22CTWalletInTime%22%5D%7D%5D
&redirect_uri=openid%3A
&nonce=glkFFoisdfEui43
&code_challenge=YjI0ZTQ4NTBhMzJmMmZhNjZkZDFkYzVhNzlhNGMyZDdjZDlkMTM4YTY4NjcyMTA5M2Q2OWQ3YjNjOGJlZDBlMSAgLQo%3D
&code_challenge_method=S256
&client_metadata=%7B%22vp_formats_supported%22%3A%7B%22jwt_vp%22%3A%7B%22alg%22%3A%5B%22ES256%22%5D%7D%2C%22jwt_vc%22%3A%7B%22alg%22%3A%5B%22ES256%22%5D%7D%7D%2C%22response_types_supported%22%3A%5B%22vp_token%22%2C%22id_token%22%5D%2C%22authorization_endpoint%22%3A%22openid%3A%22%7D

Objects, Arrays and primitives

Javascript Object
{
obj: {
a: 1,
b: 2
},
arr: [ 1, 2, 3 ],
a: 1,
b: '2',
c: ' '
}
URL Encoded
obj=%7B%22a%22%3A1%2C%22b%22%3A2%7D
&arr=%5B1%2C2%2C3%5D
&a=1
&b=2
&c=+

Javascript Example

URLSearchParams can be used to work with the application/x-www-form-urlencoded. All top level data structures must be JSON stringified as UTF-8 before the conversion takes place, thus the algorithm would look like this.

function jsonStringifyNotPrimitive([key, value]) {
if (value == null) {
// filter out null and undefined values
return null;
}
if (typeof value === "object") {
// this includes arrays
return [key, JSON.stringify(value)];
}
return [key, value];
}

function encodeObject(o) {
return new URLSearchParams(
Object.fromEntries(
Object.entries(o).map(jsonStringifyNotPrimitive).filter(Boolean),
),
).toString();
}