uPort: DID(Decentralized Identity)におけるユーザ認証について

**【本文】**
**uPort**は、ConsenSysが支援し、***Self Sovereign Identity***(自己主権アイデンティティ)の原則に基づいて開発を進める**DID(Decentralized Identity)**プロトコル。
個人情報をユーザ自身が保有するデバイス(スマートフォン等)と**IPFS**に保管しておき、ユーザに各種サービスを提供する各社や団体は、必要に応じて、ユーザに個人情報共有をリクエストし、一時的に個人情報を閲覧することで、サービス提供者側がユーザの個人情報を保管せず、KYC等を可能にするユーザ・セントリックな世界観を目指している。

uPortそのものは、独自のDIDと言うEthereumで言うところのEOAに相当するアカウント(アイデンティティ)体系を構築し、DIDを通じてユーザ自身のDIDとサービス提供者側のDIDが情報のやり取りを行うだけでなく、一方で、Ethereumにアンカリングし、Ethererum上でEtherやスマートコントラクトを介して他のトークンのやり取りも可能である点が興味深い。
（※但し、現状は開発段階の為、Ethereumメインネット上でのEtherの送金は推奨されない。）

今回、ユーザが端末に保持する個人情報(DID)を取得するサーバーサイド側の処理のサンプルコードを紹介。
（基本的に、uPortの開発ドキュメントを参照しながらで大抵の基本ロジックはほぼほぼ行けそう。）


【今回の環境構成】
---

自端末ローカル環境上で構築（uPort, Rinkeby:Ethereumのテストネットの一つ、等）


【実際のコード】
---

**ReqUserInfo.jsのサンプルコード**


```javascript:ReqUserInfo
const express = require('express')
const bodyParser = require('body-parser')

// setting Info
const fs = require('fs');
const privateKey = fs.readFileSync('.privateKey').toString().trim();
const infuraAccInfo = fs.readFileSync('.infuraAccInfo').toString().trim();

const { Credentials } = require('uport-credentials');
const { Resolver } = require('did-resolver');
const { getResolver } = require('ethr-did-resolver');

const providerConfig = { rpcUrl: infuraAccInfo }
const resolver = new Resolver(getResolver(providerConfig))

const ngrok = require('ngrok')
const decodeJWT = require('did-jwt').decodeJWT
const transports = require('uport-transports').transport
const message = require('uport-transports').message.util

let endpoint = ''
const app = express();
app.use(bodyParser.json({ type: '*/*' }))

//setup Credentials object with newly created application identity.
const credentials = new Credentials({
  appName: 'testUport',
  did: process.env.APPLICATION_DID,
  privateKey: privateKey,
  resolver
})

console.log(credentials);

app.get('/', (req, res) => {
  credentials.createDisclosureRequest({
    appName: 'EMPLOYMENT',
    requested: ['name', 'country', 'phone'],
    notifications: true,
    callbackUrl: endpoint + '/callback'
  }).then(requestToken => {
    console.log(decodeJWT(requestToken))  //log request token to console
    const uri = message.paramsToQueryString(message.messageToURI(requestToken), {callback_type: 'post'})
    const qr =  transports.ui.getImageDataURI(uri)
    res.send(`<div><img src="${qr}"/></div>`)
  })
})

app.post('/callback', (req, res) => {
  const jwt = req.body.access_token
  console.log(jwt)
  console.log(decodeJWT(jwt))
  credentials.authenticateDisclosureResponse(jwt).then(credentials => {

    console.log(credentials)
    console.log('--- USER INFO ---')
    console.log('name:' + credentials.name)
    console.log('country:' + credentials.country)
    console.log('phone:' + credentials.phone)
  }).catch( err => {
    console.log('Error!')
  })
})

// run the app server and tunneling service
const server = app.listen(8088, () => {
  ngrok.connect(8088).then(ngrokUrl => {
    endpoint = ngrokUrl
    console.log(`Verification Service running, open at ${endpoint}`)
  })
})

```

【実際の挙動】
---

