Skip to content

aceblockID/aceblock-login-npm-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Contributors Forks Stargazers Issues MIT License LinkedIn


Logo

Aceblock OIDC client npm package

This is opesource project of npm package from Aceblock, to help you easilly protect your web application.
Explore the docs »

View Demo · Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. Contributing
  6. License
  7. Contact

About The Project

New tehnologies are comming and with them new possibillities, so here we are working on self sovereign identity, for enabeling end users to create their own identiti and with that to give them oportunity to gain controll over personal data (age, contact data, hobbies, ect.).

This project is just tiny part of the whole structure and enables businessess to easily implement register and login of the potential customer into their web portals. At the same tame it makes it easi to implement authentication an authorisation of customers on any web app endpoint.

Here's how login and register works for user:

  • User installs our Aceblock IDentity app on their mobile phone and creates their identity by entering their data
  • Business creates Aceblock IDentity for their domain/web portal
  • Business installs aceblock-login-npm-template npm package and enters formerly created ID (detaild instructions for implementing are [here][instalation instructions])
  • User opens businesses login/register page -> qr code shows -> user scans qr code with his web app and confirms connection and Voilà - User is registered and loged in to the web portal - web page automaticaly redirects from login page to user page

Built With

This section should list any major frameworks that you built your project using. Leave any add-ons/plugins for the acknowledgements section. Here are a few examples.

Getting Started

Prerequisites

Befor you start setting up the project you need to install:

  • npm

    npm install npm@latest -g
  • For testing api callback you will need software for simulating api requests, the best for this is Postman

  • ID token for testing:

        eyJhbGciOiJFUzI1NksifQ.eyJhdWQiOiJodHRwOlwvXC9zc2kuYWNlYmxvY2suY29tXC9hdXRoXC9zc2lhYXNcL2NhbGxiYWNrIiwic3ViIjoiV2RCRmNueUlzRmlnUGNRQ19lQ0daOUxSUml4S3VaNF9jNWQtMVNGdG1OQSIsImlzcyI6Imh0dHBzOlwvXC9zZWxmLWlzdWVkLm1lXC8iLCJzdWJfandrIjoie1wia3R5XCI6XCJFQ1wiLFwiY3J2XCI6XCJzZWNwMjU2azFcIixcInhcIjpcInlQNWZpSXB3VnBmcmFLcF9ETXpBYzU1Yk9fSU5zSTJfR21FbzlYdTZ5LVFcIixcInlcIjpcIjFGNkRTbnNLTW80RWRNU3dPbnNVa1dzX3RpZnpOYnhRZG1QczFWS3VlV3NcIn0iLCJwaG9uZV9udW1iZXIiOiJTb21ldGhpbmcgc29tZXRoaW5nIiwiZXhwIjoxNjQwOTk1MjAwLCJpYXQiOjE2MTAwMDQ2NzMsIm5vbmNlIjoiMmU3ZGU0YzQtMjRmMS00NjZmLWExNTMtYmMyNjI0NjE0ZWVkIiwiZGlkIjoiZGlkOmFjZToweDNiYjY3MjU2OGU5YTlhODljZGJlNzA0NzNjMjE5ZmEyMThjMGRjZTMxOTEwN2JlZDJjYjAxNGZiZjFiNmZiNjQiLCJlbWFpbCI6IlNvbWV0aGluZyBzb21ldGhpbmcifQ.BLhn-5jhvP0iMvpTtAUlp3lIuyPvn3T3kUBpTipjPdMbBTNOJFK6z1dey8NO1HZE53-1E_pvyk54ehyexEZTUg

