blockstack
Version:
The Blockstack Javascript library for authentication, identity, and storage.
1,805 lines • 794 kB
JSON
[
{
"name": "Authentication",
"kind": "note",
"description": {
"type": "root",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Blockstack Authentication provides single sign on and authentication without third parties or remote servers. Blockstack Authentication is a bearer token-based authentication system. From an app user's perspective, it functions similar to legacy third-party authentication techniques that they're familiar with. For an app developer, the flow is a bit different from the typical client-server flow of centralized sign in services (e.g., OAuth). Rather, with Blockstack, the authentication flow happens entirely client-side.",
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 524,
"offset": 523
},
"indent": []
}
}
],
"position": {
"start": {
"line": 1,
"column": 1,
"offset": 0
},
"end": {
"line": 1,
"column": 524,
"offset": 523
},
"indent": []
}
},
{
"type": "heading",
"depth": 2,
"children": [
{
"type": "text",
"value": "Quickstart",
"position": {
"start": {
"line": 3,
"column": 4,
"offset": 528
},
"end": {
"line": 3,
"column": 14,
"offset": 538
},
"indent": []
}
}
],
"position": {
"start": {
"line": 3,
"column": 1,
"offset": 525
},
"end": {
"line": 3,
"column": 14,
"offset": 538
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "1) Install ",
"position": {
"start": {
"line": 5,
"column": 1,
"offset": 540
},
"end": {
"line": 5,
"column": 12,
"offset": 551
},
"indent": []
}
},
{
"type": "inlineCode",
"value": "blockstack.js",
"position": {
"start": {
"line": 5,
"column": 12,
"offset": 551
},
"end": {
"line": 5,
"column": 27,
"offset": 566
},
"indent": []
}
},
{
"type": "text",
"value": ":",
"position": {
"start": {
"line": 5,
"column": 27,
"offset": 566
},
"end": {
"line": 5,
"column": 28,
"offset": 567
},
"indent": []
}
}
],
"position": {
"start": {
"line": 5,
"column": 1,
"offset": 540
},
"end": {
"line": 5,
"column": 28,
"offset": 567
},
"indent": []
}
},
{
"type": "code",
"lang": "bash",
"value": "npm install blockstack --save",
"position": {
"start": {
"line": 7,
"column": 1,
"offset": 569
},
"end": {
"line": 9,
"column": 4,
"offset": 610
},
"indent": [
1,
1
]
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "2) Import Blockstack into your project",
"position": {
"start": {
"line": 11,
"column": 1,
"offset": 612
},
"end": {
"line": 11,
"column": 39,
"offset": 650
},
"indent": []
}
}
],
"position": {
"start": {
"line": 11,
"column": 1,
"offset": 612
},
"end": {
"line": 11,
"column": 39,
"offset": 650
},
"indent": []
}
},
{
"type": "code",
"lang": "js",
"value": "import * as blockstack from 'blockstack'",
"position": {
"start": {
"line": 13,
"column": 1,
"offset": 652
},
"end": {
"line": 15,
"column": 4,
"offset": 702
},
"indent": [
1,
1
]
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "3) Wire up a sign in button",
"position": {
"start": {
"line": 17,
"column": 1,
"offset": 704
},
"end": {
"line": 17,
"column": 28,
"offset": 731
},
"indent": []
}
}
],
"position": {
"start": {
"line": 17,
"column": 1,
"offset": 704
},
"end": {
"line": 17,
"column": 28,
"offset": 731
},
"indent": []
}
},
{
"type": "code",
"lang": "js",
"value": "document.getElementById('signin-button').addEventListener('click', function() {\n blockstack.redirectToSignIn()\n})",
"position": {
"start": {
"line": 19,
"column": 1,
"offset": 733
},
"end": {
"line": 23,
"column": 4,
"offset": 857
},
"indent": [
1,
1,
1,
1
]
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "4) Wire up a sign out button",
"position": {
"start": {
"line": 25,
"column": 1,
"offset": 859
},
"end": {
"line": 25,
"column": 29,
"offset": 887
},
"indent": []
}
}
],
"position": {
"start": {
"line": 25,
"column": 1,
"offset": 859
},
"end": {
"line": 25,
"column": 29,
"offset": 887
},
"indent": []
}
},
{
"type": "code",
"lang": "js",
"value": "document.getElementById('signout-button').addEventListener('click', function() {\n blockstack.signUserOut(window.location.origin)\n})",
"position": {
"start": {
"line": 27,
"column": 1,
"offset": 889
},
"end": {
"line": 31,
"column": 4,
"offset": 1031
},
"indent": [
1,
1,
1,
1
]
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "5) Include the logic to (a) load user data (b) handle the auth response",
"position": {
"start": {
"line": 33,
"column": 1,
"offset": 1033
},
"end": {
"line": 33,
"column": 72,
"offset": 1104
},
"indent": []
}
}
],
"position": {
"start": {
"line": 33,
"column": 1,
"offset": 1033
},
"end": {
"line": 33,
"column": 72,
"offset": 1104
},
"indent": []
}
},
{
"type": "code",
"lang": "js",
"value": "function showProfile(profile) {\n var person = new blockstack.Person(profile)\n document.getElementById('heading-name').innerHTML = person.name()\n document.getElementById('avatar-image').setAttribute('src', person.avatarUrl())\n document.getElementById('section-1').style.display = 'none'\n document.getElementById('section-2').style.display = 'block'\n}\n\nif (blockstack.isUserSignedIn()) {\n const userData = blockstack.loadUserData()\n showProfile(userData.profile)\n} else if (blockstack.isSignInPending()) {\n blockstack.handlePendingSignIn()\n .then(userData => {\n showProfile(userData.profile)\n })\n}",
"position": {
"start": {
"line": 35,
"column": 1,
"offset": 1106
},
"end": {
"line": 53,
"column": 4,
"offset": 1724
},
"indent": [
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1
]
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "6) Create a ",
"position": {
"start": {
"line": 55,
"column": 1,
"offset": 1726
},
"end": {
"line": 55,
"column": 13,
"offset": 1738
},
"indent": []
}
},
{
"type": "inlineCode",
"value": "manifest.json",
"position": {
"start": {
"line": 55,
"column": 13,
"offset": 1738
},
"end": {
"line": 55,
"column": 28,
"offset": 1753
},
"indent": []
}
},
{
"type": "text",
"value": " file",
"position": {
"start": {
"line": 55,
"column": 28,
"offset": 1753
},
"end": {
"line": 55,
"column": 33,
"offset": 1758
},
"indent": []
}
}
],
"position": {
"start": {
"line": 55,
"column": 1,
"offset": 1726
},
"end": {
"line": 55,
"column": 33,
"offset": 1758
},
"indent": []
}
},
{
"type": "code",
"lang": "json",
"value": "{\n \"name\": \"Hello, Blockstack\",\n \"start_url\": \"localhost:5000\",\n \"description\": \"A simple demo of Blockstack Auth\",\n \"icons\": [{\n \"src\": \"https://helloblockstack.com/icon-192x192.png\",\n \"sizes\": \"192x192\",\n \"type\": \"image/png\"\n }]\n}",
"position": {
"start": {
"line": 57,
"column": 1,
"offset": 1760
},
"end": {
"line": 68,
"column": 4,
"offset": 2018
},
"indent": [
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1
]
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Make sure your ",
"position": {
"start": {
"line": 70,
"column": 1,
"offset": 2020
},
"end": {
"line": 70,
"column": 16,
"offset": 2035
},
"indent": []
}
},
{
"type": "inlineCode",
"value": "manifest.json",
"position": {
"start": {
"line": 70,
"column": 16,
"offset": 2035
},
"end": {
"line": 70,
"column": 31,
"offset": 2050
},
"indent": []
}
},
{
"type": "text",
"value": " file has appropriate CORS headers so that it can\nbe fetched via an http ",
"position": {
"start": {
"line": 70,
"column": 31,
"offset": 2050
},
"end": {
"line": 71,
"column": 24,
"offset": 2123
},
"indent": [
1
]
}
},
{
"type": "inlineCode",
"value": "GET",
"position": {
"start": {
"line": 71,
"column": 24,
"offset": 2123
},
"end": {
"line": 71,
"column": 29,
"offset": 2128
},
"indent": []
}
},
{
"type": "text",
"value": " from any origin.",
"position": {
"start": {
"line": 71,
"column": 29,
"offset": 2128
},
"end": {
"line": 71,
"column": 46,
"offset": 2145
},
"indent": []
}
}
],
"position": {
"start": {
"line": 70,
"column": 1,
"offset": 2020
},
"end": {
"line": 71,
"column": 46,
"offset": 2145
},
"indent": [
1
]
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "7) Serve your application",
"position": {
"start": {
"line": 74,
"column": 1,
"offset": 2148
},
"end": {
"line": 74,
"column": 26,
"offset": 2173
},
"indent": []
}
}
],
"position": {
"start": {
"line": 74,
"column": 1,
"offset": 2148
},
"end": {
"line": 74,
"column": 26,
"offset": 2173
},
"indent": []
}
},
{
"type": "heading",
"depth": 2,
"children": [
{
"type": "text",
"value": "User flow",
"position": {
"start": {
"line": 76,
"column": 4,
"offset": 2178
},
"end": {
"line": 76,
"column": 13,
"offset": 2187
},
"indent": []
}
}
],
"position": {
"start": {
"line": 76,
"column": 1,
"offset": 2175
},
"end": {
"line": 76,
"column": 13,
"offset": 2187
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "What follows is a walk through of the experience of a user, Alice, signing in to your app with Blockstack.",
"position": {
"start": {
"line": 78,
"column": 1,
"offset": 2189
},
"end": {
"line": 78,
"column": 107,
"offset": 2295
},
"indent": []
}
}
],
"position": {
"start": {
"line": 78,
"column": 1,
"offset": 2189
},
"end": {
"line": 78,
"column": 107,
"offset": 2295
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "First, Alice clicks the \"Sign in with Blockstack\" button on your app. She is redirected to her copy of the Blockstack Browser. The Blockstack Browser shows Alice an approval dialog with information about your app including:",
"position": {
"start": {
"line": 80,
"column": 1,
"offset": 2297
},
"end": {
"line": 80,
"column": 224,
"offset": 2520
},
"indent": []
}
}
],
"position": {
"start": {
"line": 80,
"column": 1,
"offset": 2297
},
"end": {
"line": 80,
"column": 224,
"offset": 2520
},
"indent": []
}
},
{
"type": "list",
"ordered": false,
"start": null,
"loose": false,
"children": [
{
"type": "listItem",
"loose": false,
"checked": null,
"children": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "The origin your app was served from",
"position": {
"start": {
"line": 82,
"column": 3,
"offset": 2524
},
"end": {
"line": 82,
"column": 38,
"offset": 2559
},
"indent": []
}
}
],
"position": {
"start": {
"line": 82,
"column": 3,
"offset": 2524
},
"end": {
"line": 82,
"column": 38,
"offset": 2559
},
"indent": []
}
}
],
"position": {
"start": {
"line": 82,
"column": 1,
"offset": 2522
},
"end": {
"line": 82,
"column": 38,
"offset": 2559
},
"indent": []
}
},
{
"type": "listItem",
"loose": false,
"checked": null,
"children": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Your app's name",
"position": {
"start": {
"line": 83,
"column": 3,
"offset": 2562
},
"end": {
"line": 83,
"column": 18,
"offset": 2577
},
"indent": []
}
}
],
"position": {
"start": {
"line": 83,
"column": 3,
"offset": 2562
},
"end": {
"line": 83,
"column": 18,
"offset": 2577
},
"indent": []
}
}
],
"position": {
"start": {
"line": 83,
"column": 1,
"offset": 2560
},
"end": {
"line": 83,
"column": 18,
"offset": 2577
},
"indent": []
}
},
{
"type": "listItem",
"loose": false,
"checked": null,
"children": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Your app's logo",
"position": {
"start": {
"line": 84,
"column": 3,
"offset": 2580
},
"end": {
"line": 84,
"column": 18,
"offset": 2595
},
"indent": []
}
}
],
"position": {
"start": {
"line": 84,
"column": 3,
"offset": 2580
},
"end": {
"line": 84,
"column": 18,
"offset": 2595
},
"indent": []
}
}
],
"position": {
"start": {
"line": 84,
"column": 1,
"offset": 2578
},
"end": {
"line": 84,
"column": 18,
"offset": 2595
},
"indent": []
}
},
{
"type": "listItem",
"loose": false,
"checked": null,
"children": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "The types of permissions and data your app is requesting",
"position": {
"start": {
"line": 85,
"column": 3,
"offset": 2598
},
"end": {
"line": 85,
"column": 59,
"offset": 2654
},
"indent": []
}
}
],
"position": {
"start": {
"line": 85,
"column": 3,
"offset": 2598
},
"end": {
"line": 85,
"column": 59,
"offset": 2654
},
"indent": []
}
}
],
"position": {
"start": {
"line": 85,
"column": 1,
"offset": 2596
},
"end": {
"line": 85,
"column": 59,
"offset": 2654
},
"indent": []
}
}
],
"position": {
"start": {
"line": 82,
"column": 1,
"offset": 2522
},
"end": {
"line": 85,
"column": 59,
"offset": 2654
},
"indent": [
1,
1,
1
]
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Alice can choose to authenticate as one of her Blockstack IDs by selecting the ID and clicking the Approve button.",
"position": {
"start": {
"line": 87,
"column": 1,
"offset": 2656
},
"end": {
"line": 87,
"column": 115,
"offset": 2770
},
"indent": []
}
}
],
"position": {
"start": {
"line": 87,
"column": 1,
"offset": 2656
},
"end": {
"line": 87,
"column": 115,
"offset": 2770
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "When she clicks approve, she's redirected back to your app. Your app gets cryptographic proof that she is who she claims to be, access to a dedicated bucket in her Gaia storage hub for your app to read and write its own data along with public information she's stored in her profile.",
"position": {
"start": {
"line": 89,
"column": 1,
"offset": 2772
},
"end": {
"line": 89,
"column": 284,
"offset": 3055
},
"indent": []
}
}
],
"position": {
"start": {
"line": 89,
"column": 1,
"offset": 2772
},
"end": {
"line": 89,
"column": 284,
"offset": 3055
},
"indent": []
}
},
{
"type": "heading",
"depth": 2,
"children": [
{
"type": "text",
"value": "Manifest file",
"position": {
"start": {
"line": 91,
"column": 4,
"offset": 3060
},
"end": {
"line": 91,
"column": 17,
"offset": 3073
},
"indent": []
}
}
],
"position": {
"start": {
"line": 91,
"column": 1,
"offset": 3057
},
"end": {
"line": 91,
"column": 17,
"offset": 3073
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Blockstack apps have a manifest file based on the ",
"position": {
"start": {
"line": 93,
"column": 1,
"offset": 3075
},
"end": {
"line": 93,
"column": 51,
"offset": 3125
},
"indent": []
}
},
{
"type": "link",
"title": null,
"url": "https://w3c.github.io/manifest/",
"children": [
{
"type": "text",
"value": "W3C web app manifest specification",
"position": {
"start": {
"line": 93,
"column": 52,
"offset": 3126
},
"end": {
"line": 93,
"column": 86,
"offset": 3160
},
"indent": []
}
}
],
"position": {
"start": {
"line": 93,
"column": 51,
"offset": 3125
},
"end": {
"line": 93,
"column": 120,
"offset": 3194
},
"indent": []
}
},
{
"type": "text",
"value": ". The Blockstack Browser retrieves the manifest file from the app during the authentication process and displays some of the information in it such as the app name and icon to the user. The location of the app manifest file is specific in the authentication request token and ",
"position": {
"start": {
"line": 93,
"column": 120,
"offset": 3194
},
"end": {
"line": 93,
"column": 396,
"offset": 3470
},
"indent": []
}
},
{
"type": "emphasis",
"children": [
{
"type": "text",
"value": "MUST",
"position": {
"start": {
"line": 93,
"column": 397,
"offset": 3471
},
"end": {
"line": 93,
"column": 401,
"offset": 3475
},
"indent": []
}
}
],
"position": {
"start": {
"line": 93,
"column": 396,
"offset": 3470
},
"end": {
"line": 93,
"column": 402,
"offset": 3476
},
"indent": []
}
},
{
"type": "text",
"value": " be on the same origin as the app requesting authentication.",
"position": {
"start": {
"line": 93,
"column": 402,
"offset": 3476
},
"end": {
"line": 93,
"column": 462,
"offset": 3536
},
"indent": []
}
}
],
"position": {
"start": {
"line": 93,
"column": 1,
"offset": 3075
},
"end": {
"line": 93,
"column": 462,
"offset": 3536
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Below is an example of a manifest file:",
"position": {
"start": {
"line": 95,
"column": 1,
"offset": 3538
},
"end": {
"line": 95,
"column": 40,
"offset": 3577
},
"indent": []
}
}
],
"position": {
"start": {
"line": 95,
"column": 1,
"offset": 3538
},
"end": {
"line": 95,
"column": 40,
"offset": 3577
},
"indent": []
}
},
{
"type": "code",
"lang": null,
"value": "{\n \"name\": \"Todo App\",\n \"start_url\": \"http://blockstack-todos.appartisan.com\",\n \"description\": \"A simple todo app build on blockstack\",\n \"icons\": [{\n \"src\": \"http://blockstack-todos.appartisan.com/logo.png\",\n \"sizes\": \"400x400\",\n \"type\": \"image/png\"\n }]\n}",
"position": {
"start": {
"line": 97,
"column": 1,
"offset": 3579
},
"end": {
"line": 108,
"column": 4,
"offset": 3856
},
"indent": [
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1
]
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "The manifest file ",
"position": {
"start": {
"line": 110,
"column": 1,
"offset": 3858
},
"end": {
"line": 110,
"column": 19,
"offset": 3876
},
"indent": []
}
},
{
"type": "emphasis",
"children": [
{
"type": "text",
"value": "MUST",
"position": {
"start": {
"line": 110,
"column": 20,
"offset": 3877
},
"end": {
"line": 110,
"column": 24,
"offset": 3881
},
"indent": []
}
}
],
"position": {
"start": {
"line": 110,
"column": 19,
"offset": 3876
},
"end": {
"line": 110,
"column": 25,
"offset": 3882
},
"indent": []
}
},
{
"type": "text",
"value": " have ",
"position": {
"start": {
"line": 110,
"column": 25,
"offset": 3882
},
"end": {
"line": 110,
"column": 31,
"offset": 3888
},
"indent": []
}
},
{
"type": "link",
"title": null,
"url": "https://en.wikipedia.org/wiki/Cross-origin_resource_sharing",
"children": [
{
"type": "text",
"value": "Cross-origin resource sharing (CORS) headers",
"position": {
"start": {
"line": 110,
"column": 32,
"offset": 3889
},
"end": {
"line": 110,
"column": 76,
"offset": 3933
},
"indent": []
}
}
],
"position": {
"start": {
"line": 110,
"column": 31,
"offset": 3888
},
"end": {
"line": 110,
"column": 138,
"offset": 3995
},
"indent": []
}
},
{
"type": "text",
"value": " that allow the manifest file to be fetched from any arbitrary source. This usually means returning:",
"position": {
"start": {
"line": 110,
"column": 138,
"offset": 3995
},
"end": {
"line": 110,
"column": 238,
"offset": 4095
},
"indent": []
}
}
],
"position": {
"start": {
"line": 110,
"column": 1,
"offset": 3858
},
"end": {
"line": 110,
"column": 238,
"offset": 4095
},
"indent": []
}
},
{
"type": "code",
"lang": null,
"value": "Access-Control-Allow-Origin: *",
"position": {
"start": {
"line": 112,
"column": 1,
"offset": 4097
},
"end": {
"line": 114,
"column": 4,
"offset": 4135
},
"indent": [
1,
1
]
}
},
{
"type": "heading",
"depth": 2,
"children": [
{
"type": "text",
"value": "Key pairs",
"position": {
"start": {
"line": 116,
"column": 4,
"offset": 4140
},
"end": {
"line": 116,
"column": 13,
"offset": 4149
},
"indent": []
}
}
],
"position": {
"start": {
"line": 116,
"column": 1,
"offset": 4137
},
"end": {
"line": 116,
"column": 13,
"offset": 4149
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Blockstack Authentication makes extensive use of public key cryptography. As mentioned above, we use ECDSA with the secp256k1 curve. What follows is a description of the various public-private key pairs used in the authentication process including how they're generated, where they're used and to whom the private key is disclosed.",
"position": {
"start": {
"line": 118,
"column": 1,
"offset": 4151
},
"end": {
"line": 118,
"column": 332,
"offset": 4482
},
"indent": []
}
}
],
"position": {
"start": {
"line": 118,
"column": 1,
"offset": 4151
},
"end": {
"line": 118,
"column": 332,
"offset": 4482
},
"indent": []
}
},
{
"type": "heading",
"depth": 3,
"children": [
{
"type": "text",
"value": "Transit private key",
"position": {
"start": {
"line": 120,
"column": 5,
"offset": 4488
},
"end": {
"line": 120,
"column": 24,
"offset": 4507
},
"indent": []
}
}
],
"position": {
"start": {
"line": 120,
"column": 1,
"offset": 4484
},
"end": {
"line": 120,
"column": 24,
"offset": 4507
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "The transit private is an ephemeral key that is used to encrypt secrets that need to be passed from the Blockstack Browser to the app during the authentication process. It is randomly generated by the app at the beginning of the authentication response. The public key that corresponds to the transit private key is stored in a single element array in the ",
"position": {
"start": {
"line": 122,
"column": 1,
"offset": 4509
},
"end": {
"line": 122,
"column": 357,
"offset": 4865
},
"indent": []
}
},
{
"type": "inlineCode",
"value": "public_keys",
"position": {
"start": {
"line": 122,
"column": 357,
"offset": 4865
},
"end": {
"line": 122,
"column": 370,
"offset": 4878
},
"indent": []
}
},
{
"type": "text",
"value": " key of the authentication request token. The Blockstack Browser encrypts secret data such as the app private key using this public key and sends it back to the app when the user signs in to the app. The transit private key signs the app authentication request.",
"position": {
"start": {
"line": 122,
"column": 370,
"offset": 4878
},
"end": {
"line": 122,
"column": 631,
"offset": 5139
},
"indent": []
}
}
],
"position": {
"start": {
"line": 122,
"column": 1,
"offset": 4509
},
"end": {
"line": 122,
"column": 631,
"offset": 5139
},
"indent": []
}
},
{
"type": "heading",
"depth": 3,
"children": [
{
"type": "text",
"value": "Blockstack ID Identity address private key",
"position": {
"start": {
"line": 124,
"column": 5,
"offset": 5145
},
"end": {
"line": 124,
"column": 47,
"offset": 5187
},
"indent": []
}
}
],
"position": {
"start": {
"line": 124,
"column": 1,
"offset": 5141
},
"end": {
"line": 124,
"column": 47,
"offset": 5187
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "The identity address private key is derived from the user's keychain phrase and is the private key of the Blockstack ID that the user chooses to use to sign in to the app. It is a secret owned by the user and never leaves the user's instance of the Blockstack browser. This private key signs the authentication response token for an app to indicate that the user approves sign in to that app.",
"position": {
"start": {
"line": 126,
"column": 1,
"offset": 5189
},
"end": {
"line": 126,
"column": 393,
"offset": 5581
},
"indent": []
}
}
],
"position": {
"start": {
"line": 126,
"column": 1,
"offset": 5189
},
"end": {
"line": 126,
"column": 393,
"offset": 5581
},
"indent": []
}
},
{
"type": "heading",
"depth": 3,
"children": [
{
"type": "text",
"value": "App private key",
"position": {
"start": {
"line": 128,
"column": 5,
"offset": 5587
},
"end": {
"line": 128,
"column": 20,
"offset": 5602
},
"indent": []
}
}
],
"position": {
"start": {
"line": 128,
"column": 1,
"offset": 5583
},
"end": {
"line": 128,
"column": 20,
"offset": 5602
},
"indent": []
}
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "The app private key is an app-specific private key that is generated from the user's identity address private key using the ",
"position": {
"start": {
"line": 130,
"column": 1,
"offset": 5604
},
"end": {
"line": 130,
"column": 125,
"offset": 5728
},
"indent": []
}
},
{
"type": "inlineCode",
"value": "domain_name",
"position": {
"start": {
"line": 130,
"column": 125,
"offset": 5728
},
"end": {
"line": 130,
"column": 138,
"offset": 5741
},
"indent": []
}
},
{
"type": "text",
"value": " as input. It is deterministic in that for a given Blockstack ID and ",
"position": {
"start": {
"line": 130,
"column": 138