Sign In With Frequency Developer Documentation and Tools

Sign In With Frequency (SIWF) provides documentation and tools to use with SIWF-compatible services such as Frequency Access (an easy-to-use custodial social wallet for users on Frequency).

JavaScript Quick Start

Overview

There are a few main steps to authenticating using SIWF-compatible systems.

For example, when using Frequency Access:

  1. Your application sends the user the Frequency Access Authentication URL
  2. Frequency Access verifies the user, and the user signs the requested payload(s)
  3. Frequency Access sends the signed user payloads back to your application
  4. If needed, your application sends the signed payloads to Frequency
  5. Your application logs in the user, and the user's session begins

Actors

  • Your Application: Any website, mobile application, etc. for which your user needs authentication
  • SIWF service (e.g. Frequency Access): Verifies the user and provides the user with access to the entire Frequency Ecosystem
  • Frequency Blockchain: Manages user delegations and additional social operations

User Delegations and Credentials

SIWF allows you to request that a user give you various delegations such as private graph changes, and credentials such as verified email.

Staging & Production

Using Frequency Access

Frequency Access has two deployments: Staging-Testnet and Production-Mainnet.

Production-Mainnet

URL: www.frequencyaccess.com

  • Uses Frequency Mainnet
  • Supports both SMS and Email verification
  • Bot protection via hCaptcha
  • Authorization Timeout: 30 seconds

Staging-Testnet

URL: testnet.frequencyaccess.com

  • Uses Frequency Testnet on Paseo
  • Supports ONLY Email and will not send SMS verification codes
  • No uptime guarantees
  • Limited bot protection
  • May rate limit usage
  • Authorization Timeout: 30 seconds

Prerequisites

Terms

  • Frequency Provider: The identity of the application registered on Frequency
  • Staging-Testnet: The staging environment
  • Production-Mainnet: The production environment
  • MSA: The Frequency blockchain account for a user
  • SR25519: Schnorr signatures using ed25519 over ECDSA
  • Delegation: The user permission for an application to act on their behalf
  • Credential: Verified data about the user provided with permission of the user

Quick Start with JavaScript

This quick start uses the @projectlibertylabs/siwf NPM package to quickly generate the request and validate the response from Frequency Access.

Installation

Install the NPM package. This package is both CommonJS, ES Module, and TypeScript compatible. TypeScript will be shown for the examples.

npm i @projectlibertylabs/siwf

Prerequisites

Step 1: Generate the Request URL

import * as siwf from "@projectlibertylabs/siwf";

async function startLogin() {
  // Get the signed base64url encoded payload
  const signedRequest: string = getStaticProviderSignedRequest();

  // Any additional parameters that do not collide with reserved parameter names
  // on the Authentication URL are passed through unchanged.
  // Remember that ONLY the callback path from the Signed Payload is secured via signature.
  const additionalCallbackUrlParams: string = getWebOrApplicationCallbackUrlParams();

  // Options with endpoint selection
  // Endpoint may be tagged or specified in full
  const options = { endpoint: "production" };
  // Staging-Testnet Options
  // const options = { endpoint: 'staging' };

  const authenticationUrl = siwf.generateAuthenticationUrl(signedRequest, additionalCallbackUrlParams, options);
}

Step 2 (Web): Forward the User to a Browser

For website interactions, just forward the user to the returned authenticationUrl.

Step 2 (Android/iOS): Forward the User to an Embedded Browser

For mobile applications, it is recommended to use an embedded browser and set the callbackDomain in the signedRequest and the callbackPath to your application's Universal Link. This ensures that the user remains within the application environment and does not have to leave the app.

For more details, refer to the official documentation:

Step 3: Callback Processing

import * as siwf from "@projectlibertylabs/siwf";

async function handleCallback(incomingUrl: string) {
  // Extract the `authorizationCode` from the URL
  const url = new URL(incomingUrl);
  const authorizationCode = url.searchParams.get("authorizationCode");

  // Same options as before
  const options = { endpoint: "production" };

  // Exchange the `authorizationCode` for the result
  const result = await siwf.getLoginResult(authorizationCode, options);

  if (siwf.hasChainSubmissions(result)) {
    // Add your own logic for handling the submission to the chain
    await processSubmissions(result.payloads);
  }

  if (result.credentials) {
    // Add your own logic for processing credentials
    await processCredentials(result.credentials);
  }

  // Get the ss58 encoded key that identifies this session
  // It is also the control key for the user's constant MSA Id
  const userKey = result.userPublicKey.encodedValue;

  // Add your own logic for session managment
  startSession();
}

Step 4: Session Starts

You now have a logged in user! Assuming the chain submissions are complete, you also have:

  • A consistent identifier, i.e. the MSA Id
  • A universal handle (If the user set one)
  • A public delegation between the user's MSA Id and your Provider Id on chain (revokable at any time by you or the user independently)

And if requested:

  • Access to the user's private graph
  • Permission to act on the user's behalf for delegated actions
  • Verified email or phone/SMS number for the user
Note: You may start the user’s session and process the submissions in the background, however some data such as the consistent identifier, the MSA Id or full handle with suffix may not be accessible until the processing is complete.

SIWF Actions

SIWF handles three different situations for each user:

ActionFrequency Blockchain account (MSA)Delegation with Your Application
Create AccountRequiredRequired
Create DelegationExistingNew or Updated Required
LoginExistingExisting

General Flow

  1. Generate Provider Login Request Payload and Signature (Generator Tool) (Documentation)
  2. Build and send the user to the Authentication URL (See Details)
  3. Receive a callback from Frequency Access or other SIWF-compatible services
  4. Retrieve and process the login response (See Details)

Sequence Diagram

General Flow Sequency Diagram

Backend Requirements

  • Able to validate payloads received from a SIWF-compatible services
  • Able to connect to a Frequency RPC Node
  • Able to sign transactions to submit to the Frequency RPC Node

Redirect User to a SIWF-Compatible Service (e.g. Frequency Access)

To start the authentication loop, your application will generate an Authentication URL for each user.

Note: The following instruction examples are based on Frequency Access.

Quick Reference

  • Staging-Testnet: https://testnet.frequencyaccess.com/siwa/start
  • Production-Mainnet: https://www.frequencyaccess.com/siwa/start
  • Generate Login Request Payload and Signature: Generator Tool
  • Request Structure: SiwfRequest
  • Signed Request Structure: SiwfSignedRequest

Step 1: Generate the Signed Request Payload

You can generate more than one of these to use simultaneously. Most applications should generate and keep their needed value(s) static. The generated signed request payload is secured by the signature included in it, and it is not sensitive data.

Signed Request Payload Contents

  • A signature from one of the Control Keys of the Frequency Provider
  • The domain and path the callback will use
  • The requested permissions
  • The requested credentials

Signed Request Payload Generator

Generate one or more login request payloads and signatures (signedRequest) using the Generator Tool.

Signed Request Payload Detailed Documentation

For details on the Payload and how it is formed, see the Reference Documentation.

Step 2: Build the Authentication URL Parameters

Parameter: signedRequest

The Base64url encoded value from Step 1.

Reminder: This includes the callback domain that will be used.

Additional Parameters are Forwarded

Any additional parameters that do not collide with reserved parameter names on the Authentication URL are passed through unchanged.

Note: These parameters are not protected and could be changed by malicious actors. Take care when using them for security-related data.

Example

  • https://www.frequencyaccess.com/siwa/start?signedRequest=<request value>&key1=<value1>&key2=<value2>&other=<result>
  • Will result in callback URL parameters of: ?authorizationCode=<authorization code>&key1=<value1>&key2=<value2>&other=<result>

Step 3: Build the Authentication URL