Installation

  1. Get a free API Key at https://example.com

    git clone https://github.com/aceblockID/aceblock-login-npm-template.git
  2. Install NPM packages

    npm install
  3. Create config.js file and enter your DID address in config.js

         const env = process.env.APP_RUN_OPTION || 'dev';
         
         const dev = {
         app: {
             port: 4090,
             redirectUrl: '/user'
             bcURL: 'https://ssi.aceblock.com/rpc',
             IPFSclient: '/dns4/ssi.aceblock.com/tcp/5001',
             contractAddress: '0xcEe408DA63635f2bD9A1608cCDC354F1a506f2b5',
             contractAbi: [{ "constant": true, "inputs": [{ "name": "DIDs", "type": "bytes32[]" }], "name": "getDIDdocAddress", "outputs": [{ "name": "DIDdocs", "type": "string[]" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [{ "name": "DID", "type": "bytes32" }], "name": "getDIDdocAddress", "outputs": [{ "name": "DIDdoc", "type": "string" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [{ "name": "ethAddress", "type": "address" }], "name": "getDID", "outputs": [{ "name": "", "type": "bytes32" }], "payable": false, "stateMutability": "view", "type": "function" }],
             didDocSchema: __dirname + '/didDocSchema.json',
             JsonldSchema: __dirname + '/JsonldSchema.json'
         },
         qrjwt: {
             did: 'id:ace:0x1fb5ce0b0c0c09efe1a8f448d0d268365ed9d02dd34a6c2ffa56cc1626a95c02',
             callbackUri: 'http://localhost:4070/callback',
             essClaimFields: ['email', 'phone_number', 'did'],
             volunClaimFields: ['name','address'],
             issuer: "https://self-isued.me/" 
         },
         cbjwt: {
         
         }
         }
         
         
         const config = {
         dev 
         }
         
         module.exports = config[env];

    Add code to server.js:

        const config = require('./config/config');
  • Acquire did address for your domain and insert it in config file
  • Set field essClaimFields with fields that you will require from customer
  • Set field volonClaimFields with fields that will be optional for your customer
  • Set port field on which your app server is running
  1. Install aceblock-oidc-client npm package: sh npm install aceblock-oidc-client

    Add code to server.js:

        const {qrCodeValues, idTokenVerification} = require('aceblock-oidc-client');
  2. Install express-session npm package:

        npm install express-session

    Add code to server.js:

        const session = require('express-session');
        const crypto = require('crypto');
        
        // Session handling
        app.use(
        session({
            secret: crypto.randomBytes(32).toString('hex'),
            resave: false,
            saveUninitialized: false
        }));
  3. Install cookie-parser npm package:

        npm install cookie-parser

    Add code to server.js:

        const cookieParser = require('cookie-parser');
        
        app.use(cookieParser());        
  4. For rendering pages install ejs npm package:

        npm install ejs

    Add code to server.js:

        const path = require('path');
    
        // ejs engine and views folder
        app.set('view engine', 'ejs');
        app.set('views', path.join(__dirname, 'views'));
  5. For socket connection instal socket.io npm package:

        npm install socket.io

    Add code to server.js:

        const socket = require('socket.io');
        
        // Start app
        const server = app.listen(port, console.log('App is running on port ' + port));
        
        // Set up socket.io connection
        var io = socket(server);
        
        io.on('connection', (socket) => {
        io.to(socket.id).emit('conn', socket.id);
        socket.on('onload', (data) => {
            socket.nonce = data.nonce;
        });
        });
  6. Create login: a. Create api call with code:

        // Temporary usage for testing purposes
        const nonce1 = '2e7de4c4-24f1-466f-a153-bc2624614eed';
    
        app.get('/#', async (req, res) => {
        const did = config.qrjwt.did,
        callbackUri = config.qrjwt.callbackUri,
        essClaims = config.qrjwt.essClaimFields,
        volClaims = config.qrjwt.volunClaimFields;
        const {imgTag, jwt, nonce, uri} = await qrCodeValues.create_qrcode(did, callbackUri, essClaims, volClaims);
        res.render('login', {qrCodePlaceholder: imgTag, qrCodeContent: jwt, sessionNonce: nonce1});
        });

    b. Create login.ejs page in views folder with code:

        <!DOCTYPE html>
        <html lang="en">
        <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Login page</title>
        <script src="/socket.io/socket.io.js"></script>
        </head>
        <body>
        <h1>This is Login page</h1>
        <div id="qrCode"><%- qrCodePlaceholder %></div>
        <p></p>
        <p><strong>This is content of qr code: </strong><div id="qrCodeContent"></div></p>
        <a href="/">Back to home page</a>
        <p>Here are links to other pages:</p>
        <p><a href="settings">Link to settings page</a></p>
        <p><a href="stats">Link to statistics</a></p>
        <p><a href="user">Link to user settings</a></p>
        <p><a href="logoff">Log off</a></p>
        <script>
            // Make socket connetion
            const socket = io.connect( 'http://localhost:4090');
            //
            const qrCode = document.getElementById("qrCode");
            // Add event emmiter
            function sendNonnce(data){
                socket.emit('onload', {
                    nonce: <%- JSON.stringify(sessionNonce) %>,
                    socketId: data
                });
            }
            // Listen to events
            socket.on('conn', (nonce) => {
                sendNonnce(nonce);
            });
            socket.on('redirect', (redirectUrl, idToken) => {
                document.cookie = 'idToken=' + idToken + '; max-age=600; samesite=strict';           
                window.location.href = redirectUrl;
            });  
        </script>
        </body>        
  7. Add token verification api callback code:

    Add code to server.js:

        // Token verification
        const verifyIdToken = idTokenVerification.initVerIdToken(config);
        
        // api call for token verifiaciont
        app.post('/callback', verifyIdToken, (req, res) => {   
        const location = config.app.redirectUrl;
        const idToken = req.headers['id_token'];
        const tokenPayload = req.payload;
        const rnonce = tokenPayload.nonce;
        console.log(rnonce);
        let json = io.of('/').sockets;
        let socId = getSocketId(json, rnonce);
        // send info to socket for redirection and saving token to cookie
        io.to(socId).emit('redirect', location, idToken);
        res.json({
            nonce: rnonce,
            socketId: socId
        });
        });
        
        // extract socket id from sockets object
        function getSocketId(json, rnonce) {
        let values = [...json.values()];
        let soc =  values.find(socket => socket.nonce === rnonce);
        let socketID;
        if (soc) {
            socketID = soc.id;
        }
        return socketID;
        }        
  8. To protect endpoints add token verification to the rest of the api calls that need to be protected by adding “verifyIdToken” to call as here:

    Add code to server.js:

        app.get('/stats', verifyIdToken, (req, res) => {
        res.render('stats');
        });        
  9. Add log off functionality by setting idToken cookie value to some new value or maxAge to -1 which means that cookie gets deleted (or both):

    Add code to server.js:

        // Log off functionality
        app.get('/logoff', (req, res) => {
        // add functionality for to log off
        res.cookie('idToken', 'empty', {maxAge: -1, sameSite:'lax', httpOnly: false});
        res.redirect('/');
        });        

Usage

Here are four simple steps how to test this example:

  • Start the project with
        node server.js
  • Open web browser and enter url (enter same port number as is in project):
        http://localhost:4070
  • click on Login link, if everything is ok, qr code should be displayed
  • now open Postmen application and in dropdown menu select POST option and next to it enter localhost:4070/callback (with same port number as in web browser)
  • under url, select Headers tab and under KEY enter id_token and under value enter id token value stored up in this readme under Prerequisites then hit button send and go back to web browser. If everything is ok, page should be redirected from login qr code to user page.
  • you can also test if you can access other links where you have added protection (as described in 12. step of instalation)
  • also you can test if log off works by clicking on link logoff and after that on protected pages - access should be forbidden

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE for more information.

Contact

Gregor Sajovic - @aceblockcom - gregor.sajovic@netis.si

Project Link: https://github.com/aceblockID/aceblock-login

instalation instructions

About

Template for testing aceblock-OIDC-client npm package

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published