The Service Client interacts with Services for interacting with authorizations and sessions. The Service Client can be obtained from the appropriate factories.
The authorization process begins with a Create Authorization Request
call. In its most basic implementation,
an End User Username is all that is provided. The call returns an AuthorizationRequest object that contains the auth
request ID and push package. The auth request ID is used to determine the End User’s response through either: 1) polling
with Get Authorization Response or 2) asynchronously via a webhook with Handle Webhook. Currently, only one pending
Authorization request can exist at one time. In the case that another request is made before either the end user
responds or the Authorization request expires, an AuthorizationInProgress
exception is raised.
Errors specific to this call:
InvalidPolicyInput: | Input policy was not valid. |
---|---|
PolicyFailure: | Auth creation failed due to user not passing policy. |
EntityNotFound: | Username was invalid or the user does not have any valid devices. |
AuthorizationInProgress: | An authorization request cannot be created because one already exists. The current one must expire, be canceled, or responded to by the user. |
An AuthorizationRequest
object is returned from the Create Authorization Request
call. It contains:
id: | Unique identifier for the request. It will be used to identify this request when handling responses. |
---|---|
push package: | A string containing the information necessary to trigger processing an authorization request via
a Mobile Authenticator SDK. Send this value to your mobile application and have it pass the value to the
Authenticator SDK via handlePushPackage in iOS or onPushNotificationPackage in Android. |
device ids: | A list of Device IDs that can process the authorization request. Only these Devices will be able to
process the push package . |
var username = "myuser";
AuthorizationRequest authorizationRequest = serviceClient.CreateAuthorizationRequest(
user: username, context: null, policy: null title: null, ttl: null, pushTitle: null,
pushBody: null, denialReasons: null);
var authorizationRequestId = authorizationRequest.Id;
var pushPackage = authorizationRequest.PushPackage;
var deviceIds = authorizationRequest.DeviceIds
String username = "myuser";
AuthorizationRequest authorizationRequest = serviceClient.createAuthorizationRequest(
username, null, null, null, null, null, null, null);
String authorizationRequestId = authorization.getId();
String pushPackage = authorizationRequest.getPushPackage();
List<String> deviceIds = authorizationRequest.getDeviceIds();
username = "myuser"
authorization_request = service_client.authorization_request(username)
auth_request_id = authorization_request.auth_request
push_package = authorization_request.push_package
device_ids = authorization_request.device_ids
Only one Authorization can exist at one time for a user. In the case that an authorization attempt is made when one
already exists, an AuthorizationInProgress
exception will be raised. This exception will have additional contextual
attributes to aid in this process.
from same service: | Boolean stating whether the Authorization in progress is from the same Service requesting the new Authorization Request. |
---|---|
authorization request id: | Identifier of the existing Authorization Request that caused this exception. |
expires: | When the Authorization Request identified by authorization request id will expire. |
var username = "myuser";
try
{
AuthorizationRequest authorizationRequest = serviceClient.CreateAuthorizationRequest(
user: username, context: null, policy: null title: null, ttl: null,
pushTitle: null, pushBody: null, denialReasons: null);
}
catch(AuthorizationInProgress e)
{
Console.WriteLine("Authorization Request already in progress");
Console.WriteLine("From Same Service :" + e.FromSameService);
Console.WriteLine("Existing Auth ID :" + e.AuthorizationRequestId);
Console.WriteLine("Auth Expiration Time :" + e.Expires);
return 1;
}
String username = "myuser";
try
{
AuthorizationRequest authorizationRequest = serviceClient.createAuthorizationRequest(
username, null, null, null, null, null, null, null);
} catch (AuthorizationInProgress e) {
System.out.println("Authorization Request already in progress");
System.out.println("From Same Service :" + e.isFromSameService());
System.out.println("Existing Auth ID :" + e.getAuthorizationRequestId());
System.out.println("Auth Expiration Time :" + e.getExpires());
}
from launchkey.exceptions import AuthorizationInProgress
username = "myuser"
try:
authorization_request = service_client.authorization_request(username)
except AuthorizationInProgress as in_progress:
print("Authorization Request already in progress")
print("From Same Service : %s" % in_progress.from_same_service)
print("Existing Auth ID : %s" % in_progress.authorization_request_id)
print("Auth Expiration Time: %s" % in_progress.expires.strftime("%m/%d/%Y %H:%M:%S UTC"))
Context can be added to the Create Authorization Request call by passing a string value as the second parameter of the method. The context allows the user to have confidence that they are approving the correct request.
var username = "myuser";
var context = "Access to rear door requested";
AuthorizationRequest authorizationRequest = serviceClient.CreateAuthorizationRequest(
username: username, context: context, policy: null, title: null, ttl: null,
pushTitle: null, pushBody: null, denialReasons: null);
String username = "myuser";
String context = "Access to rear door requested";
AuthorizationRequest authorizationRequest = serviceClient.createAuthorizationRequest(
username, context, null, null, null, null, null, null);
username = "myuser"
context = "Access to rear door requested"
authorization_request = service_client.authorization_request(username, context=context)
Authorization requests can be customized with titles and push messaging. Three parameters (title, push title, and push body) can be used to modify the authorization request as described below. NOTE: All of these parameters are only valid for a Directory Service, and will return an error if used with an Organization Service.
title: | The title for an individual Authorization Request from a Directory Service. |
---|---|
push title: | The push title for a push notification originating from a Directory Service. By default no push title will be included. NOTE: Push title has no effect if you are processing push notifications outside of TruValidate Multifactor Authentication. |
push body: | The push message body for a push notification originating from a Directory Service. The default message is used unless a new body is included. NOTE: Push body has no effect if you are processing push notifications outside of TruValidate Multifactor Authentication. |
var username = "myuser";
var title = "Custom Request";
var pushTitle = "You have a pending request";
var pushBody = " Do you wish to authorize this request?";
AuthorizationRequest authorizationRequest = serviceClient.CreateAuthorizationRequest(
username, context: null, policy: null, title: title, ttl: null,
pushTitle: pushTitle, pushBody: pushBody, denialReasons: null);
String username = "myuser";
String title = "Custom Request";
String pushTitle = "You have a pending request";
String pushBody = " Do you wish to authorize this request?";
AuthorizationRequest authorizationRequest = ServiceClient.createAuthorizationRequest(
username, null, null, title, null, pushTitle, pushBody, null);
username = "myuser"
title = "Custom Request"
push_title = "You have a pending request"
push_body = " Do you wish to authorize this request?"
authorization_request = service_client.authorization_request(username, title=title,
push_title=push_title,
push_body=push_body)
Expiration Times can be set for an individual authorization request through a Time To Live (ttl) parameter. The ttl can be an integer value between 30 and 600 seconds. The default value is 300 if an expiration time is not provided.
var username = "myuser";
var ttl = 60;
AuthorizationRequest authorizationRequest = serviceClient.CreateAuthorizationRequest(
username, context: null, policy: null, title: null, ttl: ttl, pushTitle: null,
pushBody: null, denialReasons: null);
String username = "myuser";
Integer ttl = 60;
AuthorizationRequest authorizationRequest = ServiceClient.createAuthorizationRequest(
username, null , null, null, ttl, null, null, null);
username = "myuser"
ttl = 60
authorization_request = service_client.authorization_request(username, ttl=ttl)
The Authorization Request can also include a list array of two or more “denial reason” entries shown to an end user
when the user denies the Authorization Request. This parameter returns an error if used with an Organization Service.
This parameter will also return an error if denial_context_inquiry_enabled
is not set to true
(see Organization Client). Both the id and reason attributes for a denial reason must be unique amongst the
entire set of denial reasons.
id: | A string mapping of 1 to 5 characters representing the reason for the denial. This value exists in an authorization response package. |
---|---|
reason: | The text of the denial reason keyed to the id value and displayed to the user. Only this parameter is shown to the user. |
fraud: | A flag to indicate fraud as the denial reason. At least one of the items must have a fraud flag of true. |
var username = "myuser";
var denialReasons = new List<DenialReason>(){
new DenialReason(){id="a", reason="Absolute fraud", fraud=True},
new DenialReason(){id="b", reason="Bad Timing", fraud=False},
new DenialReason(){id="c", reason="I changed my mind", fraud=False},
};
AuthorizationRequest authorizationRequest = serviceClient.CreateAuthorizationRequest(
username, context: null, policy: null, title: null, ttl: ttl, pushTitle: null,
pushBody: null, denialReasons: denialReasons);
String username = "myuser";
List<DenialReason> denialReasons = new List<DenialReason>(){{
add("a", "Absolute fraud", True);
add("b", "Bad timing", False);
add("c", "I changed my mind", False);
}};
AuthorizationRequest authorizationRequest = serviceClient.createAuthorizationRequest(
userIdentifier, null , null, null, ttl, null, null, denialReasons);
from launchkey.entities.service import DenialReason
username = "myuser"
denial_reasons = [
DenialReason("a", "Absolute fraud", True),
DenialReason("b", "Bad timing", False),
DenialReason("c", "I changed my mind", False)
]
authorization_request = service_client.authorization_request(username, denial_reasons=denial_reasons)
Authorization policies can be set statically on the Admin Center or through updating the
Service via API calls (see Service Management). They can also be passed dynamically with the
Create Authorization Request
call. The policy can be submitted as the third argument of the method call.
Factor Quantity Example:
var username = "myuser";
var context = "Two factor policy request";
var authPolicy = new AuthPolicy(2);
AuthorizationRequest authorizationRequest = serviceClient.CreateAuthorizationRequest(
username: username, context: context, policy: authPolicy, title: null, ttl: null,
pushTitle: null, pushBody: null, denialReasons: null);
String username = "myuser";
String context = "Two factor policy request";
AuthPolicy authPolicy = new AuthPolicy(2);
AuthorizationRequest authorizationRequest = serviceClient.createAuthorizationRequest(
username, context, authPolicy, null, null, null, null, null);
from launchkey.clients.service import AuthPolicy
username = "myuser"
context = "Two factor policy request"
auth_policy = AuthPolicy(any=2)
authorization_request = service_client.authorization_request(username, context=context,
policy=auth_policy)
Factor Type Example:
var username = "myuser";
var context = "Knowledge and Inherence factors required policy request";
var authPolicy = new AuthPolicy(requireKnowledgeFactor: true, requireInherenceFactor: true,
requirePossessionFactor: false);
AuthorizationRequest authorizationRequest = serviceClient.CreateAuthorizationRequest(
username: username, context: context,
policy: authPolicy, title: null, ttl: null, pushTitle: null, pushBody: null, denialReasons: null);
String username = "myuser";
String context = "Knowledge and Inherence factors required policy request";
boolean requireKnowledgeFactor = true;
boolean requireInherenceFactor = true;
boolean requirePossessionFactor = false;
AuthPolicy authPolicy = new AuthPolicy(requireKnowledgeFactor, requireInherenceFactor, requirePossessionFactor);
AuthorizationRequest authorizationRequest = serviceClient.createAuthorizationRequest(
username, context, authPolicy, null, null, null, null, null);
from launchkey.clients.service import AuthPolicy
username = "myuser"
context = "Knowledge and Inherence factors required policy request"
require_knowledge_factor = True
require_inherence_factor = True
require_possession_factor = False
auth_policy = AuthPolicy(knowledge=require_knowledge_factor, inherence=require_inherence_factor,
possession=require_possession_factor)
authorization_request = service_client.authorization_request(username, context=context,
policy=auth_policy)
Geofence Type Example:
var username = "myuser";
var context = "Taj Mahal Geofence policy request";
var locations = new List<Location>;
var radiusMeters = 175 + 20; // 1/3 the longest side of the building + 20m for GPS error.
var latitudeDegrees = 27.1750;
var longitudeDegrees = 78.0422;
locations.add(new Location(radiusMeters, latitudeDegrees, longitudeDegrees));
AuthPolicy authPolicy = new AuthPolicy(locations: locations);
AuthorizationRequest authorizationRequest = serviceClient.CreateAuthorizationRequest(
username: username, context: context, policy: authPolicy, title: null, ttl: null,
pushTitle: null, pushBody: null, denialReasons: null);
String username = "myuser";
String context = "Taj Mahal Geofence policy request";
List<AuthPolicy.Location> locations = new ArrayList<AuthPolicy.Location>;
double radiusMeters = 175 + 20; // 1/3 the longest side of the building + 20m for GPS error.
double latitudeDegrees = 27.1750;
double longitudeDegrees = 78.0422;
locations.add(new AuthPolicy.Location(radiusMeters, latitudeDegrees, longitudeDegrees));
AuthPolicy authPolicy = new AuthPolicy(locations);
AuthorizationRequest authorizationRequest = serviceClient.createAuthorizationRequest(
username, context, authPolicy, null, null, null, null, null);
from launchkey.clients.service import AuthPolicy
username = "myuser"
context = "Taj Mahal Geofence policy request"
radius_meters = 175 + 20 # 1/3 the longest side of the building + 20m for GPS error.
latitude_degrees = 27.1750
longitude_degrees = 78.0422
auth_policy = AuthPolicy()
auth_policy.add_geofence(latitude=latitude_degrees, longitude=longitude_degrees,
radius=radius_meters)
authorization_request = service_client.authorization_request(username, context=context,
policy=auth_policy)
An authorization request may be canceled as long as a user response does not exist.
Errors specific to this call:
EntityNotFound: | The authorization request does not exist. |
---|---|
AuthorizationRequestCanceled: | The authorization request has already been canceled. |
AuthorizationResponseExists: | The authorization request has already been responded to so it cannot be canceled. |
var authorizationRequestId = "d70aef38-2365-11e9-903b-784f4361649f";
serviceClient.CancelAuthorizationRequest(authorizationRequestId);
String authorizationRequestId = "d70aef38-2365-11e9-903b-784f4361649f";
serviceClient.cancelAuthorizationRequest(authorizationRequestId);
auth_request_id = "d70aef38-2365-11e9-903b-784f4361649f"
authorization_request = service_client.cancel_authorization_request(auth_request_id)
An Authorization Response will contain various attributes, which can be retrieved when using either polling or webhooks.
Authorization Request ID: | The unique identifier for the authorization request. When using webhooks, it is required that you have a way for
the callback handler to alert your internal authentication mechanism of the response from the user based on this
value. This value can also be passed into the |
||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Authorized: | Contains a |
||||||||||||||||
Fraud: | A flag to indicate whether a user denial was marked as fraud based on their response. |
||||||||||||||||
Service User Hash: | This is a value unique to the Service and User combination. This value is the identifying
id sent in the service user session end webhook if a user session is terminated remotely. If the |
||||||||||||||||
Organization User Hash: | This value is unique to the Organization and User combination. This value may be used to ensure that a response is not sent for an authorization request from another Organization for the same user. |
||||||||||||||||
User Push ID: | This value is unique to the Service and User combination. This value can be used in place of a username in all communication where a username is required. Using this value rather than the user name can improve security by not storing a value that is valid across Services, Directories, and Organizations. If the user push ID is obtained by an attacker, the only Service the attacker could use this against would be the service for which it was generated. |
||||||||||||||||
Device ID: | This is a value unique to the term:User that identifies the device used to respond to the authorization request. |
||||||||||||||||
Service PINs: | This value is a FIFO buffer as a list of strings which are unique to the Service and Device. This list can aid in detecting device cloning. Over time, the original device and the cloned device will no longer contain any of the same values in the list they return in the authorization response. Warning Service PINs are an advanced feature that have the possibility of generating false negatives when a valid device loses synchronization with your application. If you use Service PINs to detect device cloning, you will need to provide a way to re-synchronize the user’s device. |
||||||||||||||||
Reason: | The reason for the response returned by the user. See Auths for a list of response reasons. |
||||||||||||||||
Type: | The response type returned by the user. See Auths for a list of response types. |
||||||||||||||||
Denial Reason: | A unique key identifying the reason the user denied a request. This value will match the id that was
submitted in the |
||||||||||||||||
Policy: | An object with the policy utilized by the device while processing the identified authorization request. This value is a result of the merging of the static Service Policy and dynamic Auth Policy (if they exist). This attribute is only received if the responding Device supports “Auth Method Insights” and a policy was required.
|
||||||||||||||||
Auth Methods: | A list of authentication method objects that describe the state of each auth method with the policy utilized by the device while processing the identified authorization request. This value is a result of the merging of the static Service Policy and dynamic Auth Policy if they exist. The list appears in the order in which the methods were processed. This attribute will only be received if the responding Device supports “Auth Method Insights”.
|
Errors specific to this call:
RequestTimedOut: | The authorization request has not been responded to before the timeout period. |
---|---|
AuthorizationRequestCanceled: | The authentication has been canceled so it can no longer be responded to. |
EntityNotFound: | The authorization request ID cannot be found. This may occur for one of two reasons. Either the ID is incorrect or the Authorization Request has ben removed from the system due to TTL expiration. Authorization requests live only a short time after the time to live (TTL) has been exceeded. The purpose of their existence beyond the TTL is only to provide better context via one of the other errors. |
Warning
Although the functionality exists to fetch for a response, Webhooks are the preferred method for completing a Login or Authorization request. If your implementation is not externally available or cannot receive HTTP requests, you may need to resort to polling.
The Get Authorization Response method can poll for the status of an existing authorization request and pass the authorization request identifier returned by the Create Authorization Request call.
Polling Example:
var username = "myuser";
var authorizationRequest = serviceClient.CreateAuthorizationRequest(user: username, context: null, policy: null
title: null, ttl: null, pushTitle: null, pushBody: null, denialReasons: null);
AdvancedAuthorizationResponse authResponse = null;
while (authResponse == null)
{
Thread.sleep(1000);
authResponse = serviceClient.GetAdvancedAuthorizationResponse(authorizationRequest.Id);
if (authResponse != null)
{
var authorized = authResponse.Authorized;
// handle authorization result
}
}
String username = "myuser";
String authorizationRequest = serviceClient.createAuthorizationRequest(username, null, null
null, null, null, null, null);
AdvancedAuthorizationResponse authResponse = null;
while (authResponse == null) {
Thread.sleep(1000L);
authResponse = serviceClient.getAdvancedAuthorizationResponse(authorizationRequest.getId());
if (authResponse != null) {
boolean authorized = authResponse.isAuthorized();
// handle authorization result
}
}
from launchkey.exceptions import RequestTimedOut
from time import sleep
user = "my_unique_internal_identifier"
authorization_request = service_client.authorization_request(user)
authorization_request_id = authorization_request.auth_request
response = None
try:
while response is None:
sleep(1)
response = service_client.get_advanced_authorization_response(authorization_request_id)
if response is not None:
if response.authorized is True:
# User logged in
else:
# User denied the auth request
except RequestTimedOut:
# The user did not respond to the request in the timeout period (auth ttl)
Helper attributes can quickly determine whether an authorization request is approved or denied (see previous code
examples). Additional context can also be derived using type
and reason
attributes in the
Authorization Response
object.
Response Type and Reason Example:
var username = "myuser";
var authorizationRequest = serviceClient.CreateAuthorizationRequest(user: username, context: null, policy: null
title: null, ttl: null, pushTitle: null, pushBody: null, denialReasons: null);
var authorizationRequestId = authorizationRequest.Id;
AdvancedAuthorizationResponse authResponse = null;
try
{
while (authResponse == null)
{
Thread.sleep(1000);
authResponse = serviceClient.GetAdvancedAuthorizationResponse(authorizationRequestId);
if (authResponse != null)
{
if (AuthorizationResponseType.Type == AuthorizationResponseType.AUTHORIZED)
{
//User logged in
Console.Writeline("Logged in");
}
else if (AuthorizationResponseType.Type == AuthorizationResponseType.DENIED)
{
if (authResponse.Reason == AuthorizationResponseReason.FRAUDULENT)
{
// User flagged request as fraudulent
Console.Writeline("Fraud");
}
// Denial is handled along with Denial Reason
Console.Writeline("Denied due to denial id: " + authResponse.denialReason);
}
else if (AuthorizationResponseType.Type == AuthorizationResponseType.FAILED)
{
// The auth request failed due to one of the documented failure types. They can be accessed
// and handled individually, but let's just log the reason.
Console.WriteLine("User auth failed due to: " + authResponse.Reason);
// Handle failure
}
else
{
// Unknown type
Console.WriteLine("Unknown response type");
}
}
}
}
catch(AuthorizationRequestTimedOutError)
{
// The user did not respond to the request in the timeout period (5 minutes)
Console.WriteLine("user never replied.");
return 1;
}
String username = "myuser";
AuthorizationRequest authorizationRequest = serviceClient.createAuthorizationRequest(username, null, null,
null, null, null, null, null);
String authorizationRequestId = authorizationRequest.getId();
AdvancedAuthorizationResponse authResponse = null;
try
{
while (authResponse == null)
{
Thread.sleep(1000L);
authResponse = serviceClient.getAdvancedAuthorizationResponse(authorizationRequestId);
if (authResponse != null)
{
if (authResponse.getType() == AdvancedAuthorizationResponse.AdvancedAuthorizationResponse.AUTHORIZED)
{
//User logged in
System.out.println("Logged in");
}
else if (authResponse.getType() == AuthorizationResponse.AdvancedAuthorizationResponse.DENIED)
{
if (authResponse.getReason() == AuthorizationResponse.AdvancedAuthorizationResponse.FRAUDULENT)
{
// User flagged request as fraudulent
System.out.println("Fraud");
}
// Denial is handled along with Denial Reason
System.out.println("Denied due to denial id: " + authResponse.getDenialReason());
}
else if (authResponse.getType() == AdvancedAuthorizationResponse.Type.FAILED)
{
// The auth request failed due to one of the documented failure types. They can be accessed
// and handled individually, but let's just log the reason.
System.out.println("User auth failed due to: " + authResponse.getReason();
// Handle failure
}
else
{
// Unknown type
System.out.println("Unknown response type");
}
}
}
}
catch (AuthorizationRequestTimedOutError e)
{
// The user did not respond to the request in the timeout period (5 minutes)
System.out.println("user never replied.");
}
from launchkey.exceptions import RequestTimedOut
from launchkey.entities.service import AuthResponseType, AuthResponseReason
from time import sleep
import logging
logger = logging.getLogger(__name__)
username = "myuser"
auth = service_client.authorization_request(username)
authorization_request_id = auth.auth_request
response = None
try:
while response is None:
sleep(1)
response = service_client.get_advanced_authorization_response(authorization_request_id)
if response is not None:
if response.type == AuthResponseType.AUTHORIZED:
# User logged in
logging.info("Logged in")
elif response.type == AuthResponseType.DENIED:
if response.reason == AuthResponseReason.FRAUDULENT:
# User flagged request as fraudulent
logging.info("Fraud")
# Regardless of fraud or not, it's still a denial so handle that as well
logging.info("Denied due to denial id: %s" % response.denial_reason)
elif response.type == AuthResponseType.FAILED:
# The auth request failed due to one of the documented failure types. They can be accessed
# and handled individually, but let's log the reason.
logging.error("User auth failed due to: %s" % response.reason.value)
# Handle failure
else:
# Unknown type
logging.error("Unknown response type")
except RequestTimedOut:
# The user did not respond to the request in the timeout period (5 minutes)
The Session Start method can execute with a username and an optional authorization request ID to start a user Session. An End User Session will show up in the User’s Authenticator to let the user know of an existing session. This will allow the User to end the session remotely.
Errors specific to this call:
EntityNotFound: | The input username was not valid. |
---|
var authorizationRequestId = "b1d05c28-0b18-41e4-94a0-853758eeefc8";
var username = "myuser";
serviceClient.SessionStart(username, authorizationRequestId);
String authorizationRequestId = "b1d05c28-0b18-41e4-94a0-853758eeefc8";
String username = "myuser";
serviceClient.sessionStart(username, authorizationRequestId);
authorization_request_id = "b1d05c28-0b18-41e4-94a0-853758eeefc8"
username = "myuser"
service_client.session_start(username, authorization_request_id)
The Session End method can execute with a username to end a user Session. This method should be called whenever a Service ends the End User’s session. This will be reflected in the End User’s Authenticator.
Errors specific to this call:
EntityNotFound: | The input username was not valid. |
---|
var username = "myuser";
serviceClient.SessionEnd(username);
String username = "myuser";
serviceClient.sessionEnd(username);
username = "myuser"
service_client.session_end(username)
The Verify TOTP
method determines whether a given OTP value is valid for a user. A Boolean is returned.
Errors specific to this call:
EntityNotFound: | Unable to find TOTP configuration for given user. |
---|
var username = "myuser";
var otp = "569874";
var valid = serviceClient.VerifyTotp(username, otp);
String username = "myuser";
String otp = "569874";
boolean valid = serviceClient.verifyTotp(username, otp);
username = "myuser"
otp = "569874"
valid = service_client.verify_totp(username, otp)
Webhooks allow a service to reduce its load by not performing polling against an external API. An endpoint must be created to receive the webhook HTTP request and update the Service configuration accordingly. Here is a link to the setup instructions: Webhooks.
Webhooks are HTTP POST requests utilizing a JSON Web Token (JWT) for authorization and validation and a JSON Web Encrypted payload. To process a webhook, collect the request headers as a map or dictionary (with the key being a string and the value being a list of strings) and pass it with the request body as a string to the Handle Webhook method.
var context = listener.GetContext();
using (var reader = new StreamReader(context.Request.InputStream, Encoding.UTF8))
{
var body = reader.ReadToEnd();
var headers = new Dictionary<string, List<string>>();
foreach (var headerName in context.Request.Headers.AllKeys)
{
headers.Add(headerName, new List<string>());
foreach (var headerValue in context.Request.Headers.GetValues(headerName))
{
headers[headerName].Add(headerValue);
}
}
var webhookPackage = serviceClient.HandleAdvancedWebhook(
headers, body, context.Request.HttpMethod, context.Request.Url.AbsolutePath);
if (webhookPackage is AdvancedAuthorizationResponseWebhookPackage)
{
// Handle authorization response
}
else if (webhookPackage is ServiceUserSessionEndWebhookPackage)
{
// Handle session end
}
}
// Spring Web Example
@RequestMapping(value = "/service-webhook", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void serviceWebhook (WebRequest request, @RequestBody String body) throws BaseException {
Map<String, List<String>> headers = new HashMap<>();
Iterator<String> headerNames = request.getHeaderNames();
while (headerNames.hasNext()) {
String headerName = headerNames.next();
headers.put(headerName, Arrays.asList(request.getHeaderValues(headerName)));
}
WebhookPackage webhookPackage = serviceClient.handleAdvancedWebhook(headers, body, "POST", "/service-webhook");
if (webhookPackage instanceof AdvancedAuthorizationResponseWebhookPackage) {
// Handle authorization response
} else if (webhookPackage instanceof ServiceUserSessionEndWebhookPackage) {
// Handle session end
}
}
# Flask example
from flask import Flask, request
from launchkey.entities.service import AdvancedAuthorizationResponse, SessionEndRequest
app = Flask(__name__)
# Path defined in your Service Callback URL value
@app.route('/webhook', methods = ['POST'])
def launchkey_webhook():
package = service_client.handle_webhook(request.data, request.headers, request.method, request.path)
if isinstance(package, AdvancedAuthorizationResponse):
if package.authorized is True:
# User accepted the auth, now create a session
service_client.session_start(user, auth_request_id)
else:
# User denied the auth
elif isinstance(package, SessionEndRequest):
# The package will have the user hash, so use it to log the user out based on however you are handling it
logout_user_from_my_app(package.service_user_hash)
The authorization response webhook contains information necessary to complete the authorization request as well as respond to a Service User Session End webhook.
The GetAdvancedAuthorizationResponse
method of the AdvancedAuthorizationResponseServerSentEventPackage
will return the same
AdvancedAuthorizationResponse
value as returned by the get Auth Response call.
See the above table for a list of attributes.
If a User ends one or all of their sessions from a linked Device or the Admin Center or a directory requests all sessions for a user to be ended, the service user session end webhook will be triggered.
Retrieving the service user hash from the Session Ended
webhoook package allows you
to identify the session(s) within your implementation that were initiated by a particular User. Use that
value to end the session in your system.
The Session Ended
webhook contains the following attributes:
API Time: | The date and time the logout was performed. |
---|---|
Service User Hash: | Hashed user identifier that will match the same value returned by an AdvancedAuthorizationResponse . |
TransUnion links to user contributed code as a resource to its community. TransUnion does not in any way guarantee or warrant the quality and security of these code bases. User contributed code is supported by the creators. If you do find a link from the site to user contributed code that is malicious or inappropriate in any way, please report that link to TransUnion immediately and we will investigate the claim. Submit any issue to TransUnion support at https://transunion.com/support. ×