Taking the parameters from the previous step, build an Authentication URL using the correct base for the SIWF path of /start:

  • Staging-Testnet: https://testnet.frequencyaccess.com/siwa/start
  • Production-Mainnet: https://www.frequencyaccess.com/siwa/start

The SIWF System will send the user back by building the callback URL. The callback URL will be built with:

  • The callback from the signedRequest
  • Appending any additional GET request parameters
  • Appending the reserved URL parameter of authorizationCode

The callback URL will maintain all non-reserved URL parameters. For example, if you wish to correlate the original unauthorized session with the authorized session, you can generate a dynamic parameter with a random UUIDv4 identifier on each request.

Example

Parameters

{
  "signedRequest": "eyJyZXF1ZXN0ZWRTaWduYXR1cmVzIjp7InB1YmxpY0tleSI6eyJlbmNvZGVkVmFsdWUiOiJmNmNMNHdxMUhVTngxMVRjdmRBQk5mOVVOWFhveUg0N21WVXdUNTl0elNGUlc4eURIIiwiZW5jb2RpbmciOiJiYXNlNTgiLCJmb3JtYXQiOiJzczU4IiwidHlwZSI6IlNyMjU1MTkifSwic2lnbmF0dXJlIjp7ImFsZ28iOiJTUjI1NTE5IiwiZW5jb2RpbmciOiJiYXNlMTYiLCJlbmNvZGVkVmFsdWUiOiIweDk2MGYxOTVkYzFmOTFiZjcxYzBiMzUyMzE1MGFlMzc0NzFiZWRlMDdhMDAzOTA5NjQ3Y2NmMDQwYWNkNWNkMDRlYTQ4NzBiZDEyNGNhZmEyZGViNTliMGUzNzhjYjE5ZmJjNmFmNjAxYjc1NTU5ZmFhYjdiNzY4ZGU4MWEwOTgzIn0sInBheWxvYWQiOnsiY2FsbGJhY2siOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJwZXJtaXNzaW9ucyI6WzUsNyw4LDksMTBdfX0sInJlcXVlc3RlZENyZWRlbnRpYWxzIjpbeyJ0eXBlIjoiVmVyaWZpZWRHcmFwaEtleUNyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFtZHZteGQ1NHp2ZTVraWZ5Y2dzZHRvYWhzNWVjZjRoYWwydHMzZWV4a2dvY3ljNW9jYTJ5Il19LHsiYW55T2YiOlt7InR5cGUiOiJWZXJpZmllZEVtYWlsQWRkcmVzc0NyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFlNHFvY3poZnRpY2k0ZHpmdmZiZWw3Zm80aDRzcjVncmNvM29vdnd5azZ5NHluZjQ0dHNpIl19LHsidHlwZSI6IlZlcmlmaWVkUGhvbmVOdW1iZXJDcmVkZW50aWFsIiwiaGFzaCI6WyJiY2lxanNwbmJ3cGMzd2p4NGZld2NlazVkYXlzZGpwYmY1eGppbXo1d251NXVqN2UzdnUydXducSJdfV19XX0",
  "mode": "dark"
}

Testnet Authentication URL

"https://testnet.frequencyaccess.com/siwa/start?signedRequest=eyJyZXF1ZXN0ZWRTaWduYXR1cmVzIjp7InB1YmxpY0tleSI6eyJlbmNvZGVkVmFsdWUiOiJmNmNMNHdxMUhVTngxMVRjdmRBQk5mOVVOWFhveUg0N21WVXdUNTl0elNGUlc4eURIIiwiZW5jb2RpbmciOiJiYXNlNTgiLCJmb3JtYXQiOiJzczU4IiwidHlwZSI6IlNyMjU1MTkifSwic2lnbmF0dXJlIjp7ImFsZ28iOiJTUjI1NTE5IiwiZW5jb2RpbmciOiJiYXNlMTYiLCJlbmNvZGVkVmFsdWUiOiIweDk2MGYxOTVkYzFmOTFiZjcxYzBiMzUyMzE1MGFlMzc0NzFiZWRlMDdhMDAzOTA5NjQ3Y2NmMDQwYWNkNWNkMDRlYTQ4NzBiZDEyNGNhZmEyZGViNTliMGUzNzhjYjE5ZmJjNmFmNjAxYjc1NTU5ZmFhYjdiNzY4ZGU4MWEwOTgzIn0sInBheWxvYWQiOnsiY2FsbGJhY2siOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJwZXJtaXNzaW9ucyI6WzUsNyw4LDksMTBdfX0sInJlcXVlc3RlZENyZWRlbnRpYWxzIjpbeyJ0eXBlIjoiVmVyaWZpZWRHcmFwaEtleUNyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFtZHZteGQ1NHp2ZTVraWZ5Y2dzZHRvYWhzNWVjZjRoYWwydHMzZWV4a2dvY3ljNW9jYTJ5Il19LHsiYW55T2YiOlt7InR5cGUiOiJWZXJpZmllZEVtYWlsQWRkcmVzc0NyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFlNHFvY3poZnRpY2k0ZHpmdmZiZWw3Zm80aDRzcjVncmNvM29vdnd5azZ5NHluZjQ0dHNpIl19LHsidHlwZSI6IlZlcmlmaWVkUGhvbmVOdW1iZXJDcmVkZW50aWFsIiwiaGFzaCI6WyJiY2lxanNwbmJ3cGMzd2p4NGZld2NlazVkYXlzZGpwYmY1eGppbXo1d251NXVqN2UzdnUydXducSJdfV19XX0&mode=dark"

Step 3: Redirect the User

Getting the Login Result from SIWF

After the user completes the authentication and authorization, the user is redirected to the callback URL with one additional parameter set: authorizationCode.

The authorizationCode can be used to retrieve the result of the login.

Note: The following instruction examples are based on Frequency Access.

Quick Reference

  • Staging-Testnet: https://testnet.frequencyaccess.com/siwa/api/payload
  • Production-Mainnet: https://www.frequencyaccess.com/siwa/api/payload
  • Response Structure: SiwfResponse

Step 1: Retrieve the Response

  • GET:
    • Staging-Testnet: https://testnet.frequencyaccess.com/siwa/api/payload?authorizationCode=[Parameter from callback URL]
    • Production-Mainnet: https://www.frequencyaccess.com/siwa/api/payload?authorizationCode=[Parameter from callback URL]

Step 2: Parsing the Response

Response Sections

  • userPublicKey: The key for the user signing this request
  • payloads: Signed payloads from the user
  • credentials: User approved verified credentials from Frequency Access (or other SIWF-compatible services) such as email, phone, user keys, etc...

userPublicKey

The public key for the user identifies the user for this session. If that user has a Frequency blockchain account (MSA), the MSA Id can be retrieved from Frequency using this key. Or in the case when it does not, the payloads section will contain the payload to create said MSA Id.

While the userPublicKey may change, the MSA Id will always be the same for the same user account.

Step 3: Processing the Credentials

The credentials array will contain any requested and approved credentials. Each credential would be matched based on the type field.

These credentials follow the DSNP Verifiable Credentials Specification.

Verify the Credential

