Anonymous Persons
Introduction
Most websites will associate a lot of information with the current user, including GDPR consents, regional preferences, items in the shopping cart, etc.
However, requiring a sign-in as soon as the website opens would often negatively impact the user experience. For instance, most online shops allow you to browse and add items to the shopping cart immediately, and only require a sign-in when placing the order.
SlashID supports this and similar scenario with the concept of Anonymous persons.
An anonymous person can be created anytime, without any extra information and supports all the same operations as regular persons, like storing attributes, GPDR consents, etc. The only catch is that an anonymous user do not contain handles, credentials or any way of signing-in.
If the user decides to authenticate later on, one of two things happen:
If it is a new registration, the person type is upgraded from
anonymous
toregular
and you get an updated token.If the user signs-in with existing credentials, you get a new token for the existing person.
Both the new token and the
TokenMinted
events will contain theprev_anonymous_person_id
field, allowing you to import relevant state to the signed in user.
Anonymous persons are automatically deleted after 30 days, unless they have been upgraded to a regular person through a sign-up.
Creating a new Anonymous Person
A new anonymous person can be created anytime from the SDK:
import { SlashID, AnonymousUser } from '@slashid/slashid'const sid = new SlashID(...)const user: AnonymousUser = sid.createAnonymousUser()
It's also possible to create anonymous users in an SSR context:
import { SSR, SlashIDOptions } from '@slashid/slashid'// your client-side SlashID optionsconst options: SlashIDOptions = { ... }// provide the same options hereconst user: SSR.User = SSR.User.createAnonymousUser(options)
Anonymous user tokens are long-lived and can be stored in the local storage for reuse in future sessions (Up to 30 days)
Anonymous users are not counted towards the maximum number of persons on your plan until they sign-up, however, the creation of anonymous persons is rate limited proportionally.
Sign-in & Sign-up
Performing a sign-in or sign-up from an anonymous person is done via a custom id
method, unique to the AnonymousUser
class. This can only be performed in the browser.
The function signature is similar to SlashID.id(), except for not needing to pass the organization ID as the first argument as it is inferred from the underlying anonymous person token.
const anonymousUser: AnonymousUser = ...const user: BrowserUser = anonymousUser.id(identifier, factor)
If the authentication signs in with an existing person, the previous state of user
is discarded and replaced with the values from the selected person.
However, if the authentication succeeds with a new set of credentials (sign-up), they are added to the current user and its person_type
gets be upgraded to a regular
. user.ID
and everything else remains the same.
Events
Anonymous persons have separate lifecycle events: AnonymousPersonCreated
and AnonymousTokenMinted
, which are trimmed down versions of PersonCreated
and TokenMinted
events triggered by regular persons.
The creation of a new anonymous person will trigger both events.
Additionally, if it is later upgraded to a regular
person (either through a signup or by adding handles via server-side APIs) a PersonCreated
event is triggered.
Finally, if a sign-in is performed while using an anonymous person, the TokenMinted
event will contain the field prev_anonymous_person_id
.
Merging state after sign-in
When an anonymous person signs in with an existing account the application may decide to consolidate their state. A few examples:
- In a shopping website you want to import the items from the anonymous person's cart.
- If GDPR consents were recently set on the anonymous person, they should override the old consents.
- If language/regions options were set on the anonymous person, they should be used.
Unfortunately, the specifics on how to consolidate these things is application-specific and these cannot be performed automatically by SlashID. However it does provide the information you need to implement your merging logic:
Both the user token and the TokenMinted
event contain a prev_anonymous_person_id
field.
When present, this field indicates that the specified anonymous person was in use prior to sign-in, so that the application may import it.
This may be done either on the web application or in a webhook.
E.g., this will copy GDPR consents from the anonymous user to the signed in user (if they have been set)
const anonymousUser: AnonymousUser = ...const user: BrowserUser = await anonymousUser.id(...)if (anonymousUser.ID == user.tokenClaims.prev_anonymous_person_id) { const gdprConsents = await anonymousUser.getGDPRConsent() const anonymousUserConsentLevels = consents .map(({ consent_level }) => consent_level) if (anonymousUserConsentLevels) { await user.setGDPRConsent({ consentLevels: anonymousUserConsentLevels }) }}