+ 今回は、iPhoneのuPortアプリ上でユーザが直接保管する以下の個人情報をサーバ側に共有する。
+ なお、個人情報はIPFS上に記録されており、ニーモニックを保管しておけばDIDそのものと共に、他のデバイスでも復元可能。暗号通貨のwallet操作に慣れている

<img width="30%" alt="IMG_0050.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167054/544a6bd0-9dc9-f5af-7a64-86dde540f6a6.jpeg">

**＜サーバ側＞**

+ サーバ起動

```javascript:console
> node reqUserInfo

e {
  signer: [Function],
  did: 'did:ethr:<server-side DID>',
  resolver:
   r { registry: { ethr: [Function: ethr] }, cache: [Function: t] } }
Verification Service running, open at https://xxx.ngrok.io
```

+ ブラウザ上でQRコードを表示(今回は、localhost:8088)

<img width="30%" alt="reqUserInfo_qr_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167054/b27544aa-62e4-e6a0-d37a-318cec5839da.png">

+ QRコード表示時のサーバ側の挙動
+ ユーザがDIDに保有する[name,country, phone]の情報共有をリクエスト。

```javascript:JWT(Server-sideconsolelog)
{ header: { typ: 'JWT', alg: 'ES256K-R' },
  payload:
   { iat: 1604412887,
     exp: 1604413487,
     requested: [ 'name', 'country', 'phone' ],
     permissions: [ 'notifications' ],
     callback: 'https://xxx.ngrok.io/callback',
     type: 'shareReq',
     iss: 'did:ethr:<server-side DID>' },
  signature:
   'xxx',
  data:
   'xxx' }
xxx
```

**<ユーザ側＞**

+ QRコードをiPhoneのuPortアプリより読み込む
+ uPortアプリ上でリクエスト情報が届く（サーバ側もDIDを持っており、DID経由でリクエストされていることが分かる）

<img width="30%" alt="IMG_0051.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167054/b644f63e-4319-a3ff-9e85-d84e58b32d1c.jpeg">


+ ユーザがリクエストに応じると、サーバ側に開示情報(ユーザのidentity及び付随情報、等)が共有される。

```javascript:JWT(Server-sideconsolelog)

{ did: 'did:ethr:<user DID>',
  boxPub: 'xxx',
  name: 'accius',
  country: 'bitland',
  phone: '000-0000-0000',
  pushToken:
   'xxx' }
--- USER INFO ---
name:accius
country:bitland
phone:000-0000-0000
```

以上、簡単なサンプルコードと実行結果の紹介だが、ユーザ本人であることの認証がDIDの仕組みを通じて実現されている点が注目される。
個人情報そのものはあくまでユーザ側が保持している為、サービスを受ける際に認証さえされれば良いという前提に立つと、サーバ側がユーザの個人情報を直接保管する必要がない点が特に重要。

終わりに
---

**uPort**のような***Self Sovereign Identity***の原則に基づくユーザ・セントリックな仕組みがサードパーティを挟まずプロトコルを通じて実現すれば、アイデンティティを明かす手段が皆無な為に、金融サービスの恩恵から除外されてきた人々にとっても、アイデンティティが付与され、かつ、その同じwallet(アプリ)を通じて金融サービスを受けることが可能となり、金融包摂の観点からもとても意義深い試みだと考えている。

日本においても、金融とアイデンティティは長らく分断され、双方が別々に管理することで情報がサイロ化しており、結果として両者にフリクションな状態が常に発生してきた。（例えば、KYC一つとっても個々の金融機関や市役所等の公共機関が個別に管理し、ユーザ目線では情報登録の重複が発生）
また、一部のBig Tech(Tech Giants)が膨大な個人情報を集中保管することで、個人情報が勝手に使用され（あるいはそれがいつどう使われているのかを知る術がない。）状況も原題を取り巻く課題の一つ。

一方、現代において、DIDと言う概念が概念以上の実装を伴う形で徐々に実現されてきている点を鑑みれば、uPortのような取り組みを技術レベルでも追っていくことは意義深いことのように思う。