Trust Model Note: You may choose to just trust credentials issued by Frequency Access (or other SIWF-compatible services) given that the credential is fetched directly. These will have issuer did:web:testnet.frequencyaccess.com or did:web:frequencyaccess.com.

  1. Check that the credentialSubject.id matches the userPublicKey following the did:key Method from the W3C
  • Example: f6cL4wq1HUNx11TcvdABNf9UNXXoyH47mVUwT59tzSFRW8yDH is the SS58 version with prefix 90 of the hex address 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d. 0xef01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d is multicodec sr25519-pub hex which is multiformat base58-btc z6QNzHod3tSSJbwo4e5xGDcnsndsR9WByZzPoCGdbv3sv1jJ
  1. Fetch the issuer DID Document following the did:web Method from the W3C
  • Production-Mainnet should always be did:web:frequencyaccess.com which resolves to https://frequencyaccess.com/.well-known/did.json
  • Staging-Testnet should always be did:web:testnet.frequencyaccess.com which resolves to https://testnet.frequencyaccess.com/.well-known/did.json
  1. Check that the key in the proof.verificationMethod is in the DID Document to verify that the key is still valid
  2. Test that the proof validates according the to W3C Verifiable Credentials Specification

Graph Encryption Key Credential

If the user has permitted access to their private social graph per the request for VerifiedGraphKeyPairCredential, credentials will have a entry with type including VerifiedGraphKeyPairCredential. This is an x25519 key pair for use with the curve25519xsalsa20poly1305 encryption algorithm from the NaCl Library. For more information on how the Graph data is structured after decryption, see the DSNP Specification.

This key pair is PII and should be stored with care, but must be stored to read the user's private graph.

Example Credential

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/undefined-terms/v2"
  ],
  "type": [
    "VerifiedPhoneNumberCredential",
    "VerifiableCredential"
  ],
  "issuer": "did:web:frequencyaccess.com",
  "validFrom": "2024-08-21T21:28:08.289+0000",
  "credentialSchema": {
    "type": "JsonSchema",
    "id": "https://schemas.frequencyaccess.com/VerifiedPhoneNumberCredential/bciqjspnbwpc3wjx4fewcek5daysdjpbf5xjimz5wnu5uj7e3vu2uwnq.json"
  },
  "credentialSubject": {
    "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
    "phoneNumber": "+01-234-867-5309",
    "lastVerified": "2024-08-21T21:27:59.309+0000"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "verificationMethod": "did:web:frequencyaccess.com#z6MkofWExWkUvTZeXb9TmLta5mBT6Qtj58es5Fqg1L5BCWQD",
    "cryptosuite": "eddsa-rdfc-2022",
    "proofPurpose": "assertionMethod",
    "proofValue": "z5sJ2CjHX1wwgzfFGoZNocxeFKd2ffpo5TVgUvdaSkYq1M6gF7UjpYfePo97QoZgmiWdgPAWPjxFvGBysaxHV8DZ4"
  }
}

Step 4: Processing the Payloads

The payload section has several different types that can be returned:

  • login: When the user already has a correct delegation
  • addProvider*: When the user does not have a delegation (a new user signup) or when the delegation was needing to be changed
  • itemActions*: When the user has user chain data to set or update
  • claimHandle*: When the user needs to claim a new handle

* Requires submission to Frequency

The payloads that require submission to Frequency should be submitted in one batch using Capacity. The addProvider must always be first in the batch to ensure the correct permissions and delegations are in place for subsequent actions in the batch.

Signatures to Frequency have an expiration set to a future Frequency block number. If the actions are not submitted before expriation, Frequency will reject the transactions and your application will need to request new signatures.

Payload Examples and Signature Details

login

The correct delegation for the user already exists. No submission to the chain is required, but the application must validate the signature to be sure that the user is authenticated.

The message signed follows CAIP-122: Sign in With X specification which is derived from EIP-4361: Sign-In with Ethereum.

Example Message with Placeholders

{{domain}} wants you to sign in with your Frequency account:
frequency:{{chainReference}}:{{ss58Address}}

URI: {{uri}}
Version: {{version}}
Nonce: {{nonce}}
Chain ID: frequency:{{chainReference}}
Issued At: {{issued-at}}

Inside the message, {{domain}} is the domain of the application requesting the sign-in. {{domain}} should match the domain contained in the URI field.

Validation Steps

  1. Perform an Sr25519 signature verification using:
    • userPublicKey: The signing key
    • payload.message: The signed message parsing \n into LF line breaks
    • signature.encodedValue: The signature
  2. Verify that the userPublicKey matches the second line of the message for the correct chain identifier
    • Production-Mainnet: frequency:mainnet:
    • Staging-Testnet: frequency:testnet-paseo:
  3. Verify that the message starts with your domain based on RFC 4501 dnsauthority
  4. Verify the Issued At value from the message is within your acceptable time range
  5. Verify that Nonce value in the message is not being reused

Parsing the Message Data

  1. Break the lines by \n
  2. Match based on the prefix:
    • Nonce:
    • Issued At:
    • URI:

addProvider

The user either needs a new delegation or a new MSA created with the delegation.

The endpoint.extrinsic field will distinguish between the two:

  • createSponsoredAccountWithDelegation: New MSA
  • grantDelegation: New/Updated Delegation

See Frequency Documentation on forming the transaction for the extrinsics.

itemActions

Item actions will update the user's chain data for things such as their public key for the encrypted graph. These actions must be submitted to the chain for the correct functioning of private graph and other systems.

See Frequency Documentation on forming the transaction for the extrinsics.

claimHandle

The user wishes to claim a Frequency Handle.

See Frequency Documentation on forming the transaction for the extrinsics.

Step 6: Frequency Transaction Submission

All payloads that are returned will be able to be processed using Capacity on Frequency.

Frequency submission is required for any of the following payloads:

  • addProvider
  • itemActions
  • claimHandle

They can be submitted to the chain in one transaction using pay_with_capacity_batch_all.

Step 6: Session Starts

Once the payloads have been validated, the user's authenticated session may start. SIWF services do not manage user sessions.

Examples

New Frequency User Response

{
  "userPublicKey": {
    "encodedValue": "f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ",
    "encoding": "base58",
    "format": "ss58",
    "type": "Sr25519"
  },
  "payloads": [
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0x1a27cb6d79b508e1ffc8d6ae70af78d5b3561cdc426124a06f230d7ce70e757e1947dd1bac8f9e817c30676a5fa6b06510bae1201b698b044ff0660c60f18c8a"
      },
      "endpoint": {
        "pallet": "msa",
        "extrinsic": "createSponsoredAccountWithDelegation"
      },
      "type": "addProvider",
      "payload": {
        "authorizedMsaId": 1,
        "schemaIds": [
          5,
          7,
          8,
          9,
          10
        ],
        "expiration": 24
      }
    },
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0x9eb338773b386ded2e3731ba68ba734c80408b3ad24f92ed3c60342d374a32293851fa8e41d722c72a5a4e765a9e401c68570a8c666ab678e4e5d94aa6825d85"
      },
      "endpoint": {
        "pallet": "statefulStorage",
        "extrinsic": "applyItemActionsWithSignatureV2"
      },
      "type": "itemActions",
      "payload": {
        "schemaId": 7,
        "targetHash": 0,
        "expiration": 20,
        "actions": [
          {
            "type": "addItem",
            "payloadHex": "0x40eea1e39d2f154584c4b1ca8f228bb49ae5a14786ed63c90025e755f16bd58d37"
          }
        ]
      }
    },
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0xb004140fd8ba3395cf5fcef49df8765d90023c293fde4eaf2e932cc24f74fc51b006c0bebcf31d85565648b4881fa22115e0051a3bdb95ab5bf7f37ac66f798f"
      },
      "endpoint": {
        "pallet": "handles",
        "extrinsic": "claimHandle"
      },
      "type": "claimHandle",
      "payload": {
        "baseHandle": "ExampleHandle",
        "expiration": 24
      }
    }
  ],
  "credentials": [
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedEmailAddressCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:web:frequencyaccess.com",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedEmailAddressCredential/bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "emailAddress": "john.doe@example.com",
        "lastVerified": "2024-08-21T21:27:59.309+0000"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:web:frequencyaccess.com#z6MkofWExWkUvTZeXb9TmLta5mBT6Qtj58es5Fqg1L5BCWQD",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z4jArnPwuwYxLnbBirLanpkcyBpmQwmyn5f3PdTYnxhpy48qpgvHHav6warjizjvtLMg6j3FK3BqbR2nuyT2UTSWC"
      }
    },
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedGraphKeyCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedGraphKeyCredential/bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "encodedPublicKeyValue": "0xb5032900293f1c9e5822fd9c120b253cb4a4dfe94c214e688e01f32db9eedf17",
        "encodedPrivateKeyValue": "0xd0910c853563723253c4ed105c08614fc8aaaf1b0871375520d72251496e8d87",
        "encoding": "base16",
        "format": "bare",
        "type": "X25519",
        "keyType": "dsnp.public-key-key-agreement"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:key:z6MktZ15TNtrJCW2gDLFjtjmxEdhCadNCaDizWABYfneMqhA",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z2HHWwtWggZfvGqNUk4S5AAbDGqZRFXjpMYAsXXmEksGxTk4DnnkN3upCiL1mhgwHNLkxY3s8YqNyYnmpuvUke7jF"
      }
    }
  ]
}

