title | category | type | source |
---|---|---|---|
Getting Started with uPort Credentials |
uport-credentials |
content |
In your application, you must first configure your uPort object with an identifier and a private key (or signer function). There are several ways to instantiate a credentials object. The most common approach is to save a DID and private key on a server for your application and create a credentials instance from your application's unique private key. Signed JWTs for requests and verifications can then be passed to a client-side application, and presented to a user using a QR code or via another transport.
import { Credentials } from 'uport-credentials'
import { Resolver } from 'did-resolver'
import { getResolver } from 'ethr-did-resolver'
const providerConfig = { rpcUrl: 'https://mainnet.infura.io/<YOUR INFURA PROJECT ID>' }
const resolver = new Resolver(getResolver(providerConfig))
// For ethereum based addresses (ethr-did)
const credentials = new Credentials({
appName: 'App Name',
did: 'did:ethr:0x....',
privateKey: process.env.PRIVATE_KEY,
resolver
})
At times, you might want identities to be created dynamically. This can be accomplished with the static
Credentials.createIdentity()
method, which generates an Ethereum keypair and returns an object containing the
associated DID and private key. This method is not intended to be used in a react-native context, if you are developing
a react-native app please use the react-native-uport-signer
to generate Ethereum Keypairs.
// Create a credentials object for a new identity
const {did, privateKey} = Credentials.createIdentity()
const credentials = new Credentials({
appName: 'App Name',
did,
privateKey,
resolver
})
You can request information from your user, by creating a Selective Disclosure Request JWT. When this is presented to a
user via a QR code or another transport, they will be prompted to
approve sharing the request attributes. All requests will return a user's DID
.
credentials.createDisclosureRequest().then(requestToken => {
// send requestToken to browser or transport
})
A selective disclosure request JWT can ask for specific private data, and/or provide a URL to which a mobile app should send a response.
credentials.createDisclosureRequest().then({
requested: ['name', 'phone', 'identity_no'],
callbackUrl: 'https://....' // URL to send the response of the request to
}).then(requestToken => {
// send requestToken to browser or transport
})
If you need to know the users address on a specific Ethereum network, specify its networkId
(currently defaults to
Mainnet 0x1
). In this case be aware that the address
returned will be the address on the public network (currently
Mainnet) for the user's profile. The requested network address will be in the networkAddress
field and will be MNID
encoded.
// Request an address on Rinkeby
credentials.requestDisclosure({networkId: '0x4'}).then(requestToken => {
// send requestToken to browser or transport
})
When a response JWT is received, it can be parsed and verified via the verifyDisclosure()
method, which checks the
validity of the signature on the JWT, as well as the validity of the original disclosure request, which is expected as
part of the response.
credentials.verifyDisclosure(responseToken).then(verifiedData => {
// Do stuff with verified data or transport
})
To ensure that the response received was created as a response to your selective disclosure request above, the original request is included in the response from the mobile app.
The verification rule for the Selective Disclosure Response is that the issuer of the embedded request must match the
did in your Credentials object and that the original request has not yet expired. This is to be sure that when
requesting data from a user, only a response to your initial request will be accepted as valid. If you would like to
consume an arbitrary signed JWT that is not part of a particular selective disclosure flow, you can use the
verifyDisclosure()
method to skip the challenge/response check.
As part of the selective disclosure request, you can also ask for permission from your users to communicate directly with their app. With a push token, you can configure a transport to send JWTs via push.
credentials.createRequest({
requested:[...],
notifications: true
}).then(requestToken => {
// send to the browser
})
If the user approves the use of push notifications, the selective disclosure response will contain a pushToken
field,
which can be saved when the response is received and verified.
credentials.verifyDisclosureResponse(responseToken).then(verifiedData => {
// Store push token securely
doSomethingWith(verifiedData.pushToken)
})
In addition to requesting and verifying information, you can also sign new data on behalf of your application and share
it with your users in the form of attestations, also known as verifications. By presenting an attestation to a user,
you are making a claim about them, and are attesting to its truth with your application's signature. Exactly what
information your app should attest to depends the context -- If you're a financial institution, you may be able to
attest to KYC related information such as national identity numbers. If you're an educational institution, you may want
to attest to your user's achievements in a way that they can securely share. Anyone with access to your application's
did
can verify that a particular attestation came from your app.
Attesting to information about your users helps to add real value to your application, and your users will use uPort to build up their own digital identity.
credentials.createVerification({
sub: '0x...', // uport address of user
expiresIn: <future timestamp>, // If your information is not permanent make sure to add expiresIn, the time in seconds from now
claims: {name: 'John Smith'}
}).then(attestation => {
// send attestation to user
})
As with a verification request, you will want to send this JWT to your user. You can do this in the browser via QR, using push with a previously requested pushToken, or via another transport of your choosing.
Finally, as uPort is based in the Ethereum blockchain, uPort Credentials can be used to request that a user call a
particular Ethereum smart contract function. Smart contracts live on the blockchain at a certain address and expose
public functions that can be called according to their ABI. Using the Credentials.contract
method, you can create an
object from a contract abi that will create transaction request JWTs for each contract method, that can be presented to
a user's mobile application like any other JWT described above. This is just a wrapper around
Credentials.createTxRequest()
, which generates the txObject for a particular contract method call.
import abi from './myContractAbi.json'
const myContract = Credentials.contract(abi).at(contractAddress)
// creates a request for the user to call the transfer() function on the smart contract
const txRequest = myContract.transfer(...).then(txRequestToken => {
// send tx request token to user
})