Technical Review of Civic's Secure Identity Platform

Scott Brady
Scott Brady
Blockchain Identity

Recently I’ve been looking into blockchain for decentralised identity and authentication. I’m not sure how I feel about blockchain for authentication yet, but I can definitely see the befits of having some sort of decentralised identity system. It turns out there are a lot of identity blockchain projects out there already, some even have released products (and yes, others already gone bust).

Civic

I like learning by doing, and from my initial research I’ve found Civic to be one of the more popular platforms. So, what I’m going to do is dig into the technical aspects of the Civic platform and, in a separate article, integrate with it using ASP.NET Core.

A quick note about my background, I work with identity and access control systems, focusing on authentication & authorization protocols, such as SAML, WS-Federation, OAuth, and OpenID Connect. It’s using this technical experience that I will be reviewing Civic’s platform. This review has been performed unsolicited and is not affiliated with my employers.

I’m not going to dig into their use of the blockchain for this review, as I’m not an expert on this subject. Instead I'm going to focus on their current SIP product at time of publication, and how it integrates with your typical website for authentication.

Skip to the conclusion.

Civic ($CVC)

Civic’s Secure Identity Platform (SIP) is a blockchain used for real-time authorization to allow a third part to access a user’s identity. The decentralised aspect comes from who confirms/verifies the identity data. When a third party is authorized to access a user’s identity, the identity data is sent through the blockchain, and various validators have to agree that the user is who they say they are. This check uses a range of public records that the verifier may hold (e.g. their social media accounts or contact information).

Civic have a nice little intro to their identity product from the user’s perspective:

In words that I understand: it gives the user (the owner of the identity) control over what data is shared with external parties and the power of consent. Much like the OAuth authorization protocol.

One of the central ideas of Civic, is to have reusable identity, where companies no longer need to verify identities from the ground up each and every time. This reduces fees and processing time (low fees with no middlemen is one of its big selling points).

Civic seem to target financial institutions, which isn’t surprising considering the CEO’s background. How successful adoption will be outside of the cryptocurrency arena will be though, is yet to be seen.

You’ll see this identity verification process called “Know You Customer” (KYC) a lot when dealing with financial institutions.

Civic currently has a suite of non-blockchain related products. These are meant to generate revenue whilst Civic ID is marketed to governments & businesses:

Architecture

The process of accessing this identity looks a lot like the OAuth Authorization/Delegation protocol:

Civic SIP Architecture

So, in this case the:

  • Identity Requester is the Client Application/Relying Party
  • User is the Resource Owner
  • User’s Identity is the Protected Resource
  • Blockchain (the SIP) + Identity Partner (the attester) is the Authorization Server

So, in terms of architecture, it’s nothing we haven’t seen before.

Blockchain

Civic uses the Bitcoin blockchain for identity verification. According to the whitepaper, it uses rootstock to facilitate smart contracts.

Based on the current implementation, I’m unclear as to how the Civic tokens fit into the picture. There’s information out there about users being paid for providing identity info, verifiers for verifying identity, and similar scenarios, but I’m not seeing any evidence of that yet.

As I said in the intro, I’m going to focus on the current SIP product and how it integrates with standard websites for authentication.

Whitepaper

You can read the initial whitepaper from token sale here.

Civic Secure Identity Application

Users access the SIP by downloading the Civic Secure Identity App (Civic App). Registration includes configuring their identity in the app and then verifying it with Civic. Civic doesn’t store Personally Identifiable Information (PII), instead user data is stored locally in the mobile app. This includes the users private key. Any transactions then require biometric proof of identity (facial or voice recognition, or thumb print).

Let’s start as an end-user of the product, and download Civic’s mobile app. I use an iPhone, so this is the version of the app that I’ll be testing with. Civic ranks pretty high if you search for “identity”.

Civic Appstore

Once we load the app, we get a nice little intro:

Civic App Intro Screen 1 Civic App Intro Screen 2 Civic App Intro Screen 3