New Application/Delegation Response

{
  "userPublicKey": {
    "encodedValue": "f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ",
    "encoding": "base58",
    "format": "ss58",
    "type": "Sr25519"
  },
  "payloads": [
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0xbac399831b9e3ad464a16e62ad1252cc8344a2c52f80252b2aa450a06ae2362f6f4afcaca791a81f28eaa99080e2654bdbf1071a276213242fc153cca43cfa8e"
      },
      "endpoint": {
        "pallet": "msa",
        "extrinsic": "grantDelegation"
      },
      "type": "addProvider",
      "payload": {
        "authorizedMsaId": 1,
        "schemaIds": [
          5,
          7,
          8,
          9,
          10
        ],
        "expiration": 24
      }
    }
  ],
  "credentials": [
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedEmailAddressCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:web:frequencyaccess.com",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedEmailAddressCredential/bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "emailAddress": "john.doe@example.com",
        "lastVerified": "2024-08-21T21:27:59.309+0000"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:web:frequencyaccess.com#z6MkofWExWkUvTZeXb9TmLta5mBT6Qtj58es5Fqg1L5BCWQD",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z4jArnPwuwYxLnbBirLanpkcyBpmQwmyn5f3PdTYnxhpy48qpgvHHav6warjizjvtLMg6j3FK3BqbR2nuyT2UTSWC"
      }
    },
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedGraphKeyCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedGraphKeyCredential/bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "encodedPublicKeyValue": "0xb5032900293f1c9e5822fd9c120b253cb4a4dfe94c214e688e01f32db9eedf17",
        "encodedPrivateKeyValue": "0xd0910c853563723253c4ed105c08614fc8aaaf1b0871375520d72251496e8d87",
        "encoding": "base16",
        "format": "bare",
        "type": "X25519",
        "keyType": "dsnp.public-key-key-agreement"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:key:z6MktZ15TNtrJCW2gDLFjtjmxEdhCadNCaDizWABYfneMqhA",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z2HHWwtWggZfvGqNUk4S5AAbDGqZRFXjpMYAsXXmEksGxTk4DnnkN3upCiL1mhgwHNLkxY3s8YqNyYnmpuvUke7jF"
      }
    }
  ]
}

Login Only Response

{
  "userPublicKey": {
    "encodedValue": "f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ",
    "encoding": "base58",
    "format": "ss58",
    "type": "Sr25519"
  },
  "payloads": [
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0xe261698297111834e68b4152bf1f89819e886b6528f6fff45715f7781d0f1e7dc4007ccfed1e85b8c603c0fea2f7abf22bfe6336869ad21f11a09a114452c680"
      },
      "type": "login",
      "payload": {
        "message": "your-app.com wants you to sign in with your Frequency account:\nf6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ\n\n\n\nURI: https://your-app.com/signin/callback\nNonce: N6rLwqyz34oUxJEXJ\nIssued At: 2024-10-29T19:17:27.077Z\nExpiration Time: 2060-03-05T23:23:03.041Z"
      }
    }
  ],
  "credentials": [
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedEmailAddressCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:web:frequencyaccess.com",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedEmailAddressCredential/bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "emailAddress": "john.doe@example.com",
        "lastVerified": "2024-08-21T21:27:59.309+0000"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:web:frequencyaccess.com#z6MkofWExWkUvTZeXb9TmLta5mBT6Qtj58es5Fqg1L5BCWQD",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z4jArnPwuwYxLnbBirLanpkcyBpmQwmyn5f3PdTYnxhpy48qpgvHHav6warjizjvtLMg6j3FK3BqbR2nuyT2UTSWC"
      }
    },
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedGraphKeyCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedGraphKeyCredential/bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "encodedPublicKeyValue": "0xb5032900293f1c9e5822fd9c120b253cb4a4dfe94c214e688e01f32db9eedf17",
        "encodedPrivateKeyValue": "0xd0910c853563723253c4ed105c08614fc8aaaf1b0871375520d72251496e8d87",
        "encoding": "base16",
        "format": "bare",
        "type": "X25519",
        "keyType": "dsnp.public-key-key-agreement"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:key:z6MktZ15TNtrJCW2gDLFjtjmxEdhCadNCaDizWABYfneMqhA",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z2HHWwtWggZfvGqNUk4S5AAbDGqZRFXjpMYAsXXmEksGxTk4DnnkN3upCiL1mhgwHNLkxY3s8YqNyYnmpuvUke7jF"
      }
    }
  ]
}

Reference

Authentication URL Signature

Most applications skip all of this and just generate the login request payload and signature.

Step 1: Create the Payload for Signing

Parameter: callback

When the user has completed the authentication, this is the return URI that will be used.

Appended to the URL will be this parameter:

  • authorizationCode Used to retrieve the full response payload

The callback url will maintain any other URL parameters included. For example, if you wish to correlate the original unauthorized session with the authorized session, you can generate a dynamic callback url with a parameter with a random UUIDv4 identifier on each request.

Parameter: permissions

The list of Frequency Schema Ids permissions your application is requesting from the user.

Parameter: userIdentifierAdminUrl

Only used for custom integration situations.

Step 2: Signing the Request

To ensure that the correct application is requesting the authentication and that the response is only sent to the authorized party, the request is signed. The signature MUST be from one of the Control Keys of the Frequency Provider.

2a: Serialize the payload using the SCALE Codec

SCALE Type (Note: Order matters!)

{
  "callback": "String",
  "permissions": "Vec<U16>",
  "userIdentifierAdminUrl": "Option<String>",
}

2b: Wrap the Payload

So that no payloads can be accidentally used on a chain, the payload is wrapped with a <Bytes> tag.

Byte Arrays Concatenated: [ 60, 66, 121, 116, 101, 115, 62 ] + scale_encoded_payload_bytes + [ 60, 47, 66, 121, 116, 101, 115, 62 ]

2c: Sign the Wrapped Payload Bytes

Sign the serialized payload using Schnorr signatures over ECDSA.

2d: Example

Remember that SR25519 signatures are non-deterministic, so the payload and encoding will match, but the signature will be different. This example uses the //Alice seed phrase to generate the signature.

  • Payload: { "callback": "https://localhost:44181", "permissions": [5, 7, 8, 9, 10] }
  • SCALE Payload (Hex): 0x5c68747470733a2f2f6c6f63616c686f73743a34343138311405000700080009000a0000
  • Wrapped Payload (Hex): 0x3c42797465733e5c68747470733a2f2f6c6f63616c686f73743a34343138311405000700080009000a00003c2f42797465733e
  • Signing Public Key (SS58 Prefix 90): f6cL4wq1HUNx11TcvdABNf9UNXXoyH47mVUwT59tzSFRW8yDH
  • Signature (Hex): 0x9abd3c54e7164e8385627dc692724b9467386acd7b02a13d6187e2c58fd91440d9134781c0410a45812f5532b71f4a34b4a5443ef8d68b5a1956f7f0f81d4286

