Skip to main content

Server Libraries

A Upollo server library can be used identify users before they login, or if they visit from multiple devices.

The library runs on your server, and can be paired with a client library for web or mobile to protect logins or payments.

Server libraries are currently available for the following languages:

  • Go
  • NodeJS
  • Python

Get your API Keys

Sign up for our beta at upollo.ai/beta to get your Private API key.

Install the library

go get github.com/Userwatch/userwatch-go

Creating the API Client

Import the package and create a client with your api key.

import userwatchgo "github.com/Userwatch/userwatch-go"

client, err := userwatchgo.NewClientBuilder(PRIVATE_API_KEY).Build()
if err != nil {
log.Panicf("Unexpected error creating the userwatch client %v", err)
}

Validate a User

To validate a user you need a token from a web or mobile client library.

You also need a userId and possibly their email address or phone number, whichever is available to improve detection. You can use an email address as the id if you don't have another id.

javascriptUserwatchToken := ??? // get the validation token from the javascript library
userId := ???
userEmail := ???
userPhone := ???

result, err := client.Validate(ctx, &userwatchgo.ValidationRequest{
ValidationToken: javascriptUserwatchToken,
Userinfo: &userwatchgo.UserInfo{
UserID: userId,
UserEmail: userEmail, // optional
UserPhone: userPhone, // optional
},
})

if result.Action == Outcome_PERMIT {
// continue
}
else if result.Action == Outcome_CHALLENGE {
// challenge the user with a sms code or webauthn
}
else if result.Action == Outcome_DENY {
// deny the user access
}

// The deviceId Can we used to help identify the user and is used in challenges
deviceId := result.DeviceInfo.DeviceID

With the validateResponse we look in the flags to interperate the analysis and see what type of customer it is.

// The result.Flag's slice contains even more useful information,
// like If account_sharing or using multiple accounts was detected
isAccountSharing := funk.Contains(result.Flag, func(flag *userwatchgo.Flag) bool {
return flag.Type == userwatchgo.FlagType_ACCOUNT_SHARING
})

isMultiAccounts := funk.Contains(result.Flag, func(flag *userwatchgo.Flag) bool {
return flag.Type == userwatchgo.FlagType_MULTIPLE_ACCOUNTS
})

Challenging a User

If you receive a Outcomes.CHALLENGE result type you can challenge the user for more identifying information. You can use either a phone SMS code, a WebAuthn login (like a fingerprint reader) or one you have built yourself which you verify.

If a SMS challenge is used first create the challenge to send the code. Then ask the user to enter the code and verify it.

requestType := ??? // usually ChallengeType_CHALLENGE_TYPE_SMS or ChallengeType_CHALLENGE_TYPE_WEBAUTHN
deviceId := ??? // from the Validate call
userId := ???
userEmail := ???
userPhone := ???
response, err := client.CreateChallenge(ctx, &userwatchgo.CreateChallengeRequest{
Type: request.Type,
DeviceID: request.DeviceID,
Origin: request.Origin,
Userinfo: &userwatchgo.UserInfo{
UserID: userId,
UserEmail: userEmail, // optional
UserPhone: userPhone, // optional
},
})

Verifying a Challenge

You can verify a challenge by doing another Validate call providing a ChallengeVerification to the ValidationRequest or you can use the VerifyChallenge method.

For an SMS challenge

challengeId := ???
challengeSecret := ???
response, err := client.VerifyChallenge(ctx, &userwatchgo.ChallengeVerificationRequest{
ChallengeID: challengeId,
SecretResponse: challengeSecret,
Type: userwatchgo.ChallengeType_CHALLENGE_TYPE_SMS,
})

For a WebAuthn challenge

response, err := client.VerifyChallenge(ctx, &userwatchgo.ChallengeVerificationRequest{
ChallengeID: challengeId,
WebauthnCredentialResponse: challengeSecretBytes,
Type: userwatchgo.ChallengeType_CHALLENGE_TYPE_WEBAUTHN,
})

response.challenge_completed_successfully indicates if the challenge was completed. If not you might like to re-issue the challenge.