How it works
Using the hosted UI
The Authsignal hosted challenge UI is the easiest way to strongly authenticate your users through passwordless challenge flows.

1. Track an action
In your app's backend, track an action which represents what your user is doing, e.g. signIn
. You can do this using one of the Authsignal Server SDKs or you can call the Authsignal Server API directly using a RESTful HTTP request.
- Node.js
- C#
- Go
- Ruby
- PHP
- Python
const { url } = await authsignal.track({
userId: user.id,
action: "signIn",
redirectUrl: "https://yourapp.com/callback",
});
var request = new TrackRequest(
UserId: user.Id,
Action: "signIn",
RedirectUrl: "https://yourapp.com/callback");
var response = await authsignal.Track(request);
var url = response.Url;
response, err := authsignal.TrackAction(
client.TrackRequest{
UserId: user.Id,
Action: "signIn",
RedirectUrl: "https://yourapp.com/callback",
},
)
url := response.Url;
result = Authsignal.track_action({
user_id: user_id,
action_code: "signIn",
redirect_url: "https://yourapp.com/callback",
})
url = result[:url]
$result = Authsignal::trackAction(
userId: $userId,
actionCode: "signIn",
payload: array("redirectUrl" => "https://yourapp.com/callback"));
$url = $result["url"]
result = authsignal_client.track_action(
user_id=user_id,
action_code="signIn",
payload={"redirectUrl": "https://yourapp.com/callback"}
)
url = result["url"]
2. Launch the hosted UI
In your app's frontend, pass the url from the track
call to the Authsignal Browser SDK to launch an enrollment or re-authentication flow using our hosted challenge UI.
- Web
authsignal.launch(url);
3. Validate the result
Once the user has completed the challenge, Authsignal will send them back to the redirect URL you provided in step 1, appending a token
as a query param which you can use to lookup the result of the challenge server-side.
- Node.js
- C#
- Go
- Ruby
const { state } = await authsignal.validateChallenge({
userId: user.id,
token: req.query.token,
});
if (state === "CHALLENGE_SUCCEEDED") {
// The user completed the challenge successfully
// Proceed with authenticated action or integrate with IdP to create authenticated session
} else {
// The user did not complete the challenge successfully
}
var request = new ValidateChallengeRequest(UserId: user.Id, Token: token);
var response = await authsignal.ValidateChallenge(request);
if (response.State == UserActionState.CHALLENGE_SUCCEEDED) {
// The user completed the challenge successfully
// Proceed with authenticated action or integrate with IdP to create authenticated session
} else {
// The user did not complete the challenge successfully
}
response, err := authsignal.ValidateChallenge(
client.ValidateChallengeRequest{
Token: token,
UserId: user.Id,
},
)
if err == nil && response.State == "CHALLENGE_SUCCEEDED" {
// The user completed the challenge successfully
// Proceed with authenticated action or integrate with IdP to create authenticated session
} else {
// The user did not complete the challenge successfully
}
response = Authsignal.validate_challenge(user_id: user.id, token: token)
if response[:state] == "CHALLENGE_SUCCEEDED"
# The user completed the challenge successfully
# Proceed with authenticated action or integrate with IdP to create authenticated session
else
# The user did not complete the challenge successfully
end
Embedded or native challenge flows
If you prefer to build your own web or mobile app UI, you can also use one of the Authsignal Client SDKs to handle the logic behind performing the challenge.



1. Track an action
In your app's backend, track an action which represents what your user is doing, e.g. signIn
. You can do this using one of the Authsignal Server SDKs or you can call the Authsignal Server API directly using a RESTful HTTP request.
- Node.js
- C#
- Go
- Ruby
- PHP
- Python
const { token } = await authsignal.track({
userId: user.id,
action: "signIn",
});
var request = new TrackRequest(
UserId: user.Id,
Action: "signIn");
var response = await authsignal.Track(request);
var token = response.Token;
response, err := authsignal.TrackAction(
client.TrackRequest{UserId: user.Id, Action: "signIn"},
)
url := response.Url;
result = Authsignal.track_action({
user_id: user_id,
action_code: "signIn",
})
token = result[:token]
$result = Authsignal::trackAction(
userId: $userId,
actionCode: "signIn");
$token = $result["token"]
result = authsignal_client.track_action(
user_id=user_id,
action_code="signIn"
)
token = result["token"]
2. Use a client SDK
Use one of the Authsignal Client SDKs to perform a challenge directly within your app, passing the token from step 1.
- Web
- React Native
- Swift
- Kotlin
const resultToken = await authsignal.passkey.signIn({ token });
const { data: resultToken, error } = await authsignal.passkey.signIn({ token });
let result = await authsignal.passkey.signIn(token: token)
val result = authsignalPasskey.signIn(token)
3. Validate the result
Pass the result token returned by the client SDK to your backend and validate the result of the challenge server-side.
- Node.js
- C#
- Go
- Ruby
const { state } = await authsignal.validateChallenge({
userId: user.id,
token: req.body.token,
});
if (state === "CHALLENGE_SUCCEEDED") {
// The user completed the challenge successfully
// Proceed with authenticated action or integrate with IdP to create authenticated session
} else {
// The user did not complete the challenge successfully
}
var request = new ValidateChallengeRequest(UserId: user.Id, Token: token);
var response = await authsignal.ValidateChallenge(request);
if (response.State == UserActionState.CHALLENGE_SUCCEEDED) {
// The user completed the challenge successfully
// Proceed with authenticated action or integrate with IdP to create authenticated session
} else {
// The user did not complete the challenge successfully
}
response, err := authsignal.ValidateChallenge(
client.ValidateChallengeRequest{
Token: token,
UserId: user.Id,
},
)
if err == nil && response.State == "CHALLENGE_SUCCEEDED" {
// The user completed the challenge successfully
// Proceed with authenticated action or integrate with IdP to create authenticated session
} else {
// The user did not complete the challenge successfully
}
response = Authsignal.validate_challenge(user_id: user.id, token: token)
if response[:state] == "CHALLENGE_SUCCEEDED"
# The user completed the challenge successfully
# Proceed with authenticated action or integrate with IdP to create authenticated session
else
# The user did not complete the challenge successfully
end