Step 3 (Optional): Request Credentials (Graph Key, Email, Phone)

Frequency Access users can provide verified email or phone/SMS to your application when requested and approved by the user. This is not required, and best practice is to only make such a request if it is required for the functioning of the application.

The request MUST be wrapped in requestedCredentials which is an array that requires ALL listed credential objects. Supported Options:

  • anyOf: Request for one or more credentials from the list (0+ may return)
{
  // ...
  "requestedCredentials": [
    {
      "type": "VerifiedGraphKeyCredential",
      "hash": ["bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y"]
    }
    {
      "anyOf": [
        // List of contact credential requests here
        {
          "type": "VerifiedEmailAddressCredential",
          "hash": ["bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi"]
        },
        {
          "type": "VerifiedPhoneNumberCredential",
          "hash": ["bciqjspnbwpc3wjx4fewcek5daysdjpbf5xjimz5wnu5uj7e3vu2uwnq"]
        }
      ]
    }
  ]
}

Example Using TypeScript/JavaScript

// This is the URI of a key. Usually just a seed phrase, but also supports test accounts such as `//Alice` or `//Bob`
const providerKeyUri: string = getProviderKeyUriSecret();

// The list of Frequency Schemas Ids that you are requesting the user delegate
// See a full reference: https://projectlibertylabs.github.io/siwf/v2/docs/Delegations.html
// This example is for Graph Only
const permissions: number[] = [7, 8, 9, 10];

// List of Credentials
// See a full reference and examples: https://projectlibertylabs.github.io/siwf/v2/docs/Credentials.html
const credentials = [
  {
    anyOf: [siwf.VerifiedEmailAddressCredential, siwf.VerifiedPhoneNumberCredential],
  },
  siwf.VerifiedGraphKeyCredential,
];

// This is the URI that the user should return to after authenticating
const callbackUri: string = getWebOrApplicationCallbackUri();

// The Encoded Signed Request can remain static if
// It is the same as is generated with the Signed Payload Generation Tool
const encodedSignedRequest = await siwf.generateEncodedSignedRequest(
  providerKeyUri,
  callbackUri,
  permissions,
  credentials,
);

// Options with endpoint selection
// Endpoint may be tagged or specified in full
const options = { endpoint: "production" };
// Staging-Testnet Options
// const options = { endpoint: 'staging' };

const authenticationUrl: string = generateAuthenticationUrl(signedRequest, new URLSearchParams({ id: getSessionId() }));

Full Example Request

{
  "requestedSignatures": {
    "publicKey": {
      "encodedValue": "f6cL4wq1HUNx11TcvdABNf9UNXXoyH47mVUwT59tzSFRW8yDH",
      "encoding": "base58",
      "format": "ss58",
      "type": "Sr25519"
    },
    "signature": {
      "algo": "SR25519",
      "encoding": "base16",
      "encodedValue": "0x0407ce814b77861df94d16b3fcb317d37a07abc2a7f9cd7c02cc22529ee7b32d56795f88bd6b4ad106b72b91b6246a783671bcd24cb01aaf0e9316db5e0cd085"
    },
    "payload": {
      "callback": "http://localhost:3000",
      "permissions": [
        5,
        7,
        8,
        9,
        10
      ]
    }
  },
  "requestedCredentials": [
    {
      "type": "VerifiedGraphKeyCredential",
      "hash": [
        "bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y"
      ]
    },
    {
      "anyOf": [
        {
          "type": "VerifiedEmailAddressCredential",
          "hash": [
            "bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi"
          ]
        },
        {
          "type": "VerifiedPhoneNumberCredential",
          "hash": [
            "bciqjspnbwpc3wjx4fewcek5daysdjpbf5xjimz5wnu5uj7e3vu2uwnq"
          ]
        }
      ]
    }
  ]
}

Usage

See Start for details on how to use the generated signature.

Serialization

  1. JSON Stringify the SignedRequest object
  2. base64url encode the stringified result

Signed Request Generator

Fill out the form and the signed request will be generated at the bottom.

Permissions
Select Credentials

Result

Login Request Payload and Signature ( signedRequest parameter )
Mainnet/Production URL
Testnet/Staging URL
Signed Request (JSON)
Expand

Credentials

Request Structure

The request is an array that requires ALL listed credential objects. Supported Options:

  • anyOf: Request for one or more credentials from the list (0+ may return)

Example Request

This is a common request: one verified contact method and access to the graph encryption key.

[
  {
    "type": "VerifiedGraphKeyCredential",
    "hash": ["bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y"]
  },
  {
    "anyOf": [
      {
        "type": "VerifiedEmailAddressCredential",
        "hash": ["bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi"]
      },
      {
        "type": "VerifiedPhoneNumberCredential",
        "hash": ["bciqjspnbwpc3wjx4fewcek5daysdjpbf5xjimz5wnu5uj7e3vu2uwnq"]
      }
    ]
  }
]

Available Credentials

Each request also has a multiformat hash of the schema file to ensure the correct verification document is requested. Below are the official types and multihashes to use.

Graph Key

{
  "type": "VerifiedGraphKeyCredential",
  "hash": ["bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y"]
}

Email

{
  "type": "VerifiedEmailAddressCredential",
  "hash": ["bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi"]
}

Phone/SMS

{
  "type": "VerifiedPhoneNumberCredential",
  "hash": ["bciqjspnbwpc3wjx4fewcek5daysdjpbf5xjimz5wnu5uj7e3vu2uwnq"]
}

Available Delegations

Staging-Testnet and Production-Mainnet have the same delegation Schema Ids available.

Short Name and Specification LinkDescriptionSchema Id
dsnp.broadcast@v1(Deprecated) Create new public content2
dsnp.broadcast@v2Create new public content17
dsnp.dsnp-content-attribute@v1Create an authenticated attribute set for DSNP content12
dsnp.ext-content-attribute@v1Create an authenticated attribute set for content external to DSNP13
dsnp.private-connections@v1Update private friendship connections10
dsnp.private-follows@v1Update private follow list9
dsnp.profile-resources@v1Update user profile information15
dsnp.profile@v1(Deprecated) Update profile information6
dsnp.public-follows@v1Update public follow list8
dsnp.reaction@v1Public reaction to content4
dsnp.reply@v1(Deprecated) Public reply to content3
dsnp.reply@v2Public reply to content18
dsnp.tombstone@v1(Deprecated) Mark content for deletion1
dsnp.tombstone@v2Mark content for deletion16
dsnp.update@v1(Deprecated) Update an existing post or reply5
dsnp.update@v2Update an existing post or reply19
dsnp.user-attribute-set@v2Create an authenticated attribute set for a DSNP User20

Possible Payloads

Each response may have one or more of the following signed payloads.

Login

The signature is generated by signing the UTF-8 bytes of payload.message using SR25519.

See Response Payloads: Login for more details.

Example

Example is signed using f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ which is the SS58 (Prefix 90) public key from the seed phrase //Bob.

{
  "signature": {
    "algo": "SR25519",
    "encoding": "base16",
    "encodedValue": "0x84a4e03344b07d64087ebdf47b2c8c679aa7de78179689988992609f1b83c34f6086c7de99ef41c5325cce64d148624e716c605d355f22d1281f6d23f546f584"
  },
  "type": "login",
  "payload": {
    "message": "localhost wants you to sign in with your Frequency account:\nf6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ\n\n\n\nURI: https://testnet.frequencyaccess.com/signin/confirm\nNonce: N6rLwqyz34oUxJEXJ\nIssued At: 2024-03-05T23:18:03.041Z\nExpiration Time: 2060-03-05T23:23:03.041Z"
  }
}

