Quick Guide
Introduction
Below is a quick guide on how to integrate Instalogin in your project to test it easily. We are preparing a comprehensive documentation covering all possible use cases and parameters.
Notice: This documentation is work in progress.
Prerequisites
To use the Almefy API you’ll be provided a Key and a Secret, which will be used to authenticate at our API. The binary secret is Base64 encoded.
KEY=5bbf4923faf099a3515a40d9b0e6e6e32c890ef6cd7a8a120657c2f49d2341fe
SECRET=Fw59ctgPG8u4NbDJH7KiO8H1SySAGeDWvE9QrBDxygCPACKOP9DbN/yvHRWJAoYR45dqytYOx4APcAuZ3lSR/w==
Notice: Example Data
Authentication
We use signed Json Web Tokens (JWT) for API authentication. To provide maximum security, we also use additional claims related to the request.
The following example request:
POST /v1/entity/identities/enroll HTTP/1.1
Content-Type: application/json; charset=utf-8
...
{"identifier":"john.doe","sendEmail":true,"sendEmailTo":"john.doe@example.com"}
would require a JWT with a structure similar to this:
// JWT Header
{
"typ": "JWT",
"alg": "HS256"
}
// JWT Claims
{
// API Key
"iss": "5bbf4923faf099a3515a40d9b0e6e6e32c890ef6cd7a8a120657c2f49d2341fe",
// API Host
"aud": "https://api.almefy.com",
// "Issued At" Current Unix Timestamp (seconds since Jan 01 1970)
"iat": 1577833201,
// "Not Before" Current Unix Timestamp (seconds since Jan 01 1970)
"nbf": 1577833201,
// "Expiration Time" Current Unix Timestamp (seconds since Jan 01 1970)
"exp": 1577833211, // Add e.g. 10 seconds to address latency
// Request method, in upper letters
"method": "POST",
// Full URL to the API endpoint
"url": "https://api.almefy.com/v1/entity/identities/enroll",
// The bodyHash below is a SHA256 hash of the request body in the example request
"bodyHash": "cffe073b895526943614212f20207aa982846918476fbde32dcb66e484b010ef"
}
Notice: These are the minimum claims required by the Almefy API.
This JWT needs then to be signed with the API secret provided by Almefy.
Please Notice
For many HMAC SHA256 functions the secret parameter needs to be provided as binary representation of the Base64 encrypted API secret.
Then simply add the signed JWT as an authorization header inside the request:
POST /v1/entity/identities/enroll HTTP/1.1
Content-Type: application/json; charset=utf-8
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOweqwe2241dgweiIw2324ew23qd ...
{"identifier":"john.doe","sendEmail":true,"sebdEmailTo":"john.doe@example.com"}
Enroll Identity
Before a user account can be used with the Almefy app, an Identity for that account needs to be enrolled and a device provisioned. The easiest way to start an enrollment is to send the user an Email with an enrollment QR Code inside. A good starting point could be a "Link with Almefy" button somewhere in the protected frontend or administration backend, which triggers the following API call in the backend (simplified view):
POST /v1/entity/identities/enroll HTTP/1.1
{
"identifier": "john.doe"
}
Notice: Check out the API Enrollment Reference for all available options.
The response is enrollment data with a response status of either 201 (Created) or 200 (Ok, updated), and will look something like this:
{
"id": "1d5e36b89c",
"createdAt": "2020-02-25T08:26:50+00:00",
"expiresAt": "2020-02-25T09:26:50+00:00",
"base64ImageData": "BINARY_DATA",
"identity": {
"id": "0aa249e2-94ca-4bb2-89cf-bc3a329f4aac",
"createdAt": "2020-02-21T10:16:11+00:00",
"locked": false,
"identifier": "john.doe",
"nickname": null,
"label": "john.doe",
"role": "ROLE_USER",
"tokens": []
}
}
This API call, regardless how often it is being called, simply creates or updates an existing identity inside the Almefy system, and sends out an email with a provisioning QR Code that needs to be scanned with the Almefy app. Once done, the enrollment & provisioning is completed, and the user is ready to authenticate using the Almefy app.
Show Auth Image
Add the following few lines to your HTML frontend to show the Almefy auth image used for authentication.
<!-- Place this HTML code wherever the Almefy image should appear -->
<div data-almefy-auth
data-almefy-key="5bbf4923faf099a3515a40d9b0e6e6e32c890ef6cd7a8a120657c2f49d2341fe"
data-almefy-auth-url="/path/to/auth-controller"></div>
<!-- Load the JavaScript library -->
<script defer src="https://cdn.almefy.com/js/almefy-1.0.0.js"
integrity="sha384-9cWXAg8MurIKKZOnt0x5QIm7o6HzOwVT9r03rLTSwkjti7f4SEmJAM1CZPBJkZ1X"
crossorigin="anonymous"></script>
Notice: Please see the JavaScript SDK for list of available parameters
Process Auth Token
The controller configured in the data-almefy-auth-url attribute will receive a signed JWT inside the X-Almefy-Auth
header. A request to this controller will look something like:
GET /path/to/auth-controller HTTP/1.1
Accept: application/json
X-Requested-With: XMLHttpRequest
X-Almefy-Auth: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOweqwe2241dgweiIw2324ew23qd ...
The first thing that needs to be done inside the controller is to extract the JWT from the header and validate it with any JWT utility class using the API secret. Once done, you can retrieve three important claims from the JWT:
{
"jti": "c29a49e4b1", // Challenge Id
"sub": "john.doe", // Identifier
"otp": "1c7eab97" // One Time Password
}
The next step is to use your own internal logic to check, if the user with the identifier from the JWTs sub
claim is actually in your database and enabled to authenticate into your application. As a final step you need to confirm the authentication on the Almefy system by validating the challenge
and otp
claim. This also ensures that the provided data is consumed and not available for further requests:
POST /v1/entity/identities/john.doe/authenticate HTTP/1.1
{
"challenge": "c29a49e4b1",
"otp": "1c7eab97"
}
Please notice, it is recommended to url-encode the “identifier” parameter when calling the authentication endpoint from the Almefy API:
POST /v1/entity/identities/{identifier}/authenticate HTTP/1.1
{
...
}
The response is either a status code of 200 (Ok) or 401 (Unauthorized). At this point the user is successfully authenticated, the session can be set up and user redirected. The embedded Almefy JavaScript handles any redirect response internally, you just have to return the appropriate redirect response (e.g. 301) with the final location from the controller.