From 915155748469a1b3efe888ba4955dc9d7ed7053c Mon Sep 17 00:00:00 2001 From: "Mark M. Hendrickson" Date: Wed, 10 Jun 2020 17:27:06 +0200 Subject: [PATCH] Add back "Guide to Blockstack Auth" with modifications for Connect --- _data/navigation_home.yml | 4 +- _data/navigation_learn.yml | 13 +-- _develop/overview_auth.md | 157 +++++++++++++++++++++++++++++++++++++ _includes/sign_in.md | 8 +- 4 files changed, 170 insertions(+), 12 deletions(-) create mode 100644 _develop/overview_auth.md diff --git a/_data/navigation_home.yml b/_data/navigation_home.yml index dac77dac..c0363344 100644 --- a/_data/navigation_home.yml +++ b/_data/navigation_home.yml @@ -1,9 +1,9 @@ # Categories home page navigation - title: Build Decentralized Apps - desc: Learn how to build decentralized applications using Blockstack's storage and authentication tools. + desc: Learn how to build decentralized applications using Blockstack's authentication and storage tools. icon: code - doc: browser/hello-blockstack + doc: develop/overview_auth - title: Build Smart Contracts desc: Learn how to develop smart contracts using Blockstack's smart contracting language. diff --git a/_data/navigation_learn.yml b/_data/navigation_learn.yml index 3f89ec08..d56b91e3 100644 --- a/_data/navigation_learn.yml +++ b/_data/navigation_learn.yml @@ -1,3 +1,9 @@ +- title: Guides + docs: + - develop/overview_auth + - develop/storage + - develop/profiles + - title: Tutorials docs: - browser/hello-blockstack @@ -7,7 +13,7 @@ - android/tutorial - ios/tutorial -- title: Connect +- title: Blockstack Connect docs: - develop/connect/overview - develop/connect/get-started @@ -26,11 +32,6 @@ - develop/collections - develop/collection-type -- title: Guides - docs: - - develop/storage - - develop/profiles - - title: References docs: - common/javascript_ref diff --git a/_develop/overview_auth.md b/_develop/overview_auth.md new file mode 100644 index 00000000..30d87482 --- /dev/null +++ b/_develop/overview_auth.md @@ -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 AppConfig 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 Javascript and Ruby 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 + } +``` \ No newline at end of file diff --git a/_includes/sign_in.md b/_includes/sign_in.md index 4e48c337..d95327a0 100644 --- a/_includes/sign_in.md +++ b/_includes/sign_in.md @@ -1,16 +1,16 @@ For an application developer, the application flow is similar to the typical client-server flow used by centralized sign in services (e.g., OAuth). However, with Blockstack, the authentication flow happens entirely client-side. -A decentralized application (DApp) and the Blockstack Browser communicate during the authentication flow by passing back and forth two tokens. The requesting application sends the Blockstack Browser an `authRequest` token. Once a user approves a sign-in, the Blockstack Browser responds to the application with an `authResponse` token. These tokens are JSON Web Tokens, and they are passed via URL query strings. +A decentralized application and [the Blockstack App](https://github.com/blockstack/ux/tree/master/packages/app) communicate during the authentication flow by passing back and forth two tokens. The requesting application sends the Blockstack App an `authRequest` token. Once a user approves a sign-in, the Blockstack App responds to the application with an `authResponse` token. These tokens are JSON Web Tokens, and they are passed via URL query strings. ![](/storage/images/app-sign-in.png) -When a user chooses to **Sign in with Blockstack** on a DApp, it calls the `doOpenAuth()` method which sends an `authRequest` to the Blockstack Authenticator. Blockstack passes the token in via a URL query string in the `authRequest` parameter: +When a user chooses to authenticate a decentralized application, it calls the `doOpenAuth()` method which sends an `authRequest` to the Blockstack App. Blockstack passes the token in via a URL query string in the `authRequest` parameter: `https://app.blockstack.org/#/sign-up?authRequest=j902120cn829n1jnvoa...` -When the Blockstack Browser receives the request, it generates an (`authResponse`) token to the application using an _ephemeral transit key_ . The ephemeral transit key is just used for the particular instance of the application, in this case, to sign the `authRequest`. The application stores the ephemeral transit key during the request generation. The public portion of the transit key is passed in the `authRequest` token. The Blockstack Browser uses the public portion of the key to encrypt an _app-private key_ which is returned via the `authResponse`. +When the Blockstack App receives the request, it generates an (`authResponse`) token to the application using an _ephemeral transit key_ . The ephemeral transit key is just used for the particular instance of the application, in this case, to sign the `authRequest`. The application stores the ephemeral transit key during the request generation. The public portion of the transit key is passed in the `authRequest` token. The Blockstack App uses the public portion of the key to encrypt an _app-private key_ which is returned via the `authResponse`. -During sign in, the Blockstack Browser generates the app-private key from the user's _identity-address private_ key and the application's `appDomain`. The app private key serves three functions: +During sign in, the Blockstack App generates the app-private key from the user's _identity-address private_ key and the application's `appDomain`. The app private key serves three functions: * It is used to create the credentials that give an app access to the Gaia storage bucket for that specific app. * It is used in the end-to-end encryption of files stored for the app in the user's Gaia storage.