Add Provider

This payload follows the AddProvider type from Frequency. It has the same payload for two different endpoint extrinsics: createSponsoredAccountWithDelegation used for creating a new MSA on chain and grantDelegation which is used to grant a new provider permissions on an existing MSA.

The signature is generated by signing the SCALE-encoded payload using SR25519.

Example

Example is signed using f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ which is the SS58 (Prefix 90) public key from the seed phrase //Bob.

{
  "signature": {
    "algo": "SR25519",
    "encoding": "base16",
    "encodedValue": "0x94156d570b29e9c4e3a04eefbff56439f40de7fb6bdba1ca31e9017b55e5e773f747d0ab4f0fc2b44ca903aa8fb641f227fac395e74bb1d837d07cfa70fa1e80"
  },
  "endpoint": {
    "pallet": "msa",
    "extrinsic": "grantDelegation"
  },
  "type": "addProvider",
  "payload": {
    "authorizedMsaId": 1,
    "schemaIds": [
      5,
      7,
      8,
      9,
      10
    ],
    "expiration": 24
  }
}

SCALE Payload Type

{
  authorizedMsaId: 'u64',
  schemaIds: 'Vec<u16>',
  expiration: 'u32',
}

Claim Handle

This payload follows the ClaimHandlePayload type from Frequency.

The signature is generated by signing the SCALE-encoded payload using SR25519.

Example

Example is signed using f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ which is the SS58 (Prefix 90) public key from the seed phrase //Bob.

{
  "signature": {
    "algo": "SR25519",
    "encoding": "base16",
    "encodedValue": "0xc8c7587ef80b6bd64295d63b69f97196a9a0b635bd8f1974156d7e3c7206134bb9838d29978a2f91c18a6592aff180f2314db7528b6aac796f0073d758406e81"
  },
  "endpoint": {
    "pallet": "handles",
    "extrinsic": "claimHandle"
  },
  "type": "claimHandle",
  "payload": {
    "baseHandle": "ExampleHandle",
    "expiration": 24
  }
}

SCALE Payload Type

{
  baseHandle: 'Bytes',
  expiration: 'u32',
}

User Item Actions

This payload follows the ItemizedSignaturePayloadV2 type from Frequency.

The signature is generated by signing the SCALE-encoded payload using SR25519.

Example

Example is signed using f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ which is the SS58 (Prefix 90) public key from the seed phrase //Bob.

{
  "signature": {
    "algo": "SR25519",
    "encoding": "base16",
    "encodedValue": "0x86bdd46a5f91ed3f259374f5856fdc48ee00b8eced10eecd05af8d7637c51d17df6252f617feacbce1cf91cc57ca036c69773ab9b0c31d6843344704b4fb898d"
  },
  "endpoint": {
    "pallet": "statefulStorage",
    "extrinsic": "applyItemActionsWithSignatureV2"
  },
  "type": "itemActions",
  "payload": {
    "schemaId": 7,
    "targetHash": 0,
    "expiration": 20,
    "actions": [
      {
        "type": "addItem",
        "payloadHex": "0x40eea1e39d2f154584c4b1ca8f228bb49ae5a14786ed63c90025e755f16bd58d37"
      }
    ]
  }
}

SCALE Payload Types

{
  PalletStatefulStorageItemActionEnumAdd: {
    data: 'Bytes',
  },
  PalletStatefulStorageItemActionEnumDelete: {
    index: 'u16',
  },
  PalletStatefulStorageItemAction: {
    _enum: {
      Add: '<PalletStatefulStorageItemActionEnumAdd>',
      Delete: '<PalletStatefulStorageItemActionEnumDelete>',
    },
  },
  PalletStatefulStorageItemizedSignaturePayloadV2: {
    schemaId: 'Compact<u16>',
    targetHash: 'Compact<u32>',
    expiration: 'u32',
    actions: 'Vec<PalletStatefulStorageItemAction>',
  },
}

Data Structure Reference

Request / Response from SIWF

Request

{
  "signedRequest": "eyJyZXF1ZXN0ZWRTaWduYXR1cmVzIjp7InB1YmxpY0tleSI6eyJlbmNvZGVkVmFsdWUiOiJmNmNMNHdxMUhVTngxMVRjdmRBQk5mOVVOWFhveUg0N21WVXdUNTl0elNGUlc4eURIIiwiZW5jb2RpbmciOiJiYXNlNTgiLCJmb3JtYXQiOiJzczU4IiwidHlwZSI6IlNyMjU1MTkifSwic2lnbmF0dXJlIjp7ImFsZ28iOiJTUjI1NTE5IiwiZW5jb2RpbmciOiJiYXNlMTYiLCJlbmNvZGVkVmFsdWUiOiIweDk2MGYxOTVkYzFmOTFiZjcxYzBiMzUyMzE1MGFlMzc0NzFiZWRlMDdhMDAzOTA5NjQ3Y2NmMDQwYWNkNWNkMDRlYTQ4NzBiZDEyNGNhZmEyZGViNTliMGUzNzhjYjE5ZmJjNmFmNjAxYjc1NTU5ZmFhYjdiNzY4ZGU4MWEwOTgzIn0sInBheWxvYWQiOnsiY2FsbGJhY2siOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJwZXJtaXNzaW9ucyI6WzUsNyw4LDksMTBdfX0sInJlcXVlc3RlZENyZWRlbnRpYWxzIjpbeyJ0eXBlIjoiVmVyaWZpZWRHcmFwaEtleUNyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFtZHZteGQ1NHp2ZTVraWZ5Y2dzZHRvYWhzNWVjZjRoYWwydHMzZWV4a2dvY3ljNW9jYTJ5Il19LHsiYW55T2YiOlt7InR5cGUiOiJWZXJpZmllZEVtYWlsQWRkcmVzc0NyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFlNHFvY3poZnRpY2k0ZHpmdmZiZWw3Zm80aDRzcjVncmNvM29vdnd5azZ5NHluZjQ0dHNpIl19LHsidHlwZSI6IlZlcmlmaWVkUGhvbmVOdW1iZXJDcmVkZW50aWFsIiwiaGFzaCI6WyJiY2lxanNwbmJ3cGMzd2p4NGZld2NlazVkYXlzZGpwYmY1eGppbXo1d251NXVqN2UzdnUydXducSJdfV19XX0",
  "mode": "dark"
}

Request URL

