Set up authentication to make API calls to Virgil ServicesThis guide shows how to set up authentication using tokens that are based on the JSON Web Token standard but with some Virgil modification.In order to make call to Virgil Services (for example, to publish user's Card on Virgil Cards Service), you need to have a JSON Web Token ("JWT"). Virgil SDKs let you use Virgil token-generation functionality without having to know how they're constructed.Prerequisites for workInstall SDK and Setup Virgil Crypto This language is only suitable for Server side. The Virgil Go SDK is provided as a package named virgil. The package is distributed via github.The package is available for Go 1.10 or newer.Installing the package:go get -u gopkg.in/virgil.v5/...Crypto library noticeThe built in crypto library supports only following primitives:ED25519 keysSHA512 hashesAES256_GCM encryptingand is not recommended for production use.On linux and macOS consider using external crypto library written in c++Using external crypto library (c++)If you are building from sources, install prerequisites as described here. and thengo get -u -d gopkg.in/virgilsecurity/virgil-crypto-go.v5 cd $(go env GOPATH)/src/gopkg.in/virgilsecurity/virgil-crypto-go.v5 makeIf you use Linux x64 or Darwin x64 architecture, you can use the pre-built crypto binariesfor Linux:CRYPTO_LIB=virgil-crypto-2.4.4-go-linux-x86_64.tgzfor MacOSCRYPTO_LIB=virgil-crypto-2.4.4-go-darwin-17.4-x86_64.tgzand thengo get -u -d gopkg.in/virgilsecurity/virgil-crypto-go.v5 wget https://cdn.virgilsecurity.com/virgil-crypto/go/$CRYPTO_LIB tar -xvf $CRYPTO_LIB --strip-components=1 -C $(go env GOPATH)/src/gopkg.in/virgilsecurity/virgil-crypto-go.v5/in your source code use crypto objects from this library as follows: import ( "gopkg.in/virgilsecurity/virgil-crypto-go.v5" ) var ( crypto = virgil_crypto_go.NewVirgilCrypto() cardCrypto = virgil_crypto_go.NewVirgilCardCrypto() tokenSigner = virgil_crypto_go.NewVirgilAccessTokenSigner() )Collect your Virgil developer credentialsParameterDescriptionAPP_IDID of your Application at Virgil DashboardAPI_KEY_IDA unique string value that identifies your account at the Virgil developer portalAPI_KEYA Private Key that is used to sign API calls to Virgil Services. For security, you will only be shown the API Private Key when the key is created. Don't forget to save it in a secure location for the next stepTo show how and why JWT is actually used, we will use a simple 3 entity example (see the below diagram). The entities in this example are the User, the Application server, and the Virgil Cards Service. The authentication server will provide the JWT to the user. With the JWT, the user can then safely communicate with the Virgil Services.In this example, the user first signs into the Application server using the authentication server’s login system (e.g. username and password, Facebook login, Google login, etc). The Application server then creates the JWT and sends it to the user. When the user makes API calls to the Virgil Cards Service, the user passes the JWT along with the API call. The Cards Service is configured to verify that the incoming JWT is created by the Application server. So, when the user makes API calls with the attached JWT, Virgil can use the JWT to verify that the API call is coming from an authenticated user.Let's see how we can set up authentication:first, we'll set up a client side for sending JWT requests to a server sidesecond, we'll set up a server side with your Virgil account credentials and generate a JWTSet up Client side and send a JWT requestAfter a user installs Virgil SDK you'll need to set up jwtProvider for providing a user with a JWT. You'll need to give your users a JWT that tells Virgil who they are and what they can do.Requests to your app server must be authorized. You can use any kind of authentication, for example, Google auth.Set up JWT providerUse these lines of code to specify which JWT generation source you prefer to use in your project:package main import ( "gopkg.in/virgil.v5/sdk" ) func main() { authenticatedQueryToServerSide := func(context *sdk.TokenContext) (string, error) { // Get generated token from server-side return "eyJraWQiOiI3MGI0NDdlMzIxZjNhMGZkIiwidHlwIjoiSldUIiwiYWxnIjoiVkVEUzUxMiIsImN0eSI6InZpcmdpbC1qd3Q7dj0xIn0.eyJleHAiOjE1MTg2OTg5MTcsImlzcyI6InZpcmdpbC1iZTAwZTEwZTRlMWY0YmY1OGY5YjRkYzg1ZDc5Yzc3YSIsInN1YiI6ImlkZW50aXR5LUFsaWNlIiwiaWF0IjoxNTE4NjEyNTE3fQ.MFEwDQYJYIZIAWUDBAIDBQAEQP4Yo3yjmt8WWJ5mqs3Yrqc_VzG6nBtrW2KIjP-kxiIJL_7Wv0pqty7PDbDoGhkX8CJa6UOdyn3rBWRvMK7p7Ak", nil } // Setup AccessTokenProvider accessTokenProvider := sdk.NewCachingStringJwtProvider(authenticatedQueryToServerSide) }Set up Server Side and Generate JWTNext, you'll set up the JwtGenerator and generate a JWT using the Virgil SDK. You'll use your API Key that was created at Virgil Dashboard. For security purposes, you have to generate JWT on your server side. Each JWT is granted access to specific Application and has a limited lifetime that is configured by you. However, best practice is to generate JWT for the shortest amount of time feasible for your application.Here is an example of how to generate a JWT: // API_KEY (you got this Key at Virgil Dashboard) privateKeyStr := []byte("MIGhMF0GCSqGSIb3DQEFDTBQMC8GCSqGSIb3DQEFDDAiBBC7Sg/DbNzhJ/uakTva") // Crypto library imports a private key into a necessary format privateKey, err := crypto.ImportPrivateKey(privateKeyStr, "") if err != nil { //handle error } // use your App Credentials you got at Virgil Dashboard: appId := "be00e10e4e1f4bf58f9b4dc85d79c77a" // APP_ID apiKeyId := "70b447e321f3a0fd" // API_KEY_ID ttl := time.Hour // 1 hour (JWT's lifetime) // setup JWT generator with necessary parameters: jwtGenerator := sdk.NewJwtGenerator(privateKey, apiKeyId, tokenSigner, appId, ttl) // generate JWT for a user // remember that you must provide each user with his unique JWT // each JWT contains unique user's identity (in this case - Alice) // identity can be any value: name, email, some id etc. identity := "Alice" token, err := jwtGenerator.GenerateToken(identity, nil) if err != nil { //handle error } // as result you get users JWT, it looks like this: "eyJraWQiOiI3MGI0NDdlMzIxZjNhMGZkIiwidHlwIjoiSldUIiwiYWxnIjoiVkVEUzUxMiIsImN0eSI6InZpcmdpbC1qd3Q7dj0xIn0.eyJleHAiOjE1MTg2OTg5MTcsImlzcyI6InZpcmdpbC1iZTAwZTEwZTRlMWY0YmY1OGY5YjRkYzg1ZDc5Yzc3YSIsInN1YiI6ImlkZW50aXR5LUFsaWNlIiwiaWF0IjoxNTE4NjEyNTE3fQ.MFEwDQYJYIZIAWUDBAIDBQAEQP4Yo3yjmt8WWJ5mqs3Yrqc_VzG6nBtrW2KIjP-kxiIJL_7Wv0pqty7PDbDoGhkX8CJa6UOdyn3rBWRvMK7p7Ak" // you can provide users with JWT at registration or authorization steps // Send a JWT to client-side jwtString := token.String()Manage a JWTEach JWT consists of three parts: the header, the payload, and the signature.// JWT Token structure header.payload.signature1. HeaderThe header contains information about how the JWT signature should be computed. The header is a JSON object in the following format:{ // the type of token. It MUST be "JWT" "typ": "JWT", // Signature algorithm. Currently supports only "VEDS512" (Virgil EdDSA SHA512) "alg": "VEDS512", // the content-type. It MUST be "virgil-jwt;v=1 "cty": "virgil-jwt;v=1" // fingerprint of public key, that will be used to verify token. Equals to first 8 bytes of SHA512 of Public Key in DER format "kid": "70b447e321f3a0fd", }2. PayloadThe payload is the data that‘s stored inside the JWT (this data is also referred to as the “claims” of the JWT). In our example, the Application server creates a JWT with the user information stored inside of it.{ // Issuer. Equals to virgil- "iss": "virgil-be00e10e4e1f4bf58f9b4dc85d79c77a", // Subject. Equals to identity- "sub": "identity-Alice", // Issued at. Utc timestamp that indicates when token was issued. "iat": 1518612517 // Expires at. Utc timestamp that shows when token will expire. Tokens have a maximum age of 24 hours "exp": 1518698917, }Keep in mind that the size of the data will affect the overall size of the JWT. This generally isn’t an issue but having excessively large JWT may negatively affect performance and cause latency.3. SignatureThe signature section is a signed hash that serves to prove the authenticity of the token. It is compiled by hashing the JWT header and payload together with your API Key secret, which should only be known to your application and Virgil.The signature is computed using the following pseudo code:// Signature signature = base64urlEncode(EdDSA+SHA512(SHA512(base64urlEncode(header) + "." + base64urlEncode(payload))))base64url encodes the header and the payload that was created in steps 1 and 2. The algorithm then joins the resulting encoded strings together with a period (.) in between them. To get the JWT signature, the data string is hashed with the secret key using the hashing algorithm specified in the JWT header.Then, using the joined encoded header and payload and applying the specified signature algorithm(HS256) on the data string with the secret key set as the string “secret”, we get the JWT Signature.Now that we have created all three components, we can create the JWT. Remembering the header.payload.signature structure of the JWT, we simply need to combine the components with periods (.) separating them. We use the base64url encoded versions of the header and of the payload, and the signature.Here is an example of JWT:// JWT Token eyJraWQiOiI3MGI0NDdlMzIxZjNhMGZkIiwidHlwIjoiSldUIiwiYWxnIjoiVkVEUzUxMiIsImN0eSI6InZpcmdpbC1qd3Q7dj0xIn0.eyJleHAiOjE1MTg2OTg5MTcsImlzcyI6InZpcmdpbC1iZTAwZTEwZTRlMWY0YmY1OGY5YjRkYzg1ZDc5Yzc3YSIsInN1YiI6ImlkZW50aXR5LUFsaWNlIiwiaWF0IjoxNTE4NjEyNTE3fQ.MFEwDQYJYIZIAWUDBAIDBQAEQP4Yo3yjmt8WWJ5mqs3Yrqc_VzG6nBtrW2KIjP-kxiIJL_7Wv0pqty7PDbDoGhkX8CJa6UOdyn3rBWRvMK7p7AkIt is important to understand that the purpose of using JWT is NOT to hide or obscure data in any way. The reason why JWT is used is to prove that the sent data was actually created by an authentic source.You can try creating your own JWT through your browser at jwt.io.