QR Authentication
The QR Authentication flow (described below) is useful for website login, door access or other situations when arbitrary devices request authentication and the service does not initially identify the user.
The 3rd party server makes a request to the VeridiumID server to start a session opportunity (a type of session that waits for an authenticator to attach). It is useful when a terminal (such as web browser or an ATM) displays the authentication page and an authenticator device will try to fulfill that authentication challenge. For example, a login page on a website that displays this session opportunity and a mobile device that attaches to this session and does a biometric authentication. The website can then have access to the user's identity and display personalized information.
Server authentication request
See Appendix VeridiumID API section RegisterSessionOpportunity to see the request parameters.
memberExternalId is the external identifier for the enterprise integration.
sessionAliasType is the format of the session identifier. It can have values like QR (a QR image containing identity information) and ID (UUID).
extraValues that can be interpreted by the custom Integration Adaptor or Mobile app.
curl -X POST \
https://[domain:port]/websec/rest/enterprise/RegisterSessionOpportunity \
-H 'content-type: application/vnd.veridiumid.sessionOpportunity-v2+json' \
-d '{ "memberExternalId": "GENERIC", "sessionAliasType" : "QR" }'
Based on the preferred Alias type, the response contains a base64 encoded image or the ID as string.
Session status changes can be queried by calling GetSessionStatus/GetSessionStatusAsync (see Appendix VeridiumID API). For example, a website that wants to refresh the login page when the session status is changed, must make periodic calls for GetSessionStatus or open a long polling connection with GetSessionStatusAsync and make appropiate logic based on the returned session status.
Mobile authentication
A user scans the QR image using the phone, the SDK will extract the session identifier, use it to attach to the session opportunity and query the Veridium server for additional information (session context, required biometrics, etc.)
iOS
class AuthenticationHandler : NSObject {
...
func onAuthenticate(profileAlias: String) {
/*...*/
// when multiple profiles are enrolled in the app the authentication call needs the profile parameter to be filled in.
// the list of profiles can be retrieved by calling the asynchronous method VIDMobileSDK.shared().retrieveProfiles()
VIDMobileSDK.shared().profileDelegate = self
VIDMobileSDK.shared().authenticationDelegate = self
// retrieve profile also requires the VIDEnvironment instance to specify the environment the profile belongs to
VIDMobileSDK.shared().retrieveProfile(profileAlias, for: environment)
/*...*/
}
func onAuthenticate() {
VIDMobileSDK.shared().authenticationDelegate = self
VIDMobileSDK.shared().authenticateWithQR(profile)
/*...*/
}
extension AuthenticationHandler : VIDProfileDelegate {
func didFinishRetrievingProfiles(environment: VIDEnvironment, result: Result<[VIDProfile], VIDError>) {
switch result {
case .success(let profiles):
// Profiles retrieved successfully, only one profile is expected
if let profile = profiles.first, profiles.count == 1 {
VIDMobileSDK.shared().authenticateWithQR(profile)
}
case .failure(let error):
// Handle error
}
}
func didDeleteProfile(environment: VIDEnvironment, result: Result<VIDProfile, VIDError>) {
switch result {
case .success(_):
// handle profile removed successfully
case .failure(let error):
// handle profile remove error
}
}
func didCancelDeleteProfile(environment: VIDEnvironment) { }
func didFinishUpdateProfile(environment: VIDEnvironment, result: Result<VIDProfile, VIDError>) { }
func didCancelUpdateProfile(environment: VIDEnvironment) { }
}
extension AuthenticationHandler : VIDAuthenticationDelegate {
func didStartAuthentication() { }
func didFinishAuthentication(response: VIDAuthResponse, profile: VIDProfile?) {
switch response.status {
case .AUTHENTICATED:
print("Success")
case .ON_GOING_AUTHENTICATION:
print("Continue on another device")
case .CANCELED:
.FAILED:
.TIMEOUT:
.NONE:
print("Failed")
}
}
func didFinishAuthenticationServerChallenge(signedResponse: VIDAuthResponse, profile: VIDProfile?) { }
func didCancelAuthentication(profile: VIDProfile?) { }
func didCancelAuthenticationServerChallenge(signedResponse: VIDAuthResponse, profile: VIDProfile?) { }
func didFailAuthentication(error: VIDError, profile: VIDProfile?) {
if error.requiresBiometryRevalidation() && profile != nil {
VIDMobileSDK.shared().reenrollBiometricAuthenticators(for: profile!)
}
else {
let nsError = error as NSError
print(nsError.localizedReason)
}
}
func didFailAuthenticationServerChallenge(signedResponse: VIDAuthResponse, error: VIDError, profile: VIDProfile?) { }
}
Android
...
public boolean authenticate(VeridiumIdProfile profile) {
VeridiumIdPendingIntent pendingIntent = VeridiumMobileSDK.getInstance().authenticate(profile);
if (pendingIntent != null && pendingIntent.hasPendingIntent()) {
try {
pendingIntent.launchPendingIntent(this, REQUEST_CODE_AUTHENTICATION);
return true;
} catch (IntentSender.SendIntentException ignored) {
}
}
return false;
}
...
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (resultCode == RESULT_CANCELED)
return;
switch (requestCode) {
...
case REQUEST_CODE_AUTHENTICATION:
if (data.getExtras().getParcelable(VeridiumMobileSDK.VERIDIUMID_KEY_ERROR_EXTRA) != null) {
VeridiumIdErrorResponse errorResponse = (VeridiumIdErrorResponse) data.getExtras().getParcelable(VeridiumMobileSDK.VERIDIUMID_KEY_ERROR_EXTRA);
//ToDo Handle error result according to your needs
}
else {
VeridiumIdAuthenticationResponse authResponse = (VeridiumIdAuthenticationResponse) data.getExtras().getParcelable(VeridiumMobileSDK.VERIDIUMID_KEY_RESPONSE_EXTRA);
//ToDo Handle authentication result according to your needs
}
break;
...
}
}
Session information
When the session completes, the SDK will call the VIDAuthenticationDelegate which contains VIDAuthResponse parameter. The response.status can have one of the following values:
status | description |
---|---|
OPPORTUNITY | the session waits for an authenticator to attach |
CREATED | the authenticator and exploiter are known and waiting for biometric assertion. |
AUTHENTICATING | biometric assertion is in progress usually when server-side matching is done. |
AUTHENTICATED | the biometric assertion completed successfully. The Authenticator provided the final result which was saved in the biometricAuthenticationResult parameter. |
FAILED | session failed. |
TIMEOUT | session timed-out. |
COMPLETED | session is finalized, result was delivered to the exploiter. |
CANCELED | user canceled. |
identityToken is a cryptographic string that asserts the authentication performed on a session. It contains information about the authenticator and exploiter device, authentication time, token expiration time and authentication subject. This token is signed with the Veridium server's key (configured in the server's properties) so it can be verified by 3rd party entities and the exploiter device can pass this as proof of authentication. E.g. if a client app does biometric authentication but a different service manages user sessions, the client app can hand the received Identity Token after a successful authentication to the session manager service and receive in exchange a short token that it can use on subsequent calls to authenticate and receive authorization.