This is a Javascript client of the RESTful JSON API offered by the IRMA API server. It offers a library that allows you to use the API server to:
- Verify IRMA attributes. You specify which attributes, the library handles the user interaction and the communication with the API server and the IRMA token (such as the IRMA Android app). Finally, the API server signes a JWT (JSON Web Token) containing the attributes (provided the attributes are valid), after which the library returns this signed JWT.
- Issue IRMA attributes. You put the credentials to be issued in a signed JWT, the library handles the user interaction and the communication with the API server. (The API server does need to allow you to issue these credentials).
- Create IMRA attribute-based signatures (experimental): signature on a string to which IRMA attributes are verifiably attached.
The flow of the various interactions in a typical IRMA session is shown here.
This javascript package contains two parts:
client
: The IRMA Javascript library that you can use on your website if you want to integrate IRMA verification.examples
: Example pages that use various aspects of the IRMA Javascript library.
In case you quickly want to get started with setting up IRMA verification for your website please proceed as follows. First, you need an API server. For testing, feel free to user our API server. It is hosted at https://demo.irmcard.org/tomcat/irma_api_server/
. (Please note that it only allows verifies and issues credentials in the demo domain.)
First, we load the IRMA client-side Javascript library and css:
<link rel="stylesheet" href="https://path/to/webserver/client/irma.css">
<script src="https://path/to/webserver/client/irma.js" type="text/javascript"></script>
Next, we tell irma.js
to initialize, and where to find the API server
IRMA.init("https://demo.irmacard.org/tomcat/irma_api_server/api/v2/");
We can now use irma.js
for a simple verification. First, we specify the verification request:
var sprequest = {
"validity": 60,
"request": {
"content": [
{
"label": "over12",
"attributes": ["irma-demo.MijnOverheid.ageLower.over12"]
},
]
}
};
in this case we would like to check that the user is over 12 years old, and we only accept the irma-demo.MijnOverheid.ageLower.over12
attribute prove this. Next, you need to put the request in a JWT, that depending on the server's configuration, may need to be signed. If the server accepts unsigned JWT's, you can use irma.js
to create one:
var jwt = IRMA.createUnsignedVerificationJWT(sprequest);
After that you call IRMA.verify
when you want to verify the attribute:
IRMA.verify(jwt, success, warning, error);
Since this causes a popup please make sure to bind this to a user action, for example a button, and specify the callbacks if you want to see any result from the call
var success = function(jwt) { console.log(jwt); }
var warning = function() { console.log("Warning:", arguments); }
var error = function() { console.log("Error:", arguments); }
var btn = document.getElementById("myButtonId");
btn.addEventListener("click", function() {
console.log("Button clicked");
var jwt = IRMA.createUnsignedVerificationJWT(sprequest);
IRMA.verify(jwt, success, warning, error);
});
The success
, warning
, error
callbacks are only examples, you may wish to redefine them based on your scenario. Most of this code was taken from the verify
example in examples
.
A full working minimal example is:
<html>
<head>
<link rel="stylesheet" href="https://path/to/webserver/client/irma.css">
<script src="https://path/to/webserver/client/irma.js" type="text/javascript"></script>
<script type="text/javascript">
IRMA.init("https://demo.irmacard.org/tomcat/irma_api_server/api/v2/");
var sprequest = {
"request": {
"content": [
{
"label": "18+",
"attributes": ["irma-demo.MijnOverheid.ageLower.over18"]
},
]
}
};
var success = function(jwt) { console.log("Success:", jwt); alert("Success"); }
var warning = function() { console.log("Warning:", arguments); }
var error = function() { console.log("Error:", arguments); }
var clicked = function() {
console.log("Clicked");
var jwt = IRMA.createUnsignedVerificationJWT(sprequest);
IRMA.verify(jwt, success, warning, error);
};
</script>
</head>
<body>
<button onclick="clicked();">ClickMe</button>
</body>
</html>
For a more complete scenario, see examples/multiple-attributes
(live demo).
Behind the scenes, the IRMA API server produces a signed JWT containing the attributes you requested. irma_js
returns this JWT to you to further handle these verified data in your backend. Naturally, you should always verify this JWT there too. If you want to rely on our server for now, you'll also need its public key. This page explicitly shows the JWT and its content.
Issuing a credential is equally easy. First we build a JSON object describing the credential(s) to issue.
var iprequest = {
timeout: 60,
request: {
"credentials": [
{
"credential": "irma-demo.MijnOverheid.address",
"attributes": {
"country": "The Netherlands",
"city": "Nijmegen",
"street": "Toernooiveld 212",
"zipcode": "6525 EC"
}
}
],
}
};
Then your backend application creates a signed JWT using this request so that the API server can check that you are indeed eligible to issue this credential. Our testing API server is very permissive (only for credentials in the demo domain), but it does require a JWT. As in the case of verification requests, irma.js
offers a convenience function for creating an unsigned JWT. After you have created one, just make a call to IRMA.issue
to issue the credentials:
var jwt = IRMA.createUnsignedIssuanceJWT(iprequest);
IRMA.issue(jwt, success, warning, error);
For a full example, see examples\issue
(live demo).
IRMA signatures are almost the same as verification. We first need to create a JSON object with a signature request:
var sigrequest = {
"validity": 60,
"request": {
"messageType" : "STRING",
"message" : "a test message",
"content": [
{
"label": "over12",
"attributes": [ "irma-demo.MijnOverheid.ageLower.over12" ],
},
]
}
};
messageType
must be "STRING", and message
contains the message you want to sign and content contains the attributes that are used and included in the signature. Next, call IRMA.sign
when you want to obtain the signature from the client:
IRMA.sign(sprequest, success, warning, error);
This will start the protocol in the same way as in the verify case. Note that the web token that will be returned in the success
case contains the IRMA signature.
The IRMA javascript client supports localisation of all its interface elements to other languages. Translations are provided in the client/languages
folder. During the call to IRMA.init()
, a second argument can be provided to localize the interface to a different language. For example, initializing using
IRMA.init("<URL>", "nl");
localizes the interface to the dutch language. When not provided, the IRMA javascript client defaults to english. The interface language can also be changed at runtime using IRMA.setLang("<language>")
.
Some notes on development
First setup the development environment:
npm install -g grunt-cli
npm install compass # unchecked
by installing grunt. Then run
npm install
to install the node dependencies and JavaScript libraries. Finally run
grunt build
to build the libraries and examples. See below for how to setup server URLs for a remote verification server or a local verification server. Alternatively, you can just run
grunt build watch
to keep rebuilding the files as they change. If you specify neither build
nor watch
, build watch
is implied.
Using the flags --client
and --examples
you can specify which of the subfolders should be built. If you specify none of these, all will be built.
This project relies on one URL for verification: The client-side library needs to know the location of the API backend to perform the actual verifications and issuances. This can be specified in your webpage through the call to IRMA.init
.
For the examples in this package, an url is required during the build proces. The default is to use the demo server at https://demo.irmacard.org/tomcat/irma_api_server/
. To use a local verification server, one can specify the server address using the --api_server_url=<URL>
option. For this, you might also be interested in the shortcut explained below.
If you are running a local api server using the irma_api_server
project you might as well use it to host the web pages as well (and thus avoid CORS problems). First, make sure that the assembled output is written to the webapp
directory. If irma_api_server
is in the same directory is irma_js
run:
ln -s ../irma_api_server/src/main/webapp/ build
(Note: if you have already run grunt
before creating this symlink, then a directory named build
already exists. Be sure to remove it first!)
Then simply specify the root of the servlet when running grunt:
grunt --api-server_url="http://<HOST>:8088/irma_api_server/"
If you want to test your application using an external token, make sure that <HOST>
is either is an ip address that the token can reach, or is resolvable to one by the token. You can then run the example by visiting
http://<HOST>:8088/irma_api_server/examples/custom-button.html
or
http://<HOST>:8088/irma_api_server/examples/issue.html
or
http://<HOST>:8088/irma_api_server/examples/multiple-attributes.html