Authentication
Each MPC node in the TSM is controlled by an SDK. When the SDK is initiated, it must be authenticated. When the authentication succeeds, the SDK is logged into the MPC node on a given application. The MPC node can have many applications. SDKs that are logged into the same application have access to the same keys.
SDK Authentication
The following types of SDK authentication are supported:
Authentication with API Key
Assuming that the MPC node URL is https://node.tsm.sepior.net
and that the MPC node is configured to accept the API key apikey , you can log in like this:
config := tsm.Configuration{URL: "https://node.tsm.sepior.net"}
config = config.WithAPIKeyAuthentication("apikey")
node, err := tsm.NewClient(config)
SDK authentication using an API key requires that the MPC node has been configured to accept the API key, and the actual application that this API key maps to, is specified in the TSM configuration. See this section for more about how to configure API key authentication in the TSM.
See this for a full example with API key authentication.
Authentication with TLS Client Certificate (mTLS)
As an alternative to API key authentication, the SDK can authenticate using a TLS certificate. This means that the connection between the SDK and the MPC node will be secured using a 2-way TLS connection.
This can be done like this:
clientKey := "/path/to/client.key"
clientCrt := "/path/to/client.crt"
config := tsm.Configuration{URL: "https://node.tsm.sepior.net"}
config, err = config.WithMTLSAuthentication(clientKey, clientCrt, nil)
node, err := tsm.NewClient(config)
SDK authentication with a client certificate requires that the certificate authority (CA) that issued the client certificate has been registered in the MPC node configuration. See this for more about how to configure the client certificate authentication in the MPC node configuration.
Authentication with a client certificate can be further refined in two ways:
Fine-Grained Access Control with Certificate Attributes
The MPC node can be configured with a client certificate filter. The attributes in the client certificate must match this filter in order for the authentication to succeed, and the filter also defines to which application in the Builder Vault the client gets access.
Note that if no client certificate filter is specified in the MPC node configuration, authentication will succeed with any client certificate issued by the specified certificate authority (CA), and access is granted to an application ID deduced from the Subject and Issuer names in the client certificate.
You can read more about how to configure the MPC node client certificate filter here.
OCSP Stapling
The client can optionally provide an OCSP response. OCSP is the Online Certificate Status Protocol, and the OCSP response is a proof from an OCSP authority that the client's certificate is not revoked. If provided, the MPC node will use the OCSP response to check that the client certificate is not revoked, before the client is authenticated. If the MPC node is configured with OCSPRequireStapling=true
client authentication requires the client to provide an OCSP response.
The OCSP response is provided as the third parameter to the call WithMTLSAuthentication(clientKey, clientCert string, ocspStapling *OCSPStaplingConfiguration)
and has the form:
type OCSPStaplingConfiguration struct {
// PEM certificate file containing trusted root CAs used for validating the client certificate.
// If empty, the system certificate store is used.
RootCAFile string
// Lifetime of cached OCSP responses, e.g "1h30m". A value of 0 means that ValidUntil from the OCSP response
// is used, otherwise the value of CacheTTL is used if it comes before ValidUntil.
CacheTTL string
// Use this URL for all OCSP responders, regardless of what the certificate says.
ResponderURL string
}
You can read more about how to configure the MPC node client certificate OCSP stapling here.
Authentication with OIDC
The SDK can also authenticate using an OIDC access token:
config := tsm.Configuration{URL: "https://node.tsm.sepior.net"}
config, err = config.WithOIDCAccessTokenAuthentication(accessToken)
The accessToken
is obtained from the login process performed at the OIDC identity provider.
The OIDC authentication is configured on the MPC node. The node can, e.g., be configured up to accept Microsoft accounts, or Google accounts from a particular application domain, or it can be configured to accept a custom OIDC provider. See this section for more about how to configure OIDC authentication on an MPC node.
The MPC node derives the application from the audience field in the access token. This means that two SDKs that each authenticates with their own OIDC access token, will have access to the same set of keys in the TSM, if their access tokens were issued for the same audience.
MPC Node Authentication
Above, we have seen three ways for the MPC node to authenticate the SDK. In the other direction, the SDK authenticates the MPC node using TLS. For this there are a few options:
OSCP Validation
The SDK can use the Online Certificate Status Protocol (OCSP) to immediately validate that the MPC node certificate is not revoked. You can do this by instantiating the SDK configuration follows:
// WithOCSPValidation enables OCSP validation of the MPC node certificate.
newConfig := config.WithOCSPValidation(ocspConfig)
Where the ocspConfig
parameter is of type:
type OCSPConfiguration struct {
// Require the TSM node to send a stapled OCSP response, otherwise validation will fail.
RequireStapling bool
// If true then only the leaf certificate is validated. Otherwise, the entire chain is validated.
ValidateLeafOnly bool
// Lifetime of cached OCSP responses, e.g "1h30m". A value of 0 means that ValidUntil from the OCSP response
// is used, otherwise the value of CacheTTL is used if it comes before ValidUntil.
CacheTTL string
// Use this URL for all OCSP responders, regardless of what the certificate says.
ResponderURL string
}
Providing Root Certificates
Normally, the SDK will validate the MPC node certificate using one of the root certificates from the trust store of the operating system where the SDK is running. You can override this, by providing your own list of root certificates when instantiating the SDK.
// WithRootCAFile specifies a file containing PEM certificates of the trusted root CAs used to validate the MPC node
// certificate. If not set, the system certificate store is used.
config := tsm.Configuration{URL: "https://host:port"}.WithRootCAFile(caFileName)
This causes the SDK to validate the MPC node certificate with one of the root certificates you provide.
Can be used with OCSPValidate. But is This is overrided by public
Public Key Pinning
It is also possible to provide a specific public key when instantiating the SDK. In this case, the SDK will only accept a connection with the MPC node, if the MPC node provides a certificate that matches the exact private key corresponding to the provided public key.
For example (ignoring error handling):
// Extract the MPC node public key from certificate
nodeCertPEM, err := os.ReadFile("/path/to/node.crt")
block, rest := pem.Decode(nodeCertPEM)
if block == nil || len(rest) != 0 {
panic(err)
}
cert, err := x509.ParseCertificate(block.Bytes)
nodePKIXPublicKey, err := x509.MarshalPKIXPublicKey(cert.PublicKey)
// Create node SDK with mTLS authentication and public key pinning
clientKey := "/path/to/client.key"
clientCrt := "/path/to/client.crt"
config, err := tsm.Configuration{URL: "https://node.tsm.sepior.net"}.WithPublicKeyPinning(nodePKIXPublicKey)
node, err := tsm.NewClient(config)
Note that WithPublicKeyPinning
overrides the WithRootCAFile
above.
Updated about 1 month ago