Go SDK for user monitoring


Sqreen protects your application users against major threats, such as account takeover, password bruteforce, suspicious activities coming from TOR or an unusual VPN.

The Go agent does not automatically detect your web framework and you have to install the middleware functions for the web framework you use to use the SDK methods described below.

You can find a Go documentation reference of the SDK at https://godoc.org/github.com/sqreen/go-agent/sdk.

User monitoring SDK

The Sqreen SDK integration relies on methods such as TrackSignup() and TrackAuth() allowing you to track security-related events of a given user.

Here is a full example:

uid := sdk.EventUserIdentifiersMap{"uid": "my-uid"}
sqUser := sdk.FromContext(ctx).ForUser(uid)
sqUser.TrackSignup()

User scope

User-monitoring SDK methods are provided by ForUser():

uid := sdk.EventUserIdentifiersMap{"uid": "my-uid"}
sqreen := sdk.FromContext(ctx)
sqUser := sqreen.ForUser(uid)
sqUser.TrackEvent("my.user.event")

The user identifiers given to ForUser() should uniquely identify the user and are used in Sqreen's user interface to help you identify which users are at risk, or which are attacking your application. The hash keys and values should only be strings.

Tracking a user authentication

TrackAuth(), TrackAuthSuccess() and TrackAuthFailure() allows to track successful or failed users sign-ins.

uid := sdk.EventUserIdentifiersMap{"uid": "my-uid"}
sqUser := sdk.FromContext(ctx).ForUser(uid)
sqUser.TrackAuthSuccess()

Sqreen integration at signup and login

You should not call TrachAuth() or success/failure alternatives each time you check a user session in your application, but rather each time a user logs into your app.

Tracking a user sign-up

TrackSignup() allows to track users sign-ups.

uid := sdk.EventUserIdentifiersMap{"uid": "my-uid"}
sqUser := sdk.FromContext(ctx).ForUser(uid)
sqUser.TrackSignup()

Tracking a user

Identify() allows to associate the user to current request so that Sqreen can apply security rules targeting specific users when necessary. Every TrackEvent() calls performed within the scope of the user-identified request will be thus automatically associated to this user, unless overwritten with WithUserIdentifiers().

uid := sdk.EventUserIdentifiersMap{"uid": "my-uid"}
sqUser := sdk.FromContext(ctx).ForUser(uid)
sqUser.Identify()

User security automation - Blocking users

The Security Automation allows to block or redirect users and IP addresses. But while IP addresses are automatically taken from the request, user-identifiers need to be explicitly associated to the request using the Identify() SDK method.

Method MatchSecurityResponse() then allows to check if a security response matches the identified user. If it does, the request handler should be immediately stopped so that Sqreen's middleware function can abort it by applying the configured security response.

Usage example:

func handler(w http.ResponseWriter, r *http.Request) {
    // Get the request record.
    sqreen := sdk.FromContext(r.Context())

    // Example of globally identifying a user and checking if the request
    // should be aborted.
    uid := sdk.EventUserIdentifiersMap{"uid": "my-uid"}
    sqUser := sqreen.ForUser(uid)
    sqUser.Identify() // Globally associate this user to the current request
    if match, _ := sqUser.MatchSecurityResponse(); match {
        // Return to stop further handling the request and let Sqreen's
        // middleware apply and abort the request.
        return
    }
    // Not blocked.
    fmt.Fprintf(w, "OK")
}

Method MatchSecurityResponse() also returns an error which can be used to bubble-up and stopping a deep call stack with the classic Go error handling pattern:

func handler(w http.ResponseWriter, r *http.Request) {
    if err := subfunction(r.Context()); err != nil {
        // If nested in another function, you can still
        // bubble-up the error by returning it again.
        return
    }
    fmt.Fprintf(w, "OK")
}

func subfunction(ctx context.Context) error {
    // Get the request record.
    sqreen := sdk.FromContext(ctx)

    // Example of globally identifying a user and checking if the request
    // should be aborted.
    uid := sdk.EventUserIdentifiersMap{"uid": "my-uid"}
    sqUser := sqreen.ForUser(uid)
    sqUser.Identify() // Globally associate this user to the current request
    if match, err := sqUser.MatchSecurityResponse(); match {
        // Return to stop further handling the request and let Sqreen's
        // middleware apply and abort the request.
        return err
    }
    // Not blocked.
    fmt.Fprintf(w, "OK")
}

It is advised to build or use it in an user-authentication middleware for the web framework you use so that it can be easily deployed to all your endpoints and block them as soon as possible when necessary.

Example for net/http:

func MyUserMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Get the request record created by Sqreen's middleware function and
        // stored into the request context.
        sqreen := sdk.FromContext(ctx)

        // Example of globally identifying a user and checking if the request
        // should be aborted.
        uid := /* compute your user id based on the request headers or payload */
        sqUser := sqreen.ForUser(uid)
        sqUser.Identify() // Globally associate this user to the current request
        if match, __ := sqUser.MatchSecurityResponse(); match {
            // Return to stop further handling the request and let Sqreen's
            // middleware apply and abort the request.
            return
        }
        // Not blocked, continue with next handler.
        next.ServeHTTP(w, r)
    }
}

// ...
// Build a handler by chaining middlewares and making sure Sqreen's comes first.
handler := sqhttp.Middleware(MyUserMiddleware(myHandler))
// ...

User identification

User monitoring and PII

If you are concerned about sending sensitive data to us and not leaking any Personally Identifying Information (PII), visit this blogpost to learn some best practices around user tracking.

If your users are identified with a composite primary key (multiple values), all of them should be sent in order to identify them accurately on Sqreen's user interface.

For example, if you are are operating a whitelabel platform and your users are identified by their email and the shop ID, you can send these identifiers like this:

uid := sdk.EventUserIdentifiersMap{
    "email": user.email,
    "platform_id": user.platform_id,
}
sqUser := sdk.FromContext(ctx).ForUser(uid)
sqUser.TrackSignup()

Sqreen SDK only accepts user identifiers

Do not send any other information (like the auth failure reason). Sqreen will consider them as part of the user identifier, and will not be able to merge successful and failed authentications.

Primary key

Sqreen tries to determine a primary key amongst the keys you provided. The following keywords are used to determine the user primary identification key: email, mail, e-mail, username, login.

If none of those keys are found, Sqreen uses the first in alphabetic order.

If multiple keys are found, Sqreen uses the first in the sequence mentioned above.