We need a keystore service that supports non-custodial applications. It will make the process of stellarizing any applications easier as they don't have to implement the logic to create a stellar account and handle the encrypted private key themselves.
It is also intended to be the service that wallet SDK talks to.
For simplicity we will have each application spin up their own keystore server, so there won’t be any routing logic in the keystore server that directs requests to the correct client server to authenticate. Since we don’t anticipate a lot of requests to the keystore from each user, we should be able to tolerate having another round trip for relaying the auth token to the client server.
Keystore will forward two header fields, Authorization and Cookie, to the designated endpoint on the client server with an extra header field X-Forwarded-For specifying the request's origin. At this moment, keystore forwards incoming requests by using HTTP GET method. We plan on adding the support for clients who use GraphQL to authenticate in the future.
Clients are expected to put their auth tokens in one of the request header fields. For example, those who use a bearer token to authenticate should have an Authorization header in the following format:
Authorization: Bearer <token>
As mentioned above, clients will have to configure a API endpoint on their servers used for authentication when booting up the keystore. For those who choose to autheticate via a REST endpoint, keystore expects to receive a response in the following json format:
{
"userID": "some-user-id"
}Requests that the keystore is not able to derive a userID from will receive the following error:
not_authorized:
{
"type": "not_authorized",
"title": "Not Authorized",
"status": 401,
"detail": "The request is not authorized."
}RawKeyData Object:
interface RawKeyData {
keyType: string;
publicKey: string;
privateKey: string;
path?: string;
extra?: any;
}type RawKeys = RawKeyData[]The clients will encrypt RawKeys with a salt based on the encrypter they use. The clients will transmit the encrypted keys blob as a base64 URL encoded string.
EncryptedKeysData Object:
interface EncryptedKeysData {
encrypterName: string;
salt: string;
keysBlob: string;
creationTime: number;
modifiedTime: number;
}We support three different kinds of HTTP methods to manipulate keys:
Put Keys Request:
interface PutKeysRequest {
encrypterName: string;
salt: string;
keysBlob: string;
}Put Keys Response:
type PutKeysResponse = EncryptedKeysData;Errors
bad_request:
{
"keysBlob": "",
"salt": "some-salt",
"encrypterName": "identity"
}{
"type": "bad_request",
"title": "Bad Request",
"status": 400,
"detail": "The request you sent was invalid in some way.",
"extras": {
"invalid_field": "keysBlob",
"reason": "field value cannot be empty"
}
}bad_request:
{
"keysBlob": "some-base64-encoded-blob",
"salt": "",
"encrypterName": "identity"
}{
"type": "bad_request",
"title": "Bad Request",
"status": 400,
"detail": "The request you sent was invalid in some way.",
"extras": {
"invalid_field": "salt",
"reason": "field value cannot be empty"
}
}bad_request:
{
"keysBlob": "some-base64-encoded-blob",
"salt": "some-salt",
"encrypterName": ""
}{
"type": "bad_request",
"title": "Bad Request",
"status": 400,
"detail": "The request you sent was invalid in some way.",
"extras": {
"invalid_field": "encrypterName",
"reason": "field value cannot be empty"
}
}invalid_keys_blob:
{
"keysBlob": "some-badly-encoded-blob",
"salt": "some-salt",
"encrypterName": "identity"
}{
"type": "invalid_keys_blob",
"title": "Invalid Keys Blob",
"status": 400,
"detail": "The keysBlob in your request body is not a valid base64
string. Please encode the keysBlob in your request body as a base64
string properly and try again."
}Get Keys Request:
This endpoint will return the keys blob corresponding to the auth token in the request header, if the token is valid. This endpoint does not take any parameter.
Get Keys Response:
type GetKeysResponse = EncryptedKeysData;Errors
not_found:
The keystore cannot find any keys assocaited with the derived userID.
{
"type": "not_found",
"title": "Resourse Missing",
"status": 404,
"detail": "The resource at the url requested was not found. This
usually occurs for one of two reasons: The url requested is not valid,
or no data in our database could be found with the parameters
provided."
}Delete Keys Request:
This endpoint will delete the keys blob corresponding to the auth token in the request header and return the deleted keys blob to the client, if the token is valid. This endpoint does not take any parameter.
Delete Keys Response:
Success:
interface Success {
message: "ok";
}