The last one is a kind of funny, where the app is requesting either touch ID or a passcode. So maybe not the full biometrics that the whitepaper talked about, instead it’s just the usual device security. Whilst this is good for iOS (it costs a couple million dollars to get past this), it is debatable for Android devices. That said, even the iOS passcodes and touch ID are under some scrutiny these days. I wonder if it accepts iPhone X face ID?

Right now, I’m only able to input my email address and phone number. Once you enter one of these, Civic will verify them by sending a code via email or SMS respectively. Verification messages were received within seconds, although the app did crash when I initially tried adding my email address.

Civic Verification Email

This email wording is a little off. If someone is attempting to use your email address to sign up to a service, then the user needs to be proactive and let Civic know that someone is trying to impersonate them. You shouldn’t be telling users to ignore this.

As an end-user, the app feels like an alternative to password authentication at the moment. It’s early days, but for now I’m not seeing the ability to front-load my account with address, passport, or driver’s license details. It turns out these features are part of the Civic KYC Service, a new addition to SIP as of late January 2018, and are currently locked away behind a contact form, and, as far as I can tell, only available to users in the US.

Civic App Security

Civic states that using Civic SIP is safer than physical ID’s as they can be stolen. What if the phone (private key & user data) is stolen? You’re relying on, debatably unreliable, biometric data or a passcode to stop access to the app. The sales material mentions a data revocation process, but I can’t find any evidence of that within the app or portals.

With the KYC features, I’ve seen it mentioned that a user can only have a single Civic SIP account. I assume this is based on some sort of unique identification from a national authority for the user. This increases my concern about theft. If I have my phone stolen (again), do I lose my identity?

Civic states that user data is encrypted on the device. I’d like to see more evidence of this. By evidence I mean, clear implementation details such as using the secure storage, algorithms used, etc. Don’t worry, providing this information does not make your application any less secure (unfortunately a common misconception), but as a security product it’s important to build trust and show you are using best practices.

Integration Portal

Before we can integrate with Civic SIP, we need to register our application within Civic. This involves using the integration portal.

The nice thing about this portal is that Civic eat their own dog food; to sign in or register you have to use Civic SIP!

So, if we try to log on, we are presented with a QR code.

Civic Portal Signin

And if we scan this using our Civic App, we’ll be asked if we’re okay sharing our personal details with this application:

Civic Portal Signin

And then we’ll be registered/logged in.

QR Code

Civic mentions the use of other methods of communicating with the Civic App (Bluetooth low energy, QR code, and near field communication), much like the OAuth Device Flow. But looking at that list, it’s clear that QR codes are currently the most user friendly and something most people now recognize.

This QR code is then scanned by the Civic App to generate the consent request to the user. Once consent has been given, the app then sends the identity data back to Civic. Once this has been verified, the client application, who has been polling the Civic authorization servers, will receive the user data.

To access the integration portal, we do need to give up some more data directly to the portal, such as name, company name, and company domain.

Registering an Application

To register a new application within Civic, we need to provide the following data:

  1. Application Name
  2. Whitelisted Domains (domains that be allowed to display the QR code)
  3. Logo (minimum of 400px x 400px)

All three are required, including the logo. This logo must be a url to an image, which was a bit annoying.

You’ll then be given a load of keys, which you must save now before continuing:

  • Signing private & public key
  • Encryption private & public key
  • Secret

We’re now good to go. Note that the application is currently in testing mode, before going live you have to submit your app for review. I accidentally pressed the go live button the other day, but haven’t heard anything from Civic in over a week.

Integration Portal Security

I have a small concern that I want to raise regarding the security of the Civic integration portal. Luckily, it is simple to address.

When you log in, session data is stored in the browsers local storage. This is fine; however, it contains clear text personally identifiable information. Since this is in local storage, this has been written to disk. Which is illegal in some countries.

A simple solution is to store this data in session storage instead. This won’t change the user experience, since the portal has a fairly short window for expiration or for expiration after inactivity.

