Validating Cotter's Event Response

Cotter's Event Response includes the following information:

{
  "ID": 1361, // Event ID
  "CreatedAt": "2020-02-27T22:22:48.705212512Z",
  "UpdatedAt": "2020-02-27T22:22:48.705212512Z",
  "DeletedAt": null,
  "client_user_id": "1014", // your client's User ID
  "issuer": "afcabd98-745f-4b9e-98de-af968d9951d3", // your API Key
  "event": "<EVENT NAME>",// requested event (LOGIN, or TRANSACTION, etc)
  "ip": "192.168.232.2", 
  "location": "Unknown",
  "timestamp": "1582842167",
  "method": "TRUSTED_DEVICE", // auth method: TRUSTED_DEVICE (other choices are PIN / BIOMETRIC)
  "new": false, // Is this a new pending event. More explanation below about Non-Trusted Device
  "approved": true, // Is this event approved.
  "signature": "oonMGCAxp3..." // Signature to make sure this event comes from Cotter's server
}

First, make sure you check the following:

  • Check if the client_user_id is correct

  • Check if the timestamp is fairly recent

  • Check if the event matches the event name that you expected

  • Check that the issuer is the same as your API_KEY_ID

  • Check that approved is true

Verifying the Signature

The signature ensures that this token comes from Cotter's server:

  • Signature algorithm: ed25519

  • Cotter's Public Key: qqOaiQGjGsxBMgI5rdAasaACRiJthOqadmefjY5mS/c=

  • Signed Message:

{event.client_user_id}{event.issuer}{event.event}{event.timestamp}{event.method}{event.new}{event.approved}

Note that there is no space and no {} in the message. It's all just 1 long string. ex. 152163b39fb6eb-a1ff-4f7b-a205-d80f3c664cfdEVENTNAME1584659078TRUSTED_DEVICEfalsetrue

Example

// https://golang.org/pkg/crypto/ed25519/
func Verify(publicKey string, signStr string, args ...string) (bool, error) {
    str := []byte(strings.Join(args, ""))
    fmt.Println(strings.Join(args, ""))
    pubKey, err := base64.StdEncoding.DecodeString(publicKey)
    if err != nil {
        return false, responses.NewError("Fail verifying signature decoding pubkey", err)
    }
    signature, err := base64.StdEncoding.DecodeString(signStr)
    if err != nil {
        return false, responses.NewError("Fail verifying signature decoding signature", err)
    }
    valid := ed25519.Verify(pubKey, str, signature)
    return valid, nil
}

// Usage
valid, err := Verify(CotterPublicKey, event.Signature, event.ClientUserID, event.Issuer.String(), event.Event, event.Timestamp, string(event.Method), strconv.FormatBool(event.New), strconv.FormatBool(event.Approved))

Libraries for ed25519 algorithm are available in Javascript, Golang, Python and other languages.

Last updated