"https://testnet.frequencyaccess.com/siwa/start?signedRequest=eyJyZXF1ZXN0ZWRTaWduYXR1cmVzIjp7InB1YmxpY0tleSI6eyJlbmNvZGVkVmFsdWUiOiJmNmNMNHdxMUhVTngxMVRjdmRBQk5mOVVOWFhveUg0N21WVXdUNTl0elNGUlc4eURIIiwiZW5jb2RpbmciOiJiYXNlNTgiLCJmb3JtYXQiOiJzczU4IiwidHlwZSI6IlNyMjU1MTkifSwic2lnbmF0dXJlIjp7ImFsZ28iOiJTUjI1NTE5IiwiZW5jb2RpbmciOiJiYXNlMTYiLCJlbmNvZGVkVmFsdWUiOiIweDk2MGYxOTVkYzFmOTFiZjcxYzBiMzUyMzE1MGFlMzc0NzFiZWRlMDdhMDAzOTA5NjQ3Y2NmMDQwYWNkNWNkMDRlYTQ4NzBiZDEyNGNhZmEyZGViNTliMGUzNzhjYjE5ZmJjNmFmNjAxYjc1NTU5ZmFhYjdiNzY4ZGU4MWEwOTgzIn0sInBheWxvYWQiOnsiY2FsbGJhY2siOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJwZXJtaXNzaW9ucyI6WzUsNyw4LDksMTBdfX0sInJlcXVlc3RlZENyZWRlbnRpYWxzIjpbeyJ0eXBlIjoiVmVyaWZpZWRHcmFwaEtleUNyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFtZHZteGQ1NHp2ZTVraWZ5Y2dzZHRvYWhzNWVjZjRoYWwydHMzZWV4a2dvY3ljNW9jYTJ5Il19LHsiYW55T2YiOlt7InR5cGUiOiJWZXJpZmllZEVtYWlsQWRkcmVzc0NyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFlNHFvY3poZnRpY2k0ZHpmdmZiZWw3Zm80aDRzcjVncmNvM29vdnd5azZ5NHluZjQ0dHNpIl19LHsidHlwZSI6IlZlcmlmaWVkUGhvbmVOdW1iZXJDcmVkZW50aWFsIiwiaGFzaCI6WyJiY2lxanNwbmJ3cGMzd2p4NGZld2NlazVkYXlzZGpwYmY1eGppbXo1d251NXVqN2UzdnUydXducSJdfV19XX0&mode=dark"

Signed Request

This is JSON stringified and then base64url encoded for the Request signedRequest value.

{
  "requestedSignatures": {
    "publicKey": {
      "encodedValue": "f6cL4wq1HUNx11TcvdABNf9UNXXoyH47mVUwT59tzSFRW8yDH",
      "encoding": "base58",
      "format": "ss58",
      "type": "Sr25519"
    },
    "signature": {
      "algo": "SR25519",
      "encoding": "base16",
      "encodedValue": "0x0407ce814b77861df94d16b3fcb317d37a07abc2a7f9cd7c02cc22529ee7b32d56795f88bd6b4ad106b72b91b6246a783671bcd24cb01aaf0e9316db5e0cd085"
    },
    "payload": {
      "callback": "http://localhost:3000",
      "permissions": [
        5,
        7,
        8,
        9,
        10
      ]
    }
  },
  "requestedCredentials": [
    {
      "type": "VerifiedGraphKeyCredential",
      "hash": [
        "bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y"
      ]
    },
    {
      "anyOf": [
        {
          "type": "VerifiedEmailAddressCredential",
          "hash": [
            "bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi"
          ]
        },
        {
          "type": "VerifiedPhoneNumberCredential",
          "hash": [
            "bciqjspnbwpc3wjx4fewcek5daysdjpbf5xjimz5wnu5uj7e3vu2uwnq"
          ]
        }
      ]
    }
  ]
}

New Frequency User Response

{
  "userPublicKey": {
    "encodedValue": "f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ",
    "encoding": "base58",
    "format": "ss58",
    "type": "Sr25519"
  },
  "payloads": [
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0x1a27cb6d79b508e1ffc8d6ae70af78d5b3561cdc426124a06f230d7ce70e757e1947dd1bac8f9e817c30676a5fa6b06510bae1201b698b044ff0660c60f18c8a"
      },
      "endpoint": {
        "pallet": "msa",
        "extrinsic": "createSponsoredAccountWithDelegation"
      },
      "type": "addProvider",
      "payload": {
        "authorizedMsaId": 1,
        "schemaIds": [
          5,
          7,
          8,
          9,
          10
        ],
        "expiration": 24
      }
    },
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0x9eb338773b386ded2e3731ba68ba734c80408b3ad24f92ed3c60342d374a32293851fa8e41d722c72a5a4e765a9e401c68570a8c666ab678e4e5d94aa6825d85"
      },
      "endpoint": {
        "pallet": "statefulStorage",
        "extrinsic": "applyItemActionsWithSignatureV2"
      },
      "type": "itemActions",
      "payload": {
        "schemaId": 7,
        "targetHash": 0,
        "expiration": 20,
        "actions": [
          {
            "type": "addItem",
            "payloadHex": "0x40eea1e39d2f154584c4b1ca8f228bb49ae5a14786ed63c90025e755f16bd58d37"
          }
        ]
      }
    },
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0xb004140fd8ba3395cf5fcef49df8765d90023c293fde4eaf2e932cc24f74fc51b006c0bebcf31d85565648b4881fa22115e0051a3bdb95ab5bf7f37ac66f798f"
      },
      "endpoint": {
        "pallet": "handles",
        "extrinsic": "claimHandle"
      },
      "type": "claimHandle",
      "payload": {
        "baseHandle": "ExampleHandle",
        "expiration": 24
      }
    }
  ],
  "credentials": [
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedEmailAddressCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:web:frequencyaccess.com",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedEmailAddressCredential/bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "emailAddress": "john.doe@example.com",
        "lastVerified": "2024-08-21T21:27:59.309+0000"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:web:frequencyaccess.com#z6MkofWExWkUvTZeXb9TmLta5mBT6Qtj58es5Fqg1L5BCWQD",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z4jArnPwuwYxLnbBirLanpkcyBpmQwmyn5f3PdTYnxhpy48qpgvHHav6warjizjvtLMg6j3FK3BqbR2nuyT2UTSWC"
      }
    },
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedGraphKeyCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedGraphKeyCredential/bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "encodedPublicKeyValue": "0xb5032900293f1c9e5822fd9c120b253cb4a4dfe94c214e688e01f32db9eedf17",
        "encodedPrivateKeyValue": "0xd0910c853563723253c4ed105c08614fc8aaaf1b0871375520d72251496e8d87",
        "encoding": "base16",
        "format": "bare",
        "type": "X25519",
        "keyType": "dsnp.public-key-key-agreement"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:key:z6MktZ15TNtrJCW2gDLFjtjmxEdhCadNCaDizWABYfneMqhA",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z2HHWwtWggZfvGqNUk4S5AAbDGqZRFXjpMYAsXXmEksGxTk4DnnkN3upCiL1mhgwHNLkxY3s8YqNyYnmpuvUke7jF"
      }
    }
  ]
}

New Application/Delegation Response

{
  "userPublicKey": {
    "encodedValue": "f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ",
    "encoding": "base58",
    "format": "ss58",
    "type": "Sr25519"
  },
  "payloads": [
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0xbac399831b9e3ad464a16e62ad1252cc8344a2c52f80252b2aa450a06ae2362f6f4afcaca791a81f28eaa99080e2654bdbf1071a276213242fc153cca43cfa8e"
      },
      "endpoint": {
        "pallet": "msa",
        "extrinsic": "grantDelegation"
      },
      "type": "addProvider",
      "payload": {
        "authorizedMsaId": 1,
        "schemaIds": [
          5,
          7,
          8,
          9,
          10
        ],
        "expiration": 24
      }
    }
  ],
  "credentials": [
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedEmailAddressCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:web:frequencyaccess.com",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedEmailAddressCredential/bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "emailAddress": "john.doe@example.com",
        "lastVerified": "2024-08-21T21:27:59.309+0000"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:web:frequencyaccess.com#z6MkofWExWkUvTZeXb9TmLta5mBT6Qtj58es5Fqg1L5BCWQD",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z4jArnPwuwYxLnbBirLanpkcyBpmQwmyn5f3PdTYnxhpy48qpgvHHav6warjizjvtLMg6j3FK3BqbR2nuyT2UTSWC"
      }
    },
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedGraphKeyCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedGraphKeyCredential/bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "encodedPublicKeyValue": "0xb5032900293f1c9e5822fd9c120b253cb4a4dfe94c214e688e01f32db9eedf17",
        "encodedPrivateKeyValue": "0xd0910c853563723253c4ed105c08614fc8aaaf1b0871375520d72251496e8d87",
        "encoding": "base16",
        "format": "bare",
        "type": "X25519",
        "keyType": "dsnp.public-key-key-agreement"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:key:z6MktZ15TNtrJCW2gDLFjtjmxEdhCadNCaDizWABYfneMqhA",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z2HHWwtWggZfvGqNUk4S5AAbDGqZRFXjpMYAsXXmEksGxTk4DnnkN3upCiL1mhgwHNLkxY3s8YqNyYnmpuvUke7jF"
      }
    }
  ]
}

