Skip to content

What other ways to use Hivesigner auth?

Feruz M edited this page Sep 11, 2020 · 2 revisions

Hivesigner authentication can be used in several ways to give more security for your apps and your users. In this section we will showcase some uses and how you can utilize same techniques in your apps.

As mentioned in other sections of this Wiki, Hivesigner authentication is very simple to grasp if you have some experience with OAuth systems and token verification techniques.

Imagehoster

Imagehoster is opensource community software that helps you to proxy user uploaded images and allows you to create easy user authenticated image uploads with extra benefits (rate limiting based on reputation, blacklist, etc.)

There are couple instance of imagehosters run by different teams, https://images.hive.blog and https://images.ecency.com separately maintained/hosted instance of Imagehoster. You can also start your own instance easily by following Readme and Devportal guides.

If user login to your app with Hivesigner, you can verify user and accept their uploads by utilizing techniques used by Imagehoster, above instances does that and verify access_token for uploads.

POST /hs/:accesstoken

Above endpoint takes access_token and verifies if it was created by same app, in above instances, @hive.blog and @ecency.app, when you setting up your own instance of imagehoster, your users in your app will be able to verify and upload images to your instance. Below is code section to show how verification is done.

    // take access token from url params
    const token = ctx.params['accesstoken']
    //decode access token
    const decoded = Buffer.from(b64uToB64(token), 'base64').toString()
    // parse it into object
    const tokenObj = JSON.parse(decoded)
    const signedMessage = tokenObj.signed_message
    if (
        tokenObj.authors
        && tokenObj.authors[0]
        && tokenObj.signatures
        && tokenObj.signatures[0]
        && signedMessage
        && signedMessage.type
        && ['login', 'posting', 'offline', 'code', 'refresh']
        .includes(signedMessage.type)
        && signedMessage.app
    ) {
        // get username from access_token
        const username = tokenObj.authors[0]

        let account = {
            name: '',
            reputation: 0,
        }
        // initialize Hivesigner with user access_token and app_account from imagehoster config
        const cl = new hivesigner.Client({
            app: UPLOAD_LIMITS.app_account,
            accessToken: token,
        })

        await cl.me(function (err: any, res: any) {
            if (!err && res) {
                account = res.account
                APIError.assert(account, APIError.Code.NoSuchAccount)

                ctx.log.warn('uploading app %s', signedMessage.app)
                APIError.assert(username === account.name, APIError.Code.InvalidSignature)
                // user access_token should have same signed app account as imagehoster defined app account.
                APIError.assert(signedMessage.app === UPLOAD_LIMITS.app_account, APIError.Code.InvalidSignature)
                APIError.assert(res.scope.includes('comment'), APIError.Code.InvalidSignature)
                // check if user has authorized posting authority to app_account
                if (account && account.name) {
                    ['posting', 'active', 'owner'].forEach((type) => {
                      account[type].account_auths.forEach((key: string[]) => {
                        if (
                          !validSignature
                          && key[0] === UPLOAD_LIMITS.app_account
                        ) {
                          validSignature = true;
                        }
                      });
                    });
                }
            }
        });
      }

This is simple verification method use only app accounts to verify access_token and validity of user.

Backend security

More advanced backend security could also be achieved with access_token from hivesigner. You can make sure only user you want can access certain content, this way you don't have to add your own security layer just utilize what Hivesigner already provides you.

Below simple code makes sure that access_token is indeed signed by user. And checks to makes sure keys matches perfectly.

    const message = JSON.stringify({
                signed_message: signedMessage,
                authors: tokenObj.authors,
                timestamp: tokenObj.timestamp,
        })
    let hash = cryptoUtils.sha256(message)
    ...
    account[type].key_auths.forEach((key: string[]) => {
        if (
           !validSignature
           && PublicKey.fromString(key[0]).verify(hash, Signature.fromString(signature))
        ) {
              validSignature = true;
          }
    });

This combined with Imagehoster verification is perfect combination of security you can get in your app to serve user specific pages like drafts, bookmarks, images, etc.

Login without authority

There are some cases where you don't need posting authority from your users on your app. Couple examples are https://hivesearcher.com and https://openhive.chat where use case and actions are off-chain, no on-chain operations. Hivesearcher and Openhive.chat authorizes/logins Hive user and allows them to use their application with Hive account, without any chain operations. This is perfect use case for off-chain applications. In essence, make any web2.0 application web3.0 by using blockchain for authentication.

Try them out and let us know if you are able to secure your apps to the best of your ability to make sure user related data is not affect by malicious actors.

Clone this wiki locally