Open mwiesen opened 4 years ago
Ok, after a bug fix, the output to the above curl is:
{"token_type":"refresh_token","device_id":"my-fancy-phone","device_token":"ATnhQZQrrQIFz44k8fn6ZRZvbPh9v3KO"}
Take the following template, insert the device_token
JSON object and the timestamp
and store it in a file, e.g. access_token_request.json
.
$ echo '{
"device_token" : "ATnhQZQrrQIFz44k8fn6ZRZvbPh9v3KO",
"timestamp" : "2020-09-20T11:24:54.514+00:00"
}' \
> access_token_request.json
Sign the access token request JSON object using the key pair:
$ ./SpxpCryptoTool sign access_token_request.json mwiesen_keypair.json
{
"signature": {
"sig": "o3a4NX4NLGYte74PPehlanX6vT1qCr6mU6AW-FFhF8RY1Ab0NNySVxC1xZlRxhlUcUIPsrL6fE9Fr_Vi9YUNCA",
"key": "nsgPGGSTKrnjoUWZ"
},
"device_token": "ATnhQZQrrQIFz44k8fn6ZRZvbPh9v3KO",
"timestamp": "2020-09-20T11:24:54.514+00:00"
}
POST this JSON object to the /auth/access_token
endpoint:
$ curl -i -H 'Content-Type: application/json' \
-d '{
"signature": {
"sig": "o3a4NX4NLGYte74PPehlanX6vT1qCr6mU6AW-FFhF8RY1Ab0NNySVxC1xZlRxhlUcUIPsrL6fE9Fr_Vi9YUNCA",
"key": "nsgPGGSTKrnjoUWZ"
},
"device_token": "ATnhQZQrrQIFz44k8fn6ZRZvbPh9v3KO",
"timestamp": "2020-09-20T11:24:54.514+00:00"
}' \
http://profiles.xaldon.com/manage/v01/auth/access_token
Output:
{"token_type":"access_token","access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJtd2llc2VuIiwiZXhwIjoxNjAwNjA1NDMxfQ.9i5E0uFausrOuEmLtBk1jfTN5yKwl1K2b7bIbsgzI1Symsqc0hsCHl4r-fWwMf0DMdzrxrQrUYQOV-k6FalcOw","expires_in":3600}
Since access tokens expire rather quickly, it's likely that we need to use the device token to request a new access token rather frequently. So it makes sense to squash the above steps into one command that takes care of JSON object signing, the actual curl as well as access token extraction. We're going to use an environment variable for that:
export MWIESEN_DEVICE_TOKEN="ATnhQZQrrQIFz44k8fn6ZRZvbPh9v3KO"
Then we can get a new access token and store it in a file, e.g. mwiesen_access_token.json
with the following shell command:
$ echo '{
"device_token" : "'$MWIESEN_DEVICE_TOKEN'",
"timestamp" : "'$(date -u +%Y-%m-%dT%T.000)'"
}' \
| ./SpxpCryptoTool sign /dev/stdin ./mwiesen_keypair.json \
| curl -H 'Content-Type: application/json' -d @- http://profiles.xaldon.com/manage/v01/auth/access_token \
| jq -r .access_token > mwiesen_access_token.json
Content of mwiesen_access_token.json
:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJtd2llc2VuIiwiZXhwIjoxNjAwODY5MTQ4fQ.hKE3q17SzOB4TqHaKKwSBgsahoZAQnU3dyOL3dk7fiOab08zqTYEDNabVT26bVzv8reelqVtMQ6c9ZCjt4piCw
This is a simple GET request against the service/info
endpoint. It's authenticated by providing the access token in an HTTP header using the "Bearer" authentication scheme:
curl -X GET -i -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJtd2llc2VuIiwiZXhwIjoxNjAwNjA1NDMxfQ.9i5E0uFausrOuEmLtBk1jfTN5yKwl1K2b7bIbsgzI1Symsqc0hsCHl4r-fWwMf0DMdzrxrQrUYQOV-k6FalcOw' \
http://profiles.xaldon.com/manage/v01/service/info
We can also provide the access token via the mwiesen_access_token.json
file to avoid copying and pasting:
curl -X GET -i -H "Authorization: Bearer $(cat mwiesen_access_token.json)" \
http://profiles.xaldon.com/manage/v01/service/info
Output:
{"server":{"vendor":"xaldon Technologies GmbH","product":"SPXP Server","version":"0.1","helpUri":"http://xaldon.com"},"endpoints":{"friendsEndpoint":"/mwiesen/friends","postsEndpoint":"/mwiesen/posts","keysEndpoint":"/mwiesen/keys","publishEndpoint":"/mwiesen/publish","connectEndpoint":"/mwiesen/connect","connectResponseEndpoint":"/mwiesen/packageExchange"},"limits":{"maxMediaSize":10485760}}
Let's check if there are already service messages for our profile on the server. Another GET request against the /service/messages
endpoint with a maximum messages parameter and before and after timestamps:
curl -X GET -i -H "Authorization: Bearer $(cat mwiesen_access_token.json)" \
http://profiles.xaldon.com/manage/v01/service/messages?max=100&before=2020-09-26T14:00:00.000+00:00&after=2020-09-16T11:24:54.514+00:00
Output:
{"data":[],"more":false}
No messages yet ;-)
In the spec it says we need to PUT a new JSON object to the following endpoint /profile/root
. So here is what we're trying to put. It adds a shortInfo
and about
key.
Hint: Don't forget to include your public key object and endpoints like the posts and friends endpoints. Generally it's advised to either first get the full profile from the server (e.g. by curling) or to maintain an up-to-date version of the profile locally, that then can be transmitted.
Hint: The JSON object is case sensitive, so e.g. a shortinfo
key won't work as it needs to be shortInfo
.
{
"ver": "0.3",
"name": "mwiesen",
"shortInfo": "mwiesen's profile",
"about": "mwiesen is a social media connoisseur and transparency evangelist par excellence.",
"friendsEndpoint": "/mwiesen/friends",
"postsEndpoint": "/mwiesen/posts",
"keysEndpoint": "/mwiesen/keys",
"publishEndpoint": "/mwiesen/publish",
"connectEndpoint": "/mwiesen/connect",
"connectResponseEndpoint": "/mwiesen/packageExchange",
"publicKey": {
"kty": "OKP",
"crv": "Ed25519",
"kid": "nsgPGGSTKrnjoUWZ",
"x": "NptsYvJ9GByZEt7E5CqD2qS5W7c7hlOLEVN8dLfDUUU"
}
}
The resulting shell command is:
$ echo '{
"ver": "0.3",
"name": "mwiesen",
"shortInfo": "mwiesen'\''s profile",
"about": "mwiesen is a social media connoisseur and transparency evangelist par excellence.",
"friendsEndpoint": "/mwiesen/friends",
"postsEndpoint": "/mwiesen/posts",
"keysEndpoint": "/mwiesen/keys",
"publishEndpoint": "/mwiesen/publish",
"connectEndpoint": "/mwiesen/connect",
"connectResponseEndpoint": "/mwiesen/packageExchange",
"publicKey": {
"kty": "OKP",
"crv": "Ed25519",
"kid": "nsgPGGSTKrnjoUWZ",
"x": "NptsYvJ9GByZEt7E5CqD2qS5W7c7hlOLEVN8dLfDUUU"
}
}' \
| ./SpxpCryptoTool sign /dev/stdin ./mwiesen_keypair.json \
| curl -X PUT -i -H "Authorization: Bearer $(cat mwiesen_access_token.json)" -H 'Content-Type: application/json' -d @- \
http://profiles.xaldon.com/manage/v01/profile/root
Response: HTTP/1.1 201
Here, we need to POST a post JSON object as defined in the SPXP spec to the /posts
endpoint. Here is an example:
{
"seqts" : "'$(date -u +%Y-%m-%dT%T.000)'",
"type" : "text",
"message" : "Hello, world!"
}
The resulting shell command is:
$ echo '{
"createts" : "'$(date -u +%Y-%m-%dT%T.000)'",
"type" : "text",
"message" : "Hello, world!"
}' \
| ./SpxpCryptoTool sign /dev/stdin ./mwiesen_keypair.json \
| curl -i -H "Authorization: Bearer $(cat mwiesen_access_token.json)" -H 'Content-Type: application/json' -d @- \
http://profiles.xaldon.com/manage/v01/posts
Response: HTTP/1.1 201
This is actually not a part of the Management Extension but of the basic SPXP profile specification. But it's fun to see the new post listed. It's as simple as requesting:
curl http://profiles.xaldon.com/mwiesen/posts?max=2
Result:
{"data":[{"signature":{"sig":"xMsOtKNvWR83IuZI3n04YCb93_3R3AIJoA0a0PvGo5EfXX-ANaOA4VXu5WODazsKwe5TjNaniG1PdRqr2sGhBg","key":"nsgPGGSTKrnjoUWZ"},"createts":"2020-09-23T19:26:38.000","seqts":"2020-09-23T19:26:38.401","type":"text","message":"This post can soon be deleted again!"},{"signature":{"sig":"YqDqOqAp2d_G85UYRJIq6rrMVn6e4cIncxNx16PJNAJmQ5eKWawJj26tVTDAZUAc8-L-jv-hsKf39PHcfyOeAg","key":"nsgPGGSTKrnjoUWZ"},"createts":"2020-09-23T19:10:25.000","seqts":"2020-09-23T19:10:25.615","type":"text","message":"Blaukraut bleibt Blaukraut und Brautkleid bleibt Brautkleid!"}],"more":true}
To delete a post, we need to send an authenticated DELETE request to the /posts
endpoint. It needs to provide the unique seqts
of the post object. Here's how it looks like:
$ curl -X DELETE -i -H "Authorization: Bearer $(cat mwiesen_access_token.json)" \
http://profiles.xaldon.com/manage/v01/posts/2020-09-23T19:26:38.401
Result: HTTP/1.1 204
A new request for listing the posts retrieves:
{"data":[{"signature":{"sig":"YqDqOqAp2d_G85UYRJIq6rrMVn6e4cIncxNx16PJNAJmQ5eKWawJj26tVTDAZUAc8-L-jv-hsKf39PHcfyOeAg","key":"nsgPGGSTKrnjoUWZ"},"createts":"2020-09-23T19:10:25.000","seqts":"2020-09-23T19:10:25.615","type":"text","message":"Blaukraut bleibt Blaukraut und Brautkleid bleibt Brautkleid!"},{"signature":{"sig":"oB_faGLpdvPKYwN4cEpecSyow8bzjdRrPXsUvX7UteQdgDIUBq9UDXm9n9BZV-XaF6FamlOsGx84G78Vn_2zDw","key":"nsgPGGSTKrnjoUWZ"},"createts":"2020-09-23T19:09:38.000","seqts":"2020-09-23T19:09:38.780","type":"text","message":"Hello, world!"}],"more":false}
Here is what I did. @skopf
1 Create profile profile key pair
Create a new key pair and store it in
mwiesen_keypair.json
:Output:
Make a copy without the private key:
Output:
2 Register new profile
Use the public key as the value for the
publickey
key in the following JSON template:Post the resulting JSON object to the profile registration endpoint,
profiles/v01/register
in our case:Response:
NOTES:
http://profiles.xaldon.com/mwiesen
. This could also be used in the device registration step forprofile_uri
.3 Register device
Generate a random
device_id
. In our case, we're going to usemy-fancy-phone
. Take the following template, insert theprofile_uri
,device_id
andtimestamp
and store it in a file, e.g.device_registration_request.json
.NOTES:
device_id
constraints, e.g. what's the recommended / maximum length? Are there any forbidden characters?device_id
uniqueness? Does the user have to ensure that? What happens if two devices use the samedevice_id
?device_id
?Sign the device registration JSON object using the key pair:
Output:
POST this JSON object to the
manage/v01/auth/device
endpoint:Output:
Automation
NOTES:
http://profiles.xaldon.com/mwiesen
,http://profiles.xaldon.com/profiles/mwiesen
andhttp://profiles.xaldon.com/profiles/v01/mwiesen
URIs with no success