Skip to content

Commit

Permalink
feat: relocation of ctype config (#78)
Browse files Browse the repository at this point in the history
## fixes KILTprotocol/ticket#2911

The 'Ctype Hash' and 'Attester DID' have been moved to the .env file.
Additionally, if a user does not specify one, it will automatically use
the email ctype. A new ticket has been opened to list valid Ctype hashes
in the readme.md file. See Ticket
[#3103](KILTprotocol/ticket#3103).
Additionally added functionality to use multiple Ctypes added.

## How to test:
Please provide a brief step-by-step instruction.
If necessary provide information about dependencies (specific
configuration, branches, database dumps, etc.)

- Step 1
- Step 2
- etc.

## Checklist:

- [X] I have verified that the code works
- [X] I have verified that the code is easy to understand
  - [ ] If not, I have left a well-balanced amount of inline comments
- [x] I have [left the code in a better
state](https://deviq.com/principles/boy-scout-rule)
- [x] I have documented the changes (where applicable)
* Either PR or Ticket to update [the
Docs](https://github.com/KILTprotocol/docs)
    * Link the PR/Ticket here

---------

Co-authored-by: Aybars Göktuğ Ayan <[email protected]>
  • Loading branch information
aybarsayan and Aybars Göktuğ Ayan authored Mar 13, 2024
1 parent 2782fe6 commit 0882d58
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 85 deletions.
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ DAPP_DID_MNEMONIC=
DAPP_DID_URI=
DAPP_NAME=
JWT_SIGNER_SECRET=

# Email credentials from SocialKYC on the KILT testnet Peregrine
CTYPE_HASH=0x3291bb126e33b4862d421bfaa1d2f272e6cdfc4f96658988fbcffea8914bd9ac
TRUSTED_ATTESTERS=did:kilt:4pehddkhEanexVTTzWAtrrfo2R7xPnePpuiJLC7shQU894aY
REQUIRED_PROPERTIES=Email
10 changes: 5 additions & 5 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"semi": false,
"trailingComma": "none",
"singleQuote": true,
"tabWidth": 2
}
"semi": false,
"trailingComma": "none",
"singleQuote": true,
"tabWidth": 2
}
4 changes: 2 additions & 2 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ nodeLinker: node-modules

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
spec: '@yarnpkg/plugin-workspace-tools'
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
spec: "@yarnpkg/plugin-version"
spec: '@yarnpkg/plugin-version'

yarnPath: .yarn/releases/yarn-3.6.1.cjs
38 changes: 31 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,6 @@ For a user to log in with KILT, it requires:
- one of the cTypes accepted by the dApp.
- issued by one of the dApps _trusted attesters_.

- In this demo, as a default, the dApp requests a credential that contains an email address.
For that we rely on **SocialKYC** to issue email credentials after verifying the user owns it.
Get your

- [credential attested by **SocialKYC** on **_Peregrine_** here](https://test.socialkyc.io).
- [credential attested by **SocialKYC** on **_Spiritnet_** here](https://socialkyc.io).

## Steps to launch the dApp locally

1. [Clone repository and **install** all necessary modules.](#Installation)
Expand Down Expand Up @@ -129,6 +122,37 @@ The following variables are required:
- `DAPP_DID_URI` = _This is the URI of the Kilt DID that identifies your dApp_
- `DAPP_NAME` = _This should be a custom name for your dApp_
- `JWT_SIGNER_SECRET` = _This is secret key (string) that signs the Json-Web-Tokens before saving them in the Cookies_
- `CTYPE_HASH` = _This is the type of credential (CType) your dApp will request from users for login. If you want to specify more than one CType, you can do so by adding a '/' sign between them_
- `TRUSTED_ATTESTERS` = _This is a list of attester DIDs (CSV, separated by ','). Only credentials issued by these attesters will be considered valid. If you are using more than one CType, indicate the groups of trusted attesters by respectively separating them with a '/' sign._
- `REQUIRED_PROPERTIES` = _This is a subset of CType properties (CSV, separated by ',') required to be exposed on credential presentation. If you are using more than one CType, indicate the groups of required properties by respectively separating them with a '/' sign._

### Info about Example/Recommended cTypes

This table provides information on recommended cTypes for SocialKYC credential issuance. SocialKYC is a platform that issues credentials based on user social media presence. The cType-hash is consistent across both Spiritnet and Peregrine to ensure interoperability and consistent verification across the KILT network by using universal identifiers stored on archive nodes.

#### SocialKYC on Spiritnet:

did:kilt:4pnfkRn5UurBJTW92d9TaVLR2CqJdY4z5HPjrEbpGyBykare

#### SocialKYC on Peregrine:

did:kilt:4pehddkhEanexVTTzWAtrrfo2R7xPnePpuiJLC7shQU894aY

Here are the cTypes recommended for SocialKYC:

| Title | CTYPE_HASH | SocialKYC on Spiritnet | SocialKYC on Peregrine | Properties |
| -------------- | ------------------------------------------------------------------ | ------------------------------------------ | ------------------------------------------ | ---------------------------------------- |
| Email | 0x3291bb126e33b4862d421bfaa1d2f272e6cdfc4f96658988fbcffea8914bd9ac | [prod. Spiritnet](#SocialKYC-on-Spiritnet) | [prod. Peregrine](#SocialKYC-on-Peregrine) | Email |
| Twitter | 0x47d04c42bdf7fdd3fc5a194bcaa367b2f4766a6b16ae3df628927656d818f420 | [prod. Spiritnet](#SocialKYC-on-Spiritnet) | [prod. Peregrine](#SocialKYC-on-Peregrine) | Twitter |
| Discord | 0xd8c61a235204cb9e3c6acb1898d78880488846a7247d325b833243b46d923abe | [prod. Spiritnet](#SocialKYC-on-Spiritnet) | [prod. Peregrine](#SocialKYC-on-Peregrine) | Discriminator, User ID, Username |
| GitHub | 0xad52bd7a8bd8a52e03181a99d2743e00d0a5e96fdc0182626655fcf0c0a776d0 | [prod. Spiritnet](#SocialKYC-on-Spiritnet) | [prod. Peregrine](#SocialKYC-on-Peregrine) | GitHubUsername, Username |
| Twitch | 0x568ec5ffd7771c4677a5470771adcdea1ea4d6b566f060dc419ff133a0089d80 | [prod. Spiritnet](#SocialKYC-on-Spiritnet) | [prod. Peregrine](#SocialKYC-on-Peregrine) | User ID, Username |
| Telegram | 0xcef8f3fe5aa7379faea95327942fd77287e1c144e3f53243e55705f11e890a4c | [prod. Spiritnet](#SocialKYC-on-Spiritnet) | [prod. Peregrine](#SocialKYC-on-Peregrine) | First name, Last name, User ID, Username |
| YoutubeChannel | 0x329a2a5861ea63c250763e5e4c4d4a18fe4470a31e541365c7fb831e5432b940 | [prod. Spiritnet](#SocialKYC-on-Spiritnet) | [prod. Peregrine](#SocialKYC-on-Peregrine) | Channel ID, Channel Name |

Note: We only recommend these cTypes and properties for SocialKYC verification. Users are advised to select the appropriate properties based on their verification needs.

Additionally, for access to a broader range of CType Hashes, consider visiting the [CType Hub](https://ctypehub.galaniprojects.de/).

### Setup your environment

Expand Down
20 changes: 11 additions & 9 deletions backend/src/access/login.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { Response, Request } from 'express'

import { emailRequest } from '../credentials/listOfRequests'
import { cTypesToRequest } from '../credentials/cTypesToRequest'
import { buildCredentialRequest } from '../credentials/buildCredentialRequest'
import { verifySubmittedCredential } from '../credentials/verifySubmittedCredential'

import { setAccessCookie } from './setAccessCookie'

// Here you can set which type of credential (cType) your dApp will request users to login.
// You can change it by importing a different one from the list.
const requestedCTypeForLogin = emailRequest

/** First half of the login with credentials.*/
export async function buildLoginCredentialRequest(
request: Request,
Expand All @@ -19,7 +15,7 @@ export async function buildLoginCredentialRequest(
const encryptedCredentialRequest = await buildCredentialRequest(
request,
response,
requestedCTypeForLogin
cTypesToRequest
)
// With this, the extension will know what kind of credential to share
response.status(200).send(encryptedCredentialRequest)
Expand All @@ -37,13 +33,19 @@ export async function handleLoginCredentialSubmission(
const verifiedCredential = await verifySubmittedCredential(
request,
response,
requestedCTypeForLogin
cTypesToRequest
)

// Send a little something to the frontend, so that the user interface can display who logged in.
// The frontend can't read the encrypted credential; only the backend has the key to decrypt it.
// "Email" is capitalized on this cType schema
const plainUserInfo = verifiedCredential.claim.contents.Email
const claimContents = verifiedCredential.claim.contents
// Check if any properties have been provided. If not, send 'Anonymous User' to display on the frontend.
// If any property exists, send object's first attribute value,
// ensuring compatibility with any 'cType'.
const plainUserInfo =
Object.keys(claimContents).length === 0
? 'Anonymous User'
: claimContents[Object.keys(claimContents)[0]]

console.log(
'Decrypted User Info that we are passing to the frontend:',
Expand Down
5 changes: 5 additions & 0 deletions backend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ export const DAPP_DID_URI = loadEnv('DAPP_DID_URI') as Kilt.DidUri
export const DAPP_NAME = process.env.DAPP_NAME ?? 'Web3-Login-Demo'
export const JWT_SIGNER_SECRET = loadEnv('JWT_SIGNER_SECRET')

// Configurable Credential types
export const CTYPE_HASH = loadEnv('CTYPE_HASH')
export const TRUSTED_ATTESTERS = loadEnv('TRUSTED_ATTESTERS')
export const REQUIRED_PROPERTIES = loadEnv('REQUIRED_PROPERTIES')

export let DAPP_ACCOUNT_ADDRESS: string

function loadEnv(name: string) {
Expand Down
44 changes: 44 additions & 0 deletions backend/src/credentials/cTypesToRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as Kilt from '@kiltprotocol/sdk-js'

import { CTYPE_HASH, REQUIRED_PROPERTIES, TRUSTED_ATTESTERS } from '../config'

/** Establish the types of credentials (cTypes) that our dApp will request from users to log in,
* identify which properties are necessary, and specify which attesters we trust.
*
* These settings are defined by the constants imported from the config file.
* Modify the `env` file to adapt it to your preferences.
*/

const cTypeHashes = CTYPE_HASH.split('/').map((s) => s.trim())

const trustedAttesterList = TRUSTED_ATTESTERS.split('/').map((s) => s.trim())

const requiredPropertiesList = REQUIRED_PROPERTIES.split('/').map((s) =>
s.trim()
)

const cTypes: {
cTypeHash: `0x${string}`
trustedAttesters: Kilt.DidUri[]
requiredProperties: string[]
}[] = []

for (let i = 0; i < cTypeHashes.length; i++) {
const trustedAttesters = trustedAttesterList[i].split(',').map((s) => {
const trimmed = s.trim()
Kilt.Did.validateUri(trimmed)
return trimmed as Kilt.DidUri
})
const requiredProperties = requiredPropertiesList[i]
.split(',')
.map((s) => s.trim())
const cType = {
cTypeHash: cTypeHashes[i] as `0x${string}`,
trustedAttesters,
requiredProperties
}
cTypes.push(cType)
}
export const cTypesToRequest: Kilt.IRequestCredentialContent = {
cTypes
}
42 changes: 0 additions & 42 deletions backend/src/credentials/listOfRequests.ts

This file was deleted.

28 changes: 14 additions & 14 deletions frontend/public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"short_name": "Web3 Login",
"name": "KILT Web3 Login",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
"short_name": "Web3 Login",
"name": "KILT Web3 Login",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
5 changes: 2 additions & 3 deletions frontend/src/components/Card.module.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

.card {
padding: 24px;
background: rgba(255, 255, 255, 0.31);
Expand All @@ -8,12 +7,12 @@
-webkit-backdrop-filter: blur(7.1px);
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 8px;
color: white;
color: white;
display: inline-flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 16px;
font-weight: normal;
min-width: 500px;
}
}
2 changes: 1 addition & 1 deletion frontend/src/components/Logo.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
display: inline-block;
color: white;
font-size: 18px;
}
}
51 changes: 49 additions & 2 deletions scripts/genesisEnvironmentVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ const {
// This should be a custom name for your dApp
DAPP_NAME,
// This is secret key (string) that signs the Json-Web-Tokens before saving them in the Cookies
JWT_SIGNER_SECRET
JWT_SIGNER_SECRET,
// This is the CType hash for Email credentials from SocialKYC
CTYPE_HASH,
// These are the trusted attesters for the CType
TRUSTED_ATTESTERS,
// These are the required properties for the CType
REQUIRED_PROPERTIES
} = process.env

async function main() {
Expand Down Expand Up @@ -53,7 +59,10 @@ async function main() {
DAPP_DID_MNEMONIC,
DAPP_DID_URI,
DAPP_NAME,
JWT_SIGNER_SECRET
JWT_SIGNER_SECRET,
CTYPE_HASH,
TRUSTED_ATTESTERS,
REQUIRED_PROPERTIES
}

// find the first element in the object "stairs" that still has an undefined value.
Expand Down Expand Up @@ -110,6 +119,18 @@ async function main() {
case 7:
imploreJwtSecretKey()
break
case 8:
imploreCtypeHash()
break
// ask you to choose a Ctype Hash
case 9:
imploreTrustedAttesters()
break
// ask you to choose a Ctype Hash
case 10:
imploreRequestedProperties()
break
// ask you to choose a Ctype Hash
// if (step = -1):
default:
console.log(
Expand Down Expand Up @@ -240,5 +261,31 @@ function imploreJwtSecretKey() {
)
}

function imploreCtypeHash() {
console.log(
'Please provide the CType Hash(es) inside the .env file using this constant name:.\n',
'Your dApp will only accept credentials of this given Claim Type(s).',
`CTYPE_HASH={CType IDs your dApp consider valid}\n`,
`If you wish to use the default Email Credential settings, please add the following line to your .env file:\n`,
`CTYPE_HASH=0x3291bb126e33b4862d421bfaa1d2f272e6cdfc4f96658988fbcffea8914bd9ac\n`
)
}
function imploreTrustedAttesters() {
console.log(
'Please provide a list for your Trusted Attesters inside the .env file using this constant name: \n',
`TRUSTED_ATTESTERS={lists of trusted attesters}\n`,
`If you wish to use the default Email Credential settings, please add the following line to your .env file:\n`,
`TRUSTED_ATTESTERS=did:kilt:4pehddkhEanexVTTzWAtrrfo2R7xPnePpuiJLC7shQU894aY\n`
)
}
function imploreRequestedProperties() {
console.log(
'Please provide a list of Required Properties inside the .env file using this constant name: \n',
`REQUIRED_PROPERTIES={lists of Properties users should be Required to disclose}\n`,
`If you wish to use the default Email Credential settings, please add the following line to your .env file:\n`,
`REQUIRED_PROPERTIES=Email\n`
)
}

//run the code
main()

0 comments on commit 0882d58

Please sign in to comment.