I had some other issues with their integration portal, namely when coming back to an expired session the next day and still being able to see all of my data until I navigated away (though this might just be a Firefox “feature”), and a few failed authentication attempts on the session expired page which could only be fixed by going to main login page and authenticating there.

Integrating with Civic SIP

Existing Integration Libraries

On the developer documentation, there is currently only one language option: JavaScript. This is a combination of client side JavaScript and server side Node.js, where an authorization code is retrieved client side, and then sent server side to be exchanged for user data.

There’s also a Java library and a developer bounty program for a Ruby library & an Angular plugin.

ASP.NET Core Implementation

I really don’t like moaning and not contributing anything, so alongside this article I’ve released another called “Integrating with Civic SIP using ASP.NET Core”. In this article we go through each request that is made to Civic, and get it working in ASP.NET Core. It is the basis for the following integration review.

ChainAuth

Yes, ChainAuth™.

We’ve already gone into how the Civic authorization flow is just a variant of OAuth. Why have you implemented your own authorization protocol? It’s 2018, we should not be writing proprietary authorization protocols.

Civic SIP is a distributed identity verification service. Why does it need a proprietary authentication/authorization protocol? This problem space has already been solved.

ChainAuth

Okay, so this diagram is a little misleading. Currently, the identity requester (at least for the SIP login process that is currently available), does not talk directly talk to the blockchain. Instead it is talking to Civic. When the user logs in, they do not send their data to the Identity Request. No, you guessed it, they talk to Civic. Civic is the authorization server.

Just because the user is sending their identity data (the protected resource) via the authorization server, doesn’t mean that the flow is any different. It’s still all about authorizing and delegating access to that protected resource. You know, that thing OAuth does.

I’m wondering if what we see from Civic SIP currently is just a proof of concept. Are the KYC features going to enable client applications to talk directly to the blockchain? Will Civic redeem this by depreciating this current system once their full product is ready?

The use of proprietary, trademarked protocols, instead of using open standards, is a huge barrier to entry for developers, and a huge security risk for users. I cannot stress enough how bad of a decision this is.

What makes this decision even harder to understand is that banks are currently implementing “open banking” thanks to PSD2 (Payment Services Directive), which, you guessed it, uses OAuth and OpenID Connect.

Civic do not have any requirements that mean they cannot use OAuth or OpenID Connect. If Civic truly believe that OAuth is not the right fit, then they should have at least built upon the protocol, not tried to completely reinvent the wheel.

It’s even more strange when you see the CEO says that they “chose the blockchain because they didn’t want to use any proprietary software or infrastructure”. They keep selling ChainAuth as better than OAuth, but from their explanation the of protocol, it’s clear there are some fundamental misunderstandings about OAuth, or maybe just outdated knowledge.

Unfortunately, as is the case with custom protocols that haven’t been created by large groups of professionals with decades of experience on that niche subject, and without years of improvements or real-life usage in high risk systems, the ChainAuth implementation leaves a lot to be desired…

Integration Review

Okay, as you might have guessed, I’m going to be nasty for just a little longer. There’s light at the end of the tunnel, bear with me.

There’s some odd design decisions in the Civic APIs (ChainAuth?), and some of them have left me completely baffled.

As a brief overview we have to perform the following steps to swap an auth code for user data:

  1. Create a signed (ES256) JWT containing the following (nested within a “data” claim)
    1. method = POST
    2. path = scopeRequest/authCode
  2. Create a hash (HMAC SHA256) of the Authorization Code (but now called the authToken)
  3. Use an authorization header with the JWT and hash concatenated with a period, with a scheme of “Civic”
  4. POST to the Civic API with the authToken in the body
  5. Verify the signature of the response JWT (wrapped in a JSON response)
  6. Find the value of the data claim in the JWT and manually decrypt it

For more details check out my ASP.NET Core integration guide, or the official developer documentation.

