Cards Service
The Virgil Cards Service is the core service of the Virgil infrastructure and it's responsible for the Virgil Card entries management.
The main purpose of the Virgil Card entry is to store a user's Public Key with an optional identity which is issued on the application developer's side.
Card structure
Each Virgil Card consists of 2 main parameters: content_snapshot
and signatures
:
- Content Snapshot. This is a base64-encoded JSON content snapshot message that contains information about the Card's owner.
- Signatures. This parameter contains information about the card's signatures inside, their types, names etc.
Here is an example of a card that is signed with a user private key ("signer": "self") and with your application private key ("signer": "app"):
{
"content_snapshot":"eyJjcmVhdGVkX2F0IjoxNTE1Njg2MjQ1LCJpZGVudGl0eSI6InRlc3QiLCJwdWJsaWNfa2V5IjoiTUNvd0JRWURLMlZ3QXlFQTZkOWJRUUZ1RW5VOHZTbXg5ZkRvMFd4ZWM0MkpkTmc0VlI0Rk9yNC9CVWs9IiwidmVyc2lvbiI6IjUuMCJ9",
"signatures": [
{
"signer": "self",
"snapshot": "MIGaMA0GCWCGSAFlAwQCAgUABIGIMIGFAkAUkHTx9vEXcUAq9O5bRsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimwoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuU==",
"signature": "MFEwDQYJYIZIAWUDBAIDBQAEQB+vzsWTR4+S3r5BLIwtC+SLvUmFTofxikNYKSzYfgQY1CZxC4oObkDYTIWW1LY/fIXd5wW6vf+c+iSffSSxsQ0="
},
{
"signer": "app",
"snapshot": "MIGagUABIGIMIGFAkAUkHTx9vEXcUAq9O5bMA0GCWCGSAFlAwQCARsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuUABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimw==",
"signature": "MFEwDQYJYIZIAWUDBAIDBQAEQB+vzsWTR4+S3r5BLIwtC+SLvUmFTofxikNYKSzYfgQY1CZxC4oObkDYTIWW1LY/fIXd5wW6vf+c+iSffSSxsQ0="
}
]
}
1. Content snapshot
A content_snapshot
parameter contains all data related to the Virgil Card and is wrapped into base64-encoded JSON message.
Here is an example of content snapshot message:
CONTENT_SNAPSHOT = {
"public_key": "MCowBQYDK2VwAyEAX9uVxRpJwCIFRqF8ruZGeLHB4d8j/3WxODaaT5Qpxr8",
"identity": "[email protected]",
"previous_card_id": "3084dab511135ec24c2fdc5cecbdcdcbb5db52bca8f7bf6b0b83a7fa4c740a59",
"version": "5.0",
"created_at": 1505795635
}
Each message can hold an additional parameter previous_card_id
that is used when a newly created user card is supposed to override a previous one.
The parameters inside of the content snapshot are:
Parameter name | Type | Mand. | Constraints | Comment |
---|---|---|---|---|
public_key | string | - | 16-4096 bytes | a base64-encoded public key value (public key of a Card owner) |
identity | string | + | 1-1024 bytes | Unique user identifier given by you. Can be any value - email, name, some ID and etc. |
previous_card_id | string | - | 64 bytes | ID of the previous card for this identity that is overridden. |
version | string | + | "5.0" | parameter have to be exactly "5.0" |
created_at | uint64 | + | >0 | UNIX UTC timestamp |
Parameters constraints
Parameter | Constraints |
---|---|
public_key | Is mandatory to create Virgil Card and must be empty to delete cards chain identified by it's last card ID as previous_card_id value. |
identity | The value must be the same as one passed in JWT-token. Get more information about authentication and JWT here |
previous_card_id | Virgil Card with id of previous_card_id mush have the same identity as one from the creation request. In case a Card doesn't have previous_card_id the parameter can be omitted during Card creation. |
previous_card_id | The parameter must be unique, so there are no two cards which share that value. |
The content_snapshot
will persist along with the Card and is not changeable during the Virgil Card lifetime.
2. Signatures
A signatures
parameter contains information about parties (card owner, application server, and etc.) who signed a Card. Information about each party consists of 3 main parameters: signer
, snapshot
and signature
. signatures
parameter is mandatory and must always contain Card owner signature (with type value "self").
Parameter name | Type | Mand. | Constraints | Comment |
---|---|---|---|---|
snapshot | string | - | 1-1024 bytes | This is extra content snapshot (information about extra content snapshot is below). base64-encoded arbitrary data to be stored on behalf of the signer. Here, any information that the developer needs can be stored. |
signer | string | + | 1-1024 bytes | This field must be: "self" for a self-signature (for a card owner); "virgil" for signature of Virgil Cards Service; and can be any value for a Application Server (you can use for example, "my_server", "app" etc.) |
signature | string | + | - | base64-encoded digital signature of concatenation of content_snapshot and extra content snapshot (the calculation formula of signature is below) |
2.1. Signature calculation
SIGNATURE = BASE64( SIGN_HASH( SignerPrivateKey, SHA512( CONCATENATE( CONTENT_SNAPSHOT, EXTRA_CONTENT_SNAPSHOT ) ) ) )
2.2. Extra content snapshot (optional)
Each Virgil Card can have extra content snapshot
, that contains all data related to additional signature (for example, when need to sign card with private key of an application server) and is wrapped into base64-encoded string.
Thus, when it's necessary to find content_snaphot, extra_content_snaphot or Card_ID, use the following formula:
CONTENT_SNAPSHOT = BASE64_DECODE(content_snaphot)
EXTRA_CONTENT_SNAPSHOT = BASE64_DECODE( extra_content_snaphot )
Card id
Each user's Card has its own CARD_ID
that is unique and is calculated based on Card content_snaphot
value and is calculated as a hexadecimal representation of the first 32bytes of the SHA512 hash of the content_snapshot
. The CARD_ID
can be used by the Card owner and the application service to make sure the Card data was not changed by any 3rd-party.
CARD_ID = HEX(SHA512(CONTENT_SNAPSHOT)[:256])
Is used only first 256 bits.
Here is an example of a Card ID representation:
af6799a2f26376731abb9abf32b5f2ac0933013f42628498adb6b12702df1a87
Authorization header
There is only one HTTP header that is mandatory for API calls:
GET api.virgilsecurity.com/card/v5/a6f7b874ea69329372ad75353314d7bcacd8c0be365023dab195bcac015d6009
Host: cards.virgilsecurity.com
Authorization: Virgil {JWT token}
Endpoints
Create card
The endpoint creates a Virgil Card record.
The Virgil Card creation action requires an authorization header from the Virgil Card owner which is performed via the additional signatures parameter. It must be an associative array with all necessary information about card signers.
Request info
HTTP Request method POST
Request URL https://api.virgilsecurity.com/v5/card
Request body
{
"content_snapshot":"eyJjcmVhdGVkX2F0IjoxNTE1Njg2MjQ1LCJpZGVudGl0eSI6InRlc3QiLCJwdWJsaWNfa2V5IjoiTUNvd0JRWURLMlZ3QXlFQTZkOWJRUUZ1RW5VOHZTbXg5ZkRvMFd4ZWM0MkpkTmc0VlI0Rk9yNC9CVWs9IiwidmVyc2lvbiI6IjUuMCJ9",
"signatures": [
{
"signer": "self",
"snapshot": "MIGaMA0GCWCGSAFlAwQCAgUABIGIMIGFAkAUkHTx9vEXcUAq9O5bRsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimwoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuU==",
"signature": "MFEwDQYJYIZIAWUDBAIDBQAEQB+vzsWTR4+S3r5BLIwtC+SLvUmFTofxikNYKSzYfgQY1CZxC4oObkDYTIWW1LY/fIXd5wW6vf+c+iSffSSxsQ0="
},
{
"signer": "app",
"snapshot": "MIGagUABIGIMIGFAkAUkHTx9vEXcUAq9O5bMA0GCWCGSAFlAwQCARsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuUABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimw==",
"signature": "MFEwDQYJYIZIAWUDBAIDBQAEQB+vzsWTR4+S3r5BLIwtC+SLvUmFTofxikNYKSzYfgQY1CZxC4oObkDYTIWW1LY/fIXd5wW6vf+c+iSffSSxsQ0="
}
]
}
Response body
{
"content_snapshot":"eyJjcmVhdGVkX2F0IjoxNTE1Njg2MjQ1LCJpZGVudGl0eSI6InRlc3QiLCJwdWJsaWNfa2V5IjoiTUNvd0JRWURLMlZ3QXlFQTZkOWJRUUZ1RW5VOHZTbXg5ZkRvMFd4ZWM0MkpkTmc0VlI0Rk9yNC9CVWs9IiwidmVyc2lvbiI6IjUuMCJ9",
"signatures": [
{
"signer": "self",
"snapshot": "MIGaMA0GCWCGSAFlAwQCAgUABIGIMIGFAkAUkHTx9vEXcUAq9O5bRsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimwoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuU==",
"signature": "MFEwDQYJYIZIAWUDBAIDBQAEQB+vzsWTR4+S3r5BLIwtC+SLvUmFTofxikNYKSzYfgQY1CZxC4oObkDYTIWW1LY/fIXd5wW6vf+c+iSffSSxsQ0="
},
{
"signer": "app",
"snapshot": "MIGagUABIGIMIGFAkAUkHTx9vEXcUAq9O5bMA0GCWCGSAFlAwQCARsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuUABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimw==",
"signature": "MFEwDQYJYIZIAWUDBAIDBQAEQB+vzsWTR4+S3r5BLIwtC+SLvUmFTofxikNYKSzYfgQY1CZxC4oObkDYTIWW1LY/fIXd5wW6vf+c+iSffSSxsQ0="
},
{
"signer": "virgil",
"signature": "MFEwDQYJYIZIAWUDBAIDBQAEQB+vzsWTR4+S3r5BLIwtC+SLvUmFTofxikNYKSzYfgQY1CZxC4oObkDYTIWW1LY/fIXd5wW6vf+c+iSffSSxsQ0="
}
]
}
Click here to see the request or response parameters
After the Virgil Card endpoint invocation is created, the signature list is filled with an additional signature (signer
: "virgil") - the signature of the Virgil Cards Service. See an example in the response body of this endpoint.
To verify this signature it's necessary to retrieve the Public Key of the Virgil Cards Service from the Virgil Dashboard.
GET card
Returns the information about the Virgil Card by the its ID.
This endpoint returns HTTP 200 with additional HTTP header "X-Virgil-Is-Superseeded" with value "true" in case if there is a Virgil Card with previous card ID that matches this Virgil Card ID.
Request info
HTTP Request method GET
Request URL https://api.virgilsecurity.com/v5/card/{card-id}
Response body
{
"content_snapshot":"eyJwdWJsaWNfa2V5IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVsSFlrMUNVVWRDZVhGSFUwMDBPVUZuUlVkRFUzTnJRWGROUTBOQlJVSkVVVTlDWjJkQlJVTmhWM2s1VlZWVk1ERldjamRRTHpFeFdIcHViazB2UkFvd1RpOUtPRGhuWTBkTVYzcFlNR0ZMYUdjeFNqZGliM0I2UkdWNGIwUXdhVmwzYWxGWFZVcFdjVnBKUWpSTGRGVm5lRzlJY1M4MWMybHliVUkyY1cxT0NsTkZPRE54Y1RabWJpdFBTbTlxZVVwR015dEtZMUF3VFVwMVdYUlZabnBIYmpndlVIbEhWa3AxVEVWSGFpczBOVGxLV1RSV2J6ZEtiMXBuUzJoQlQyNEtjV0ozVWpSbGNUWTBjaXRsVUVwTmNVcHBNRDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHQiLCJpZGVudGl0eSI6InVzZXJAdmlyZ2lsc2VjdXJpdHkuY29tIiwiaWRlbnRpdHlfdHlwZSI6ImVtYWlsIiwic2NvcGUiOiJnbG9iYWwiLCJpbmZvIjp7ImRldmljZSI6ImlQaG9uZSIsImRldmljZV9uYW1lIjoiU3BhY2UgZ3JleSBvbmUifX0=",
"signatures": [
{
"signer": "self",
"snapshot": "MIGaMA0GCWCGSAFlAwQCAgUABIGIMIGFAkAUkHTx9vEXcUAq9O5bRsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimwoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuU==",
"signature": "MIGaMA0GCWCGSAFlAwQCAgUABIGIMIGFAkAUkHTx9vEXcUAq9O5bRsfJ0K5s8Bwm55gEXfzbdtAfr6ihJOXA9MAdXOEocqKtH6DuU7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpK65czWphRwyuwN++hI6dlHOdPABmhMSqimwoRsLN8xsivhPqQdLow5rDFic7A=="
},
{
"signer": "app",
"snapshot": "MIGagUABIGIMIGFAkAUkHTx9vEXcUAq9O5bMA0GCWCGSAFlAwQCARsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuUABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimw==",
"signature": "MIGaMA0GCWCGSAFlAwQCAgUABIGIMIGFAkBg9WJPxgq1ObqxPpXdomNIDxlOvyGdI9wrgZYXu+YAibJd+8Vf0uFce9QrB7yiG2U2zTNVqwsg4f7bd1SKVleAkEAplvCmFJ6v3sYQVBXerr8Yb25UllbTDuCw5alWSfBw2j3ueFiXTiyY885y0detX08YFEWYgbAoKtJgModQTEcQ=="
},
{
"signer": "virgil",
"signature": "MIGaBf7bd1SKVleAkEAplvCmFJ6v3sYQVBXerr8Yb25UllbTDuCw5alWSfBw2j3ueFiXTiyY88bAoKtJMA0GCWCGSAFlAwQCAgUAgModQTEc9WJPxgq1Obqx5y0dIGIMIGFAkB4etX08YFEWYgPpXdomNIDxlOvyGdI9QgwrgZYXu+YAibJd+8Vf0uFce9QrB7yiG2U2zTNVqwsg=="
}
]
}
Click to see the request or response parameters
Search cards
Allows to search for the Cards of a single user or multiple users by theirs identity
Request info
HTTP Request method POST
Request URL https://api.virgilsecurity.com/v5/card/actions/search
Search for a single user's Cards: Request body
{
"identity": "[email protected]"
}
Search for multiple users' Cards:
{
"identities": [
"[email protected]",
"[email protected]",
"[email protected]"
]
}
Response body
[
{
"content_snapshot":"eyJwdWJsaWNfa2V5IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVsSFlrMUNVVWRDZVhGSFUwMDBPVUZuUlVkRFUzTnJRWGROUTBOQlJVSkVVVTlDWjJkQlJVTmhWM2s1VlZWVk1ERldjamRRTHpFeFdIcHViazB2UkFvd1RpOUtPRGhuWTBkTVYzcFlNR0ZMYUdjeFNqZGliM0I2UkdWNGIwUXdhVmwzYWxGWFZVcFdjVnBKUWpSTGRGVm5lRzlJY1M4MWMybHliVUkyY1cxT0NsTkZPRE54Y1RabWJpdFBTbTlxZVVwR015dEtZMUF3VFVwMVdYUlZabnBIYmpndlVIbEhWa3AxVEVWSGFpczBOVGxLV1RSV2J6ZEtiMXBuUzJoQlQyNEtjV0ozVWpSbGNUWTBjaXRsVUVwTmNVcHBNRDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHQiLCJpZGVudGl0eSI6InVzZXJAdmlyZ2lsc2VjdXJpdHkuY29tIiwiaWRlbnRpdHlfdHlwZSI6ImVtYWlsIiwic2NvcGUiOiJnbG9iYWwiLCJpbmZvIjp7ImRldmljZSI6ImlQaG9uZSIsImRldmljZV9uYW1lIjoiU3BhY2UgZ3JleSBvbmUifX0=",
"signatures": [
{
"signer": "self",
"snapshot": "MIGaMA0GCWCGSAFlAwQCAgUABIGIMIGFAkAUkHTx9vEXcUAq9O5bRsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimwoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuU==",
"signature": "MIGaMA0GCWCGSAFlAwQCAgUABIGIMIGFAkAUkHTx9vEXcUAq9O5bRsfJ0K5s8Bwm55gEXfzbdtAfr6ihJOXA9MAdXOEocqKtH6DuU7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpK65czWphRwyuwN++hI6dlHOdPABmhMSqimwoRsLN8xsivhPqQdLow5rDFic7A=="
},
{
"signer": "app",
"snapshot": "MIGagUABIGIMIGFAkAUkHTx9vEXcUAq9O5bMA0GCWCGSAFlAwQCARsfJ0K5s8Bwm55gEXK65czWphRwyuwN++hI6dlHOdPoRsLN8xsivhPqQdLow5rDFic7AtAfr6ihJOXA9MAdXOEocqKtH6DuUABmhfzbd7zJAdWgqfTrweih7jAkEAgN7CeUXwZwS0lRslWulaIGvpMSqimw==",
"signature": "MIGaMA0GCWCGSAFlAwQCAgUABIGIMIGFAkBg9WJPxgq1ObqxPpXdomNIDxlOvyGdI9wrgZYXu+YAibJd+8Vf0uFce9QrB7yiG2U2zTNVqwsg4f7bd1SKVleAkEAplvCmFJ6v3sYQVBXerr8Yb25UllbTDuCw5alWSfBw2j3ueFiXTiyY885y0detX08YFEWYgbAoKtJgModQTEcQ=="
},
{
"signer": "virgil",
"signature": "MIGaBf7bd1SKVleAkEAplvCmFJ6v3sYQVBXerr8Yb25UllbTDuCw5alWSfBw2j3ueFiXTiyY88bAoKtJMA0GCWCGSAFlAwQCAgUAgModQTEc9WJPxgq1Obqx5y0dIGIMIGFAkB4etX08YFEWYgPpXdomNIDxlOvyGdI9QgwrgZYXu+YAibJd+8Vf0uFce9QrB7yiG2U2zTNVqwsg=="
}
]
}
]
Click to see the request or response parameters
Revoke card
Revokes a card by updating (replacing) an active Virgil Card
with a new card that has an empty public key. Any revoked cards can still be retrieved by calling to GET /card/{card-id} but they will not be returned as Search cards
by identity(ies) results (POST /card/actions/search).
Note:
- The
Virgil Card
that is being revoked should have the sameIdentity
which was used to generate the original JWT token. revoke
card might have an empty or absent signatures list.
Request info
HTTP Request method POST
Request URL https://api.virgilsecurity.com/card/v5/actions/revoke
Request body
Identical to CREATE Card request (POST /card) with a few differences:
Previous card ID
value will not be emptyPublic key
field will be emptysignatures
parameter is optional, and any signatures in the parameter will not be verified
Response body
{
"content_snapshot": "eyJpZGVudGl0eSI6IjExMzNlZDAwLWM5ZDQtNGY2Zi1hY2NhLTE2NmUwODE0Zjk2ZiIsInByZXZpb3VzX2NhcmRfaWQiOiIzNGJlOTc1YTViYTJkNDA1OGZhOGMzYjIzMjNkODdmZWNiYTAwNjMyMTRlNGQ4ZGUyZGRhMTk2ZWExNGJmY2Y3IiwidmVyc2lvbiI6IjUuMCIsImNyZWF0ZWRfYXQiOjE1NDY0NDA3MDR9",
"signatures": [
{
"signer": "virgil",
"signature": "MFEwDQYJYIZIAWUDBAIDBQAEQFfu/yqv6S4kuATkp9VsD8Ug4YddktLU9YQy/qMeUnwiFh+lGAUNGpHXxjTO/Pw8BSUncLhIkm7Z4WSQneGmwQU="
}
]
}
Revoke card using its id
Revokes an active Virgil Card
using its ID only. A revoke
card with an empty public key is then automatically generated.
Request info
HTTP Request method POST
Request URL https://api.virgilsecurity.com/card/v5/actions/revoke/{card-id}
Request body Request body should be empty.
Response body This endpoint returns HTTP 200 if successful or a corresponding error if it wasn't successful.
Errors
HTTP error codes
Application uses standard HTTP response codes:
Error code | Description |
---|---|
200 | Success |
201 | Created |
400 | Request error |
401 | Authentication error |
403 | Forbidden |
404 | Entity not found |
405 | Method not allowed |
500 | Server error |
Additional information about the error is returned as a JSON object that has the following format:
{
"code": "{error-code}",
"message": "{error-message}"
}
Public key of the service
The Public Key of the Cards Service can be found on application page at Virgil Dashboard.