Login Only Response

{
  "userPublicKey": {
    "encodedValue": "f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ",
    "encoding": "base58",
    "format": "ss58",
    "type": "Sr25519"
  },
  "payloads": [
    {
      "signature": {
        "algo": "SR25519",
        "encoding": "base16",
        "encodedValue": "0xe261698297111834e68b4152bf1f89819e886b6528f6fff45715f7781d0f1e7dc4007ccfed1e85b8c603c0fea2f7abf22bfe6336869ad21f11a09a114452c680"
      },
      "type": "login",
      "payload": {
        "message": "your-app.com wants you to sign in with your Frequency account:\nf6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ\n\n\n\nURI: https://your-app.com/signin/callback\nNonce: N6rLwqyz34oUxJEXJ\nIssued At: 2024-10-29T19:17:27.077Z\nExpiration Time: 2060-03-05T23:23:03.041Z"
      }
    }
  ],
  "credentials": [
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedEmailAddressCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:web:frequencyaccess.com",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedEmailAddressCredential/bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "emailAddress": "john.doe@example.com",
        "lastVerified": "2024-08-21T21:27:59.309+0000"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:web:frequencyaccess.com#z6MkofWExWkUvTZeXb9TmLta5mBT6Qtj58es5Fqg1L5BCWQD",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z4jArnPwuwYxLnbBirLanpkcyBpmQwmyn5f3PdTYnxhpy48qpgvHHav6warjizjvtLMg6j3FK3BqbR2nuyT2UTSWC"
      }
    },
    {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/undefined-terms/v2"
      ],
      "type": [
        "VerifiedGraphKeyCredential",
        "VerifiableCredential"
      ],
      "issuer": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
      "validFrom": "2024-08-21T21:28:08.289+0000",
      "credentialSchema": {
        "type": "JsonSchema",
        "id": "https://schemas.frequencyaccess.com/VerifiedGraphKeyCredential/bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y.json"
      },
      "credentialSubject": {
        "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
        "encodedPublicKeyValue": "0xb5032900293f1c9e5822fd9c120b253cb4a4dfe94c214e688e01f32db9eedf17",
        "encodedPrivateKeyValue": "0xd0910c853563723253c4ed105c08614fc8aaaf1b0871375520d72251496e8d87",
        "encoding": "base16",
        "format": "bare",
        "type": "X25519",
        "keyType": "dsnp.public-key-key-agreement"
      },
      "proof": {
        "type": "DataIntegrityProof",
        "verificationMethod": "did:key:z6MktZ15TNtrJCW2gDLFjtjmxEdhCadNCaDizWABYfneMqhA",
        "cryptosuite": "eddsa-rdfc-2022",
        "proofPurpose": "assertionMethod",
        "proofValue": "z2HHWwtWggZfvGqNUk4S5AAbDGqZRFXjpMYAsXXmEksGxTk4DnnkN3upCiL1mhgwHNLkxY3s8YqNyYnmpuvUke7jF"
      }
    }
  ]
}

Verified User Data

Graph Key

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/undefined-terms/v2"
  ],
  "type": [
    "VerifiedGraphKeyCredential",
    "VerifiableCredential"
  ],
  "issuer": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
  "validFrom": "2024-08-21T21:28:08.289+0000",
  "credentialSchema": {
    "type": "JsonSchema",
    "id": "https://schemas.frequencyaccess.com/VerifiedGraphKeyCredential/bciqmdvmxd54zve5kifycgsdtoahs5ecf4hal2ts3eexkgocyc5oca2y.json"
  },
  "credentialSubject": {
    "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
    "encodedPublicKeyValue": "0xb5032900293f1c9e5822fd9c120b253cb4a4dfe94c214e688e01f32db9eedf17",
    "encodedPrivateKeyValue": "0xd0910c853563723253c4ed105c08614fc8aaaf1b0871375520d72251496e8d87",
    "encoding": "base16",
    "format": "bare",
    "type": "X25519",
    "keyType": "dsnp.public-key-key-agreement"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "verificationMethod": "did:key:z6MktZ15TNtrJCW2gDLFjtjmxEdhCadNCaDizWABYfneMqhA",
    "cryptosuite": "eddsa-rdfc-2022",
    "proofPurpose": "assertionMethod",
    "proofValue": "z2HHWwtWggZfvGqNUk4S5AAbDGqZRFXjpMYAsXXmEksGxTk4DnnkN3upCiL1mhgwHNLkxY3s8YqNyYnmpuvUke7jF"
  }
}

Verified Contact Credentials

Email

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/undefined-terms/v2"
  ],
  "type": [
    "VerifiedEmailAddressCredential",
    "VerifiableCredential"
  ],
  "issuer": "did:web:frequencyaccess.com",
  "validFrom": "2024-08-21T21:28:08.289+0000",
  "credentialSchema": {
    "type": "JsonSchema",
    "id": "https://schemas.frequencyaccess.com/VerifiedEmailAddressCredential/bciqe4qoczhftici4dzfvfbel7fo4h4sr5grco3oovwyk6y4ynf44tsi.json"
  },
  "credentialSubject": {
    "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
    "emailAddress": "john.doe@example.com",
    "lastVerified": "2024-08-21T21:27:59.309+0000"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "verificationMethod": "did:web:frequencyaccess.com#z6MkofWExWkUvTZeXb9TmLta5mBT6Qtj58es5Fqg1L5BCWQD",
    "cryptosuite": "eddsa-rdfc-2022",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4jArnPwuwYxLnbBirLanpkcyBpmQwmyn5f3PdTYnxhpy48qpgvHHav6warjizjvtLMg6j3FK3BqbR2nuyT2UTSWC"
  }
}

SMS/Phone

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/undefined-terms/v2"
  ],
  "type": [
    "VerifiedPhoneNumberCredential",
    "VerifiableCredential"
  ],
  "issuer": "did:web:frequencyaccess.com",
  "validFrom": "2024-08-21T21:28:08.289+0000",
  "credentialSchema": {
    "type": "JsonSchema",
    "id": "https://schemas.frequencyaccess.com/VerifiedPhoneNumberCredential/bciqjspnbwpc3wjx4fewcek5daysdjpbf5xjimz5wnu5uj7e3vu2uwnq.json"
  },
  "credentialSubject": {
    "id": "did:key:z6QNucQV4AF1XMQV4kngbmnBHwYa6mVswPEGrkFrUayhttT1",
    "phoneNumber": "+01-234-867-5309",
    "lastVerified": "2024-08-21T21:27:59.309+0000"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "verificationMethod": "did:web:frequencyaccess.com#z6MkofWExWkUvTZeXb9TmLta5mBT6Qtj58es5Fqg1L5BCWQD",
    "cryptosuite": "eddsa-rdfc-2022",
    "proofPurpose": "assertionMethod",
    "proofValue": "z5sJ2CjHX1wwgzfFGoZNocxeFKd2ffpo5TVgUvdaSkYq1M6gF7UjpYfePo97QoZgmiWdgPAWPjxFvGBysaxHV8DZ4"
  }
}