Let’s start with the initial auth code exchange. Why not put the authCode/authToken in the JWT which we then sign? What is the purpose of putting it in the post body, and then adding an extra hash of the body onto the authorization header? Is it because Civic trusts HMAC over ECDSA? This seems like extra work for no benefit.

Note that this initial auth code can be replayed and swapped for user data until expiration.

Also, why the method and path values in the JWT? Is this to try and validate that the token isn’t being reused on a different endpoint? Wouldn’t a standardised approach for scoped access be better here? And why do these need to be nested within another object?

For the user data response, why is JSON Web Encryption (JWE) not being used? This eliminates the need for the user data JSON response structure (e.g. encrypted & alg), and the JWT containing an encrypted claim. Instead, an encrypted JWT, structured to a standard, can be sent back and everyone can use their usual JWT library to handle decryption for them. This current custom approach increases the barrier to entry for developers and adds no benefit.

I worry that some of these design decisions are security through obscurity or due to a misunderstanding of security & authentication best or even modern practices. This stuff has already been solved by common, open standards.

Closing Thoughts

Implementation

I was really impressed with Civic until I realised they had rolled their own authentication protocol. Not only is this a bad idea from a security perspective, but it also makes adoption harder. At the moment, there is only support for Node.js and Java. To get support for more languages, Civic is running developer bounty programs, meanwhile, there are mature OAuth and OpenID Connect libraries for most languages already. Civic is going to have a hard time getting developers to adopt their platform when they supply a very small number of client libraries.

As a user I really liked using Civic, and I was devastated when I started to look into the implementation and found a custom auth protocol.

Sure, the OAuth Device Flow specification (the QR code and polling parts) is only just being finalised, but that’s only one small part of the story. Look at how much custom code we had to do in our ASP.NET Core implementation, just to exchange an authorization code. This part of the process could have used existing OAuth libraries and could have been 10 lines of code at most.

There is nothing protocol-wise that Civic has implemented that hasn’t already been solved by OAuth and OpenID Connect, apart from the generation of QR codes, and even this is something you’ll see soon supported thanks to the OAuth Device Flow.

My next worry is that Civic’s current authentication process is only suitable for confidential client applications; clients who can keep a secret. A whole new design is going to be necessary for integration with public applications such as single page applications, and native apps such as mobile and desktop. These are problems that OAuth has already solved.

Another problem is the upcoming implementation PSD2 (Payment Services Directive). Banks and financial institutions are all in the process of implementing “open banking”, which, you guessed it, uses OAuth. Since these companies are Civic’s target audience, this feels like a major missed opportunity.

Product

The idea behind Civic itself, is fantastic. Self-sovereign identity and clear, reliable KYC where the user has control is certainly the way forward. How many of us have recently jumped onto cryptocurrency exchanges and had sent them pictures of our passport or drivers license, just to prove we are who we say we are? By using Civic, the exchange will trust Civic and its trusted identity verifiers, instead of receiving this sensitive data themselves and having third parties verify the data, unknown to the user.

I don’t know if I would call this distributed identity, but rather distributed identity verification. Currently authentication is still centralized to Civic. You still rely on them (and their trusted partners) to say you are who you say you are, and you rely on their servers being online to log into a site, blockchain or not.

Distributed KYC products such as Civic are the first step towards regaining ownership of your identity data, and no longer appearing on have I been pwned on a weekly basis.

It’ll be massive a coup if they get this into financial institutions and banks. But getting those to trust Civic is where I imagine the challenge will be, nevermind the custom authentication protocol. It’s definitely a strong contender to replace the identity verification found on cryptocurrency exchanges.

Civic really should have used OAuth and OpenID Connect, instead of rolling their own authentication protocol. I can already see issues in their implementation, and by using open standards they wouldn’t need to be asking the community to create libraries for them (hundreds already exist). Civic, if you’re reading this, take a close look at OpenID Connect & the OAuth Device Flow. This is what you’ve tried to re-implement.

Hire in a consultant. It’s not too late to fix this.

Further Reading

Do you have another identity blockchain product that you think is better or worth a review? Let me know in the comments.