mirror of https://github.com/lukechilds/docs.git
Mark M. Hendrickson
5 years ago
7 changed files with 176 additions and 15 deletions
@ -0,0 +1,157 @@ |
|||
--- |
|||
layout: learn |
|||
permalink: /:collection/:path.html |
|||
--- |
|||
|
|||
# Guide to Blockstack Auth |
|||
{:.no_toc} |
|||
|
|||
Blockstack Auth provides single sign on and authentication without third parties or remote servers. On this page, you'll get an overview of authentication from a developer perspective. The following topics are covered: |
|||
|
|||
* TOC |
|||
{:toc} |
|||
|
|||
## Authentication flow |
|||
|
|||
{% include sign_in.md %} |
|||
|
|||
## Scopes |
|||
|
|||
Scopes define the permissions requested from, and that a user accepts, through the sign-in dialog. |
|||
Decentralized apps may request any of the following scopes: |
|||
|
|||
| Scope | Definition | |
|||
| -------------- | ------------------------------------------------------------------------------------ | |
|||
| `store_write` | Read and write data to the user's Gaia hub in an app-specific storage bucket. | |
|||
| `publish_data` | Publish data so that other users of the app can discover and interact with the user. | | |
|||
|
|||
The permissions scope should be specified through the <a href="https://blockstack.github.io/blockstack.js/classes/appconfig.html" target="\_blank">AppConfig</a> object. If no `scopes` array is provided to the `redirectToSignIn` or `makeAuthRequest` |
|||
functions, the default is to request `['store_write']`. |
|||
|
|||
## Manifest file |
|||
|
|||
Decentralized apps have a manifest file. This file is based on the [W3C web app manifest specification](https://w3c.github.io/manifest/). The following is an example manifest file. |
|||
|
|||
``` |
|||
{ |
|||
"name": "Todo App", |
|||
"start_url": "http://blockstack-todos.appartisan.com", |
|||
"description": "A simple todo app build on blockstack", |
|||
"icons": [{ |
|||
"src": "http://blockstack-todos.appartisan.com/logo.png", |
|||
"sizes": "400x400", |
|||
"type": "image/png" |
|||
}] |
|||
} |
|||
``` |
|||
|
|||
The Blockstack App retrieves the manifest file from the app during the |
|||
authentication process and displays the information in it such as the |
|||
app `name` and to the user during sign in. The location of the app manifest file is specific |
|||
in the authentication request token and **must** be on the same origin as the app |
|||
requesting authentication. |
|||
|
|||
The manifest file **must** have [Cross-origin resource sharing (CORS) headers](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) that allow the manifest file to be fetched from any arbitrary source. This usually means returning a header like this: |
|||
|
|||
``` |
|||
Access-Control-Allow-Origin: * |
|||
``` |
|||
|
|||
How you implement CORS depends in part on which platform/service you use to serve your application. For example, Netlify and Firebase have two different ways of configuring CORS. Consult your vendor documentation for more information. |
|||
|
|||
## Key pairs |
|||
|
|||
Blockstack Auth makes extensive use of public key cryptography. Blockstack uses ECDSA with the `secp256k1` curve. The following sections describe the three public-private key pairs used in the authentication process: |
|||
|
|||
* how they're generated |
|||
* where they're used |
|||
* to whom the private key is disclosed |
|||
|
|||
### Transit private key |
|||
|
|||
The transit private is an ephemeral key that is used to encrypt secrets that |
|||
need to be passed from the Blockstack App to the decentralized 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 `public_keys` key of the authentication request token. The |
|||
Blockstack App 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. |
|||
|
|||
### Identity address private key |
|||
|
|||
The identity address private key is derived from the user's keychain phrase and |
|||
is the private key of the Blockstack username 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 App. |
|||
|
|||
This private key signs the authentication response token for an app to indicate that the user approves sign in to that app. |
|||
|
|||
### App private key |
|||
|
|||
The app private key is an app-specific private key that is generated from the |
|||
user's identity address private key using the `domain_name` as input. It is |
|||
deterministic in that for a given Blockstack username and `domain_name`, the same |
|||
private key is generated each time. |
|||
|
|||
The app private key is securely shared with the app on each authentication, encrypted by the Blockstack App with the transit public key. |
|||
|
|||
## JSON Web Token signatures |
|||
|
|||
Both the `authRequest` and the `authResponse` tokens are [JSON Web Tokens](https://jwt.io/), and they are passed via URL query strings. |
|||
|
|||
Blockstack's authentication tokens are based on the [RFC 7519 OAuth JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) |
|||
with additional support for the `secp256k1` curve used by Bitcoin and many other |
|||
cryptocurrencies. |
|||
|
|||
This signature algorithm is indicated by specifying `ES256K` in the token's |
|||
`alg` key, specifying that the JWT signature uses ECDSA with the secp256k1 |
|||
curve. Blockstack provide both [JavaScript](https://github.com/blockstack/jsontokens-js) |
|||
and |
|||
[Ruby](https://github.com/blockstack/ruby-jwt-blockstack/tree/ruby-jwt-blockstack) |
|||
JWT libraries with support for this signing algorithm. |
|||
|
|||
|
|||
{% include note.html content="The Blockstack JWT implementation is different from other implementations because of the underlying cryptography we employ. There are libraries in <a href='https://github.com/blockstack/jsontokens-js'>Javascript</a> and <a href='https://github.com/blockstack/ruby-jwt-blockstack'>Ruby</a> available on the Blockstack Github to allow you to work with these tokens." %} |
|||
|
|||
### Example: authRequest payload schema |
|||
|
|||
``` JavaScript |
|||
const requestPayload = { |
|||
jti, // UUID |
|||
iat, // JWT creation time in seconds |
|||
exp, // JWT expiration time in seconds |
|||
iss, // legacy decentralized identifier generated from transit key |
|||
public_keys, // single entry array with public key of transit key |
|||
domain_name, // app origin |
|||
manifest_uri, // url to manifest file - must be hosted on app origin |
|||
redirect_uri, // url to which the Blockstack App redirects user on auth approval - must be hosted on app origin |
|||
version, // version tuple |
|||
do_not_include_profile, // a boolean flag asking Blockstack App to send profile url instead of profile object |
|||
supports_hub_url, // a boolean flag indicating gaia hub support |
|||
scopes // an array of string values indicating scopes requested by the app |
|||
} |
|||
``` |
|||
|
|||
|
|||
### Example: authResponse payload schema |
|||
|
|||
```JavaScript |
|||
const responsePayload = { |
|||
jti, // UUID |
|||
iat, // JWT creation time in seconds |
|||
exp, // JWT expiration time in seconds |
|||
iss, // legacy decentralized identifier (string prefix + identity address) - this uniquely identifies the user |
|||
private_key, // encrypted private key payload |
|||
public_keys, // single entry array with public key |
|||
profile, // profile object or null if passed by profile_url |
|||
username, // blockstack username (if any) |
|||
core_token, // encrypted core token payload |
|||
email, // email if email scope is requested & email available |
|||
profile_url, // url to signed profile token |
|||
hubUrl, // url pointing to user's gaia hub |
|||
version // version tuple |
|||
} |
|||
``` |
Loading…
Reference in new issue