From 5a4bbb2b5360aae285882e2312561d52797108bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Fri, 19 Nov 2021 16:27:07 +0100 Subject: [PATCH 01/15] initial checkin --- sips/sip-x/sip-x-authentication-protocol.md | 70 +++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 sips/sip-x/sip-x-authentication-protocol.md diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md new file mode 100644 index 00000000..acb0520b --- /dev/null +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -0,0 +1,70 @@ +# Preamble + +SIP Number: X + +Title: Specification of Authentication Protcol + +Author: Friedger Müffke (mail@friedger.de) + +Consideration: Technical + +Type: Standard + +Status: Draft + +Created: 19 November 2021 + +License: CC0-1.0 + +Sign-off: + +# Abstract + +Decentralized application often require the authentication of their users. This SIP specifies a protocol between the application and an authenticator that results in a public key controlled by the user and a private key specific for the application for the user. + +# License and Copyright + +This SIP is made available under the terms of the Creative Commons CC0 1.0 Universal license, available at https://creativecommons.org/publicdomain/zero/1.0/ +This SIP’s copyright is held by the Stacks Open Internet Foundation. + +# Introduction + +Decentralized application do not want to store credentials of their users. Instead users should be able to login using some kind of cryptographic proof that they control a public key. + +The private key for that public key is guarded by a so-called authenticator. When a users visits the app, the app needs to communicate with the authenticator. In the authenticator, the user can control which public key should be shared with the application. + +In addition, to the public key more information can be shared like email address or profile pictures. In particular, a private key is derived by the authenticator specific for the application and for the user. This private key can be used by the application to access for example decentralized storage or sign messages in the name of the user of the application. + +# Specification + +## Authentication Flow + +### StacksAuthenticationProvider + +### Transport Protocol + +## Authentication Result Object + +### Public key + +### App key derivation + +### Profile + +# Out of Scope + +# Backwards Compatibility + +# Related Work + +## Unstoppabledomains auth + +## DID auth + +# Activation + +This SIP is activated if .. + +# Appendix A + +Transport protocols \ No newline at end of file From 6334407957e15fae9540ecddd494932bb265324f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Fri, 19 Nov 2021 19:17:41 +0100 Subject: [PATCH 02/15] add more details --- sips/sip-x/sip-x-authentication-protocol.md | 75 ++++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index acb0520b..83570d9e 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -39,11 +39,39 @@ In addition, to the public key more information can be shared like email address ## Authentication Flow -### StacksAuthenticationProvider +1. Application creates app transit private key, signs the auth request and sends to the authenticator. +2. User authorizes sharing of public key in authenticator, authenticator derives app private key from app domain . +3. Authenticator creates response and sends response to the application. -### Transport Protocol +https://cogarius.medium.com/blockstack-world-tour-brussels-social-dapp-workshop-fb0ef887b55f -## Authentication Result Object +## Transport Protocol + +The communication between application and authenticator can happen in various ways. It is defined by the transport protocol. + +### Stacks Provider + +Stacks Provider is a common interface used for web applications to communicate with the authenticator. + +It provides functions to handle +1. authentication +2. transaction signing + +https://github.com/hirosystems/connect/blob/main/packages/connect/src/types/provider.ts + + +### Deep Links + +Wise app uses deep links to handle request on mobile devices + +### Android Accounts + +Android provides an open account management system. + +Example implementation: https://github.com/openintents/calendar-sync/blob/master/app/src/main/java/org/openintents/calendar/common/accounts/GenericAccountService.kt + + +## Authentication Result ### Public key @@ -51,6 +79,10 @@ In addition, to the public key more information can be shared like email address ### Profile + +### Response Token +The response is a signed JWT. + # Out of Scope # Backwards Compatibility @@ -59,8 +91,45 @@ In addition, to the public key more information can be shared like email address ## Unstoppabledomains auth +https://unstoppabledomains.com/blog/login-with-unstoppable + ## DID auth +https://medium.com/@sethisaab/what-is-did-auth-and-how-does-it-works-1e4884383a53 + + +# Implementations + +## Libraries + +https://github.com/blockstack/connect + +https://github.com/fungible-systems/micro-stacks + +## Authenticators + + +### Hiro Wallet + +Hiro Wallet is an wallet that handles authentication and transaction signing. + +It uses a 24 mnemonic called SecretKey to derive private keys for different user accounts. + +Each account owns one private key to handle stx tokens (wallet key) and one private key to access storage (data key). + +The wallet key can own a BNS username. + +https://github.com/blockstack/stacks-wallet-web + +### Wise + +https://wiseapp.id + + +### Circles + +https://github.com/blocoio/stacks-circles-app + # Activation This SIP is activated if .. From 52439773ce604dbf83f671ee5a6a0422d80faead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Fri, 19 Nov 2021 19:22:22 +0100 Subject: [PATCH 03/15] add section about username --- sips/sip-x/sip-x-authentication-protocol.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index 83570d9e..ce30a7ad 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -71,9 +71,10 @@ Android provides an open account management system. Example implementation: https://github.com/openintents/calendar-sync/blob/master/app/src/main/java/org/openintents/calendar/common/accounts/GenericAccountService.kt -## Authentication Result +## Authentication Response -### Public key +### Public key and BNS Username +If the Stacks address representing the public key owns a BNS username, it is returned as part of the response. Other users can use the username to lookup metadata of other applications via the zonefile and the profile linked in the zonefile. The profile is signed with the private key belonging to the public key. ### App key derivation From d5407a1627ea91f7379e0b837782f35025bcec2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Fri, 19 Nov 2021 22:09:05 +0100 Subject: [PATCH 04/15] add wise source repo --- sips/sip-x/sip-x-authentication-protocol.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index ce30a7ad..1d81abb7 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -107,6 +107,8 @@ https://github.com/blockstack/connect https://github.com/fungible-systems/micro-stacks +https://github.com/PravicaInc/wise-js + ## Authenticators @@ -124,6 +126,8 @@ https://github.com/blockstack/stacks-wallet-web ### Wise +https://github.com/PravicaInc/Wise + https://wiseapp.id From 2147aa599c3abd4ed4c760bc533921658c05501e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Mon, 6 Dec 2021 10:52:21 +0100 Subject: [PATCH 05/15] fix typos --- sips/sip-x/sip-x-authentication-protocol.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index 1d81abb7..8692d888 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -31,9 +31,9 @@ This SIP’s copyright is held by the Stacks Open Internet Foundation. Decentralized application do not want to store credentials of their users. Instead users should be able to login using some kind of cryptographic proof that they control a public key. -The private key for that public key is guarded by a so-called authenticator. When a users visits the app, the app needs to communicate with the authenticator. In the authenticator, the user can control which public key should be shared with the application. +The private key for that public key is guarded and managed by a so-called authenticator. When a users visits the app, the app needs to communicate with the authenticator. In the authenticator, the user can control which public key should be shared with the application. -In addition, to the public key more information can be shared like email address or profile pictures. In particular, a private key is derived by the authenticator specific for the application and for the user. This private key can be used by the application to access for example decentralized storage or sign messages in the name of the user of the application. +In addition to the public key, more information can be shared like email address or profile pictures. In particular, a private key is derived by the authenticator specific for the application and for the user. This private key can be used by the application to access for example decentralized storage or sign messages in the name of the user of the application. # Specification From 43738df1b85cc45160b0bf8b40a7efc0b8fc44f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Fri, 17 Dec 2021 13:31:33 +0100 Subject: [PATCH 06/15] add description of profile --- sips/sip-x/sip-x-authentication-protocol.md | 98 +++++++++++++++------ 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index 8692d888..98f3ad16 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -2,7 +2,7 @@ SIP Number: X -Title: Specification of Authentication Protcol +Title: Specification of the Authentication Protcol Author: Friedger Müffke (mail@friedger.de) @@ -31,7 +31,7 @@ This SIP’s copyright is held by the Stacks Open Internet Foundation. Decentralized application do not want to store credentials of their users. Instead users should be able to login using some kind of cryptographic proof that they control a public key. -The private key for that public key is guarded and managed by a so-called authenticator. When a users visits the app, the app needs to communicate with the authenticator. In the authenticator, the user can control which public key should be shared with the application. +The private key for that public key is guarded and managed by a so-called authenticator. When a users visits the app, the app needs to communicate with the authenticator. In the authenticator, the user can control which public key should be shared with the application. In addition to the public key, more information can be shared like email address or profile pictures. In particular, a private key is derived by the authenticator specific for the application and for the user. This private key can be used by the application to access for example decentralized storage or sign messages in the name of the user of the application. @@ -39,53 +39,94 @@ In addition to the public key, more information can be shared like email address ## Authentication Flow -1. Application creates app transit private key, signs the auth request and sends to the authenticator. -2. User authorizes sharing of public key in authenticator, authenticator derives app private key from app domain . -3. Authenticator creates response and sends response to the application. +The basic flow of the authentication between the application and the authenticator (aka wallet or agent of the user) is as follows: + +1. Application creates app transit private key, signs an auth request with that key and sends the request to the Authenticator. +2. In the Authenticator, User authorizes sharing of public key, Authenticator derives app private key from request. +3. Authenticator creates response with authorized data and sends response to the Application. +4. Application verifies signature against the app transit private key. https://cogarius.medium.com/blockstack-world-tour-brussels-social-dapp-workshop-fb0ef887b55f +## Authentication Response + +The authentication response is a signed JWT that contains the requests and authorized data. The token is signed with the app transit key. + +### Public key and BNS Username + +If the Stacks address representing the public key owns a BNS username, it is returned as part of the response. Other users can use the username to lookup metadata of other applications via the zonefile and the profile linked in the zonefile. The profile is signed with the private key belonging to the public key. + +### App key derivation + +### Profile + +### App Meta Data + +### Response Token Schema + +The response is a signed json web token following standard [RFC 7519](https://tools.ietf.org/html/rfc7519). + +A typical header is + +``` +{ + "typ": "JWT", + "alg": "ES256K" +} +``` + +The payload must contain the following claims: + +| Claim name | Type | Description | +| ------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| jti | string | As defined in RFC7519 | +| iat | string | As defined in RFC7519 | +| exp | string | As defined in RFC7519 | +| iss | string | Decentralized identifier defined in DID specification | +| private_key | string | App private key for the provided domain | +| public_keys | array | Array of public keys owned by the user | +| profile | object | Object containing properties of the users, the object schema should be well-known type, like `Person` or `Organisation` defined by schema.org | +| profile.stxAddress | object | Object containing the user's stx address for mainnet and testnet in the form: `{mainnet: "S...", testnet: "S..."}` | +| profile.apps | object | Deprecated; use appsMeta. Storage endpoints for user data of different apps index by app urls | +| profile.appsMeta | object | Information about user data of different apps. Property names are the domain name of the app. Each property value is an object of containing properties for `storage` and `publicKey`. See "App Meta Data". | +| username | string | BNS username, owned by the first public key of `public_keys` claim. Can be empty string | +| profile_url | string | Resolvable url of the user's profile. | +| core_token | string? | | +| email | string? | User's email address. Can be null. | +| hub_url | string | User's storage hub url for the current app. | +| blockstackAPIUrl | string? | Deprecated. Url to the user's preferred authenticator | +| associationToken | string | Signed JWT to access gaia storage bucket of user's app data. | +| version | string | Version of this schema, must be "1.3.1" | + ## Transport Protocol The communication between application and authenticator can happen in various ways. It is defined by the transport protocol. ### Stacks Provider -Stacks Provider is a common interface used for web applications to communicate with the authenticator. +Stacks Provider is a common interface used for web applications to communicate with the authenticator. + +It provides functions to handle -It provides functions to handle 1. authentication 2. transaction signing https://github.com/hirosystems/connect/blob/main/packages/connect/src/types/provider.ts - ### Deep Links Wise app uses deep links to handle request on mobile devices ### Android Accounts -Android provides an open account management system. +Android provides an open account management system. Example implementation: https://github.com/openintents/calendar-sync/blob/master/app/src/main/java/org/openintents/calendar/common/accounts/GenericAccountService.kt - -## Authentication Response - -### Public key and BNS Username -If the Stacks address representing the public key owns a BNS username, it is returned as part of the response. Other users can use the username to lookup metadata of other applications via the zonefile and the profile linked in the zonefile. The profile is signed with the private key belonging to the public key. - -### App key derivation - -### Profile - - -### Response Token -The response is a signed JWT. - # Out of Scope +This SIP does not specify other flows between applications and authenticators like transaction signing or message encryption. + # Backwards Compatibility # Related Work @@ -98,7 +139,6 @@ https://unstoppabledomains.com/blog/login-with-unstoppable https://medium.com/@sethisaab/what-is-did-auth-and-how-does-it-works-1e4884383a53 - # Implementations ## Libraries @@ -111,10 +151,9 @@ https://github.com/PravicaInc/wise-js ## Authenticators - ### Hiro Wallet -Hiro Wallet is an wallet that handles authentication and transaction signing. +Hiro Wallet is an browser extension that handles authentication and transaction signing. It uses a 24 mnemonic called SecretKey to derive private keys for different user accounts. @@ -130,7 +169,6 @@ https://github.com/PravicaInc/Wise https://wiseapp.id - ### Circles https://github.com/blocoio/stacks-circles-app @@ -141,4 +179,8 @@ This SIP is activated if .. # Appendix A -Transport protocols \ No newline at end of file +Transport protocols + +``` + +``` From d9c16235651f45ee83cf24bdeceb309248b9bb78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Sun, 19 Dec 2021 13:29:31 +0100 Subject: [PATCH 07/15] fix grammar --- sips/sip-x/sip-x-authentication-protocol.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index 98f3ad16..12f6ec16 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -153,7 +153,7 @@ https://github.com/PravicaInc/wise-js ### Hiro Wallet -Hiro Wallet is an browser extension that handles authentication and transaction signing. +Hiro Wallet is a browser extension that handles authentication and transaction signing. It uses a 24 mnemonic called SecretKey to derive private keys for different user accounts. From c7049146826b9093404357e3468dcc5cdef009da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Wed, 5 Jan 2022 18:06:54 +0100 Subject: [PATCH 08/15] add authentication request --- sips/sip-x/sip-x-authentication-protocol.md | 76 ++++++++++++++------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index 12f6ec16..1c7c7aac 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -31,49 +31,68 @@ This SIP’s copyright is held by the Stacks Open Internet Foundation. Decentralized application do not want to store credentials of their users. Instead users should be able to login using some kind of cryptographic proof that they control a public key. -The private key for that public key is guarded and managed by a so-called authenticator. When a users visits the app, the app needs to communicate with the authenticator. In the authenticator, the user can control which public key should be shared with the application. +The private key for that public key is guarded and managed by a so-called authenticator. When a users visits the app, the app needs to communicate with the authenticator. The authenticator helps the user to choose a public key that should be shared with the application. -In addition to the public key, more information can be shared like email address or profile pictures. In particular, a private key is derived by the authenticator specific for the application and for the user. This private key can be used by the application to access for example decentralized storage or sign messages in the name of the user of the application. +In addition to the public key, more information can be shared like email address or profile pictures. Some data can be shared publicly, other only with the application. In particular, a private key is derived by the authenticator that is specific to the application and to the user. This private key can be used by the application to access for example decentralized storage or sign messages in the name of the user of the application. # Specification -## Authentication Flow - The basic flow of the authentication between the application and the authenticator (aka wallet or agent of the user) is as follows: 1. Application creates app transit private key, signs an auth request with that key and sends the request to the Authenticator. -2. In the Authenticator, User authorizes sharing of public key, Authenticator derives app private key from request. +2. In the Authenticator, User authorizes sharing of public key, Authenticator derives app private key from request and updates the user's public profile if required. 3. Authenticator creates response with authorized data and sends response to the Application. 4. Application verifies signature against the app transit private key. https://cogarius.medium.com/blockstack-world-tour-brussels-social-dapp-workshop-fb0ef887b55f -## Authentication Response +Requests and responses are signed json web tokens (JWT) following standard [RFC 7519](https://tools.ietf.org/html/rfc7519). -The authentication response is a signed JWT that contains the requests and authorized data. The token is signed with the app transit key. +The header of any JWT must be -### Public key and BNS Username +``` +{ + "typ": "JWT", + "alg": "ES256K" +} +``` -If the Stacks address representing the public key owns a BNS username, it is returned as part of the response. Other users can use the username to lookup metadata of other applications via the zonefile and the profile linked in the zonefile. The profile is signed with the private key belonging to the public key. +The payloads for the authentication request and the response are specified in the following sections. -### App key derivation +## Authentication Request -### Profile +The authentication request is a JWT created by the application. It is signed by a private key that is usually freshly generated. The key is called app transit key. The payload schema is defined as follows: -### App Meta Data +The payload must contain the following claims: -### Response Token Schema +| Claim name | Type | Description | +| ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------- | +| jti | string | As defined in RFC7519 | +| iat | string | As defined in RFC7519 | +| exp | string | As defined in RFC7519 | +| iss | string | Decentralized identifier defined in DID specification representing the user's account. | +| | +| public_keys | array | Single item list with the public key of the signer | +| domain_name | string | The url of the application with schema. | +| manifest_uri | string | The url of the application manifest, usually domain_name + "/manifest.json" | +| redirect_uri | string | The url that should receive the authentication response | +| do_not_include_profile | bool | | +| supports_hub_url | bool | | +| scopes | array | list of strings specifying the requested access to the user's account. See Append A for full list of scopes | +| version | string | must be "1.3.1" | -The response is a signed json web token following standard [RFC 7519](https://tools.ietf.org/html/rfc7519). +## User authorization -A typical header is +The authenticator manages the user' private keys. The protocol requires that keys are created using [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki). -``` -{ - "typ": "JWT", - "alg": "ES256K" -} -``` +Depending on the requested scopes the authenticator has to do the following operations: + +- Update public profile +- Create authentication response + +## Authentication Response + +The authentication response is a signed JWT that contains the requested and authorized data. The token is signed with the public key of the request signature, i.e. the app transit key. The payload must contain the following claims: @@ -82,7 +101,7 @@ The payload must contain the following claims: | jti | string | As defined in RFC7519 | | iat | string | As defined in RFC7519 | | exp | string | As defined in RFC7519 | -| iss | string | Decentralized identifier defined in DID specification | +| iss | string | Decentralized identifier defined in DID specification representing the user's account. | | private_key | string | App private key for the provided domain | | public_keys | array | Array of public keys owned by the user | | profile | object | Object containing properties of the users, the object schema should be well-known type, like `Person` or `Organisation` defined by schema.org | @@ -96,7 +115,18 @@ The payload must contain the following claims: | hub_url | string | User's storage hub url for the current app. | | blockstackAPIUrl | string? | Deprecated. Url to the user's preferred authenticator | | associationToken | string | Signed JWT to access gaia storage bucket of user's app data. | -| version | string | Version of this schema, must be "1.3.1" | +| version | string | Version of this schema, must be "1.3.1" + +### Public key and BNS Username + +If the Stacks address representing the public key owns a BNS username, it is returned as part of the response. Other users can use the username to lookup metadata of other applications via the zonefile and the profile linked in the zonefile. The profile is signed with the private key belonging to the public key. + +### App key derivation + +### Profile + +### App Meta Data + | ## Transport Protocol From cf77b8c2c865870ff3da23d0b0ad0bab5eb3b1f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Fri, 7 Jan 2022 02:04:27 +0100 Subject: [PATCH 09/15] add auth response, add transport protocols --- sips/sip-x/sip-x-authentication-protocol.md | 226 ++++++++++++++------ 1 file changed, 155 insertions(+), 71 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index 1c7c7aac..d46fe321 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -78,63 +78,137 @@ The payload must contain the following claims: | redirect_uri | string | The url that should receive the authentication response | | do_not_include_profile | bool | | | supports_hub_url | bool | | -| scopes | array | list of strings specifying the requested access to the user's account. See Append A for full list of scopes | -| version | string | must be "1.3.1" | +| scopes | array | list of strings specifying the requested access to the user's account. See Appendix A for full list of scopes | +| version | string | must be "2.0.0" | ## User authorization -The authenticator manages the user' private keys. The protocol requires that keys are created using [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki). +The authenticator manages the user' private keys. The protocol requires that keys are created from a deterministic wallet using [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki). -Depending on the requested scopes the authenticator has to do the following operations: +The authenticator can offer the user a list of accounts. Each account corresponds to a change of the key derivation path by 1. This SIP does not specify how the wallet determines which accounts should be presented. Only requirement is that one account is selected. The selected index shall be called account index `n`. -- Update public profile +Once the account index has been fixed, authenticator has to do the following operations: + +- Update public profile (depending on requested scopes) - Create authentication response +## Application Private Key + +If the authentication request contains the scope `storage_write`, then the authenticator must create a private key that is specific for the requesting application. It must use the following algorithm: + +1. Wallet salt: create the sha256 hash of the hex representation of the public key of derivation path (`m/888'/0'`) +1. Create sha256 hash of concatinated string of the `domain_name` from the request and the hex representation of the wallet salt. +1. Hash code: Create a hash code (as defined in Java and Javascript) from the hex representation of the hash, then apply bitwise `and` to the hash code and 0x7fffffff. +1. Use derivation path `m/888'/0'/n'/0'/_hash code_'` for the private key. + +## Public Profile + +Users who own a BNS username can publish a public profile with information about the account that owns the BNS username. The url of the publicly accessible profile is provided in the zone file of the BNS username. The process of attaching a zone file to a BNS username is part of name registration via the BNS contract. + +The public profile is used during authentication when the authentication request contains the scope `publish_data`. The profile then contains public meta data about the application that other users can use to find data shared with them. + +### Profile Storage + +It is recommended to use the [gaia protocol](https://github.com/blockstack/gaia) to publish the public profile. In this case, the gaia bucket must be used that is owned by the data private key, i.e. using derivation path `m/888'/0'/n'` (where `n` is the selected account index starting with 0). + +The profile must be stored as a JSON array containing a single JSON object with properties `token` and `decodedToken`. The values are a signed JWT token and its decoded representation. + +### Signed JWT + +The JWT must be signed by the private key of the stacks address that ownes the username of the select account. This should be the Stacks private key using the derivation path `m/44'/5757'/0'/0/n`. Some users might have used the data private key to register a username, therefore, authenticators must verify whether the username is owned by the signing private key at the time of signing. + +The JWT payload must have the following claims: + +| claim | description | +| ------- | -------------------------------------------------------------------------------------------------------------- | +| jti | as defined by RFC 7519 | +| iat | as defined by RFC 7519 | +| exp | as defined by RFC 7519 | +| subject | a json object with property `publicKey` containing the hex representation of the public key of the signing key | +| issuer | same as subject | +| claim | a json object containing data of the username owner mixed with meta data of applications used by the owner | + +#### Owner Data + +Personal data must not be published by the authenticator without consent of the user. If published, the authenticator must provide a method to remove this data as well. + +Examples of personal data are name and profile picture. + +The owner data shall use a well-known schema. See Appendix B for recommended schemas. + +#### Application Meta Data + +If the application requested to share data publicly through the scope `publish_data`, then the authenticator has to publish the public profile with information about the application's gaia bucket location. This is the gaia bucket owned by the application private key. The location and the public key are published as entry of the profile property `appsMeta`. The key of the entry is the `domain name` of the authorization request and the value is a JSON object of the following schema: + +``` +{ + "$schema": "http://json-schema.org/draft-2020-12/schema", + "type": "object", + "title": "Public profile application meta data", + "description": "Meta data for application specific storage", + "default": {}, + "examples": [ + { + "storage": "https://gaia.blockstack.org/hub/19xhuMssxAnLoa1yMTD7YNmhhaev5NBzv1/", + "publicKey": "03f2dea6295f8e4e7b05e092e4a97ad1a113143f820b65d9e4990a10fd8fcb0b1d" + } + ], + "required": [ + "storage", + "publicKey" + ], + "properties": { + "storage": { + "$id": "#/properties/storage", + "type": "string", + "title": "Storage location", + "description": "Url of the publicly readable gaia bucket owned by the application private key." + }, + "publicKey": { + "$id": "#/properties/publicKey", + "type": "string", + "title": "Public Key", + "description": "Hex representation of the public key of the application private key." + } + }, + "additionalProperties": true +} +``` + ## Authentication Response The authentication response is a signed JWT that contains the requested and authorized data. The token is signed with the public key of the request signature, i.e. the app transit key. The payload must contain the following claims: -| Claim name | Type | Description | -| ------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| jti | string | As defined in RFC7519 | -| iat | string | As defined in RFC7519 | -| exp | string | As defined in RFC7519 | -| iss | string | Decentralized identifier defined in DID specification representing the user's account. | -| private_key | string | App private key for the provided domain | -| public_keys | array | Array of public keys owned by the user | -| profile | object | Object containing properties of the users, the object schema should be well-known type, like `Person` or `Organisation` defined by schema.org | -| profile.stxAddress | object | Object containing the user's stx address for mainnet and testnet in the form: `{mainnet: "S...", testnet: "S..."}` | -| profile.apps | object | Deprecated; use appsMeta. Storage endpoints for user data of different apps index by app urls | -| profile.appsMeta | object | Information about user data of different apps. Property names are the domain name of the app. Each property value is an object of containing properties for `storage` and `publicKey`. See "App Meta Data". | -| username | string | BNS username, owned by the first public key of `public_keys` claim. Can be empty string | -| profile_url | string | Resolvable url of the user's profile. | -| core_token | string? | | -| email | string? | User's email address. Can be null. | -| hub_url | string | User's storage hub url for the current app. | -| blockstackAPIUrl | string? | Deprecated. Url to the user's preferred authenticator | -| associationToken | string | Signed JWT to access gaia storage bucket of user's app data. | -| version | string | Version of this schema, must be "1.3.1" - -### Public key and BNS Username - -If the Stacks address representing the public key owns a BNS username, it is returned as part of the response. Other users can use the username to lookup metadata of other applications via the zonefile and the profile linked in the zonefile. The profile is signed with the private key belonging to the public key. - -### App key derivation - -### Profile - -### App Meta Data - | +| Claim name | Type | Description | +| ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| jti | string | As defined in RFC7519 | +| iat | string | As defined in RFC7519 | +| exp | string | As defined in RFC7519 | +| iss | string | Decentralized identifier defined in DID specification representing the user's account. | +| private_key | string | Encrypted app private key for the provided domain. The key is encrypted with the public key of the app transit key. | +| public_keys | array | Single item array containing the public key of the selected account in hex representation. | +| profile | object | Object containing properties of the users, the object schema should be well-known type of Appendix B. This can be the public profile of the selected account. | +| profile.stxAddress | object | Object containing the user's stx address for mainnet and testnet in the form: `{mainnet: "S...", testnet: "S..."}` | +| profile.apps | object | Deprecated; use appsMeta. Storage endpoints for user data of different apps index by app urls | +| profile.appsMeta | object | Information about user data of different apps. Property names are the domain name of the app. Each property value is an object of containing properties for `storage` and `publicKey`. See "Application Meta Data". | +| username | string | BNS username, owned by the first public key of `public_keys` claim. Can be the empty string | +| profile_url | string | Resolvable url of the public profile of the selected account. | +| core_token | string? | Usually not used. Encrypted token to access a stacks node. The public key of the app transit key must be used for encryption. | +| email | string? | User's email address. Can be null. | +| hub_url | string | User's storage hub url for the current app. | +| blockstackAPIUrl | string? | Deprecated. Url to the user's preferred authenticator | +| associationToken | string | Signed JWT to access gaia storage of a private gaia hub. | +| version | string | Version of this schema, must be "2.0.0" | ## Transport Protocol -The communication between application and authenticator can happen in various ways. It is defined by the transport protocol. +The communication between application and authenticator can happen in various ways. The subsections below define common transport protocols. ### Stacks Provider -Stacks Provider is a common interface used for web applications to communicate with the authenticator. +Stacks Provider is a common interface used for web applications to communicate with the authenticator via a browser extension. It provides functions to handle @@ -143,22 +217,43 @@ It provides functions to handle https://github.com/hirosystems/connect/blob/main/packages/connect/src/types/provider.ts -### Deep Links +The function `authenticationRequest` expects the JWT of the authentication request as parameter and must return the authentication response as encoded JWT. + +This transport protocol is implemented by the [Hiro Wallet web extension](https://github.com/blockstack/stacks-wallet-web/). + +### HTTPS -Wise app uses deep links to handle request on mobile devices +Authentication requests can be sent via HTTPS to a hosted authenticator. The encoded JWT of the request must be set as query parameter `authRequest` when calling the url of the authenticator. + +The authentication request must contain a redirect url. The authenticator must open this url with the authentication response as encoded JWT in the query parameter `authResponse`. + +This transport protocol is implemented by the Blockstack Browser and the Stacks cli. + +### App Links + +On mobile devices, applications can use app links/deep links to send authentication requests and receive the response. They must use the same query parameters for the authentication requests and responses as the HTTPS protocol, i.e. `authRequest` and `authResponse`. + +This transport protocol is implemented by the following authenticator apps: + +- [Wise app](https://github.com/PravicaInc/wise-js) and +- [Circles app](https://github.com/blocoio/stacks-circles-app). ### Android Accounts -Android provides an open account management system. +Android provides an open account management system. An authenticator can make use of it and provide an account service that application can use to authenticate and to access content providers of the user. + +The communication happens via Android Intents. The used data uris must use the query parameters `authRequest` and `authResponse`. -Example implementation: https://github.com/openintents/calendar-sync/blob/master/app/src/main/java/org/openintents/calendar/common/accounts/GenericAccountService.kt +Proof of concept implementation in [OI Calendar](https://github.com/openintents/calendar-sync/blob/master/app/src/main/java/org/openintents/calendar/common/accounts/GenericAccountService.kt). # Out of Scope -This SIP does not specify other flows between applications and authenticators like transaction signing or message encryption. +This SIP does not specify other communication between application and authenticator like transaction signing or message encryption. # Backwards Compatibility +The specification contains parts that are deprecated like the property `apps` in the public profile. These parts are for information only and are not normative. Versions of the authentication requests and responses older than 1.3.1 are considered deprecated and not covered by this SIP. + # Related Work ## Unstoppabledomains auth @@ -169,6 +264,10 @@ https://unstoppabledomains.com/blog/login-with-unstoppable https://medium.com/@sethisaab/what-is-did-auth-and-how-does-it-works-1e4884383a53 +## User collections + +Collections are data items with well-defined schema, for example a collection of contacts (address book). Application can request access to these collection, the scope is defined as `collection._collection type_`. The Response will contain details about how to lookup collections. The collection types for scope `collection.contact` was defined in [blockstack-collections](https://github.com/blockstack/blockstack-collections). + # Implementations ## Libraries @@ -179,38 +278,23 @@ https://github.com/fungible-systems/micro-stacks https://github.com/PravicaInc/wise-js -## Authenticators - -### Hiro Wallet - -Hiro Wallet is a browser extension that handles authentication and transaction signing. - -It uses a 24 mnemonic called SecretKey to derive private keys for different user accounts. - -Each account owns one private key to handle stx tokens (wallet key) and one private key to access storage (data key). - -The wallet key can own a BNS username. - -https://github.com/blockstack/stacks-wallet-web - -### Wise - -https://github.com/PravicaInc/Wise - -https://wiseapp.id - -### Circles - -https://github.com/blocoio/stacks-circles-app - # Activation -This SIP is activated if .. +This SIP is activated if 3 authenticators support version 2.0.0 of the authentication requests and responses. # Appendix A -Transport protocols +Scopes in authentication requests -``` +| Scope identifier | Description | +| ---------------- | ----------------------------------------------------------- | +| store_write | Response must contain the app private key | +| email | Response may contain selected email by the user | +| publish_data | Public profile must contain app information for data lookup | -``` +# Appendix B + +Well-known JSON schemas used for owner data in `claim` of public profile + +| Canonical Url | Comment | +| https://schema.org/Person | Used for owners that are persons. Data shall contain values for `name` and `description`. Profile pictures must be named `avatar` in property `image.name` if provided as `ImageObject`.| From fcfdd544d7a84b18efb5d03a3566689f535faa23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Fri, 7 Jan 2022 02:32:04 +0100 Subject: [PATCH 10/15] fix format, add related work --- sips/sip-x/sip-x-authentication-protocol.md | 83 ++++++++++----------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index d46fe321..8b722db1 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -65,21 +65,20 @@ The authentication request is a JWT created by the application. It is signed by The payload must contain the following claims: -| Claim name | Type | Description | -| ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------- | -| jti | string | As defined in RFC7519 | -| iat | string | As defined in RFC7519 | -| exp | string | As defined in RFC7519 | -| iss | string | Decentralized identifier defined in DID specification representing the user's account. | -| | -| public_keys | array | Single item list with the public key of the signer | -| domain_name | string | The url of the application with schema. | -| manifest_uri | string | The url of the application manifest, usually domain_name + "/manifest.json" | -| redirect_uri | string | The url that should receive the authentication response | -| do_not_include_profile | bool | | -| supports_hub_url | bool | | +| Claim name | Type | Description | +| ---------------------- | ------ | ------------------------------------------------------------------------------------------------------------- | +| jti | string | As defined in RFC7519 | +| iat | string | As defined in RFC7519 | +| exp | string | As defined in RFC7519 | +| iss | string | Decentralized identifier defined in DID specification representing the user's account. | +| public_keys | array | Single item list with the public key of the signer | +| domain_name | string | The url of the application with schema. | +| manifest_uri | string | The url of the application manifest, usually domain_name + "/manifest.json" | +| redirect_uri | string | The url that should receive the authentication response | +| do_not_include_profile | bool | | +| supports_hub_url | bool | | | scopes | array | list of strings specifying the requested access to the user's account. See Appendix A for full list of scopes | -| version | string | must be "2.0.0" | +| version | string | must be "2.0.0" | ## User authorization @@ -119,14 +118,14 @@ The JWT must be signed by the private key of the stacks address that ownes the u The JWT payload must have the following claims: -| claim | description | -| ------- | -------------------------------------------------------------------------------------------------------------- | -| jti | as defined by RFC 7519 | -| iat | as defined by RFC 7519 | -| exp | as defined by RFC 7519 | -| subject | a json object with property `publicKey` containing the hex representation of the public key of the signing key | -| issuer | same as subject | -| claim | a json object containing data of the username owner mixed with meta data of applications used by the owner | +| Claim | Type | Description | +| ------- | ------ | -------------------------------------------------------------------------------------------------------------- | +| jti | string | as defined by RFC 7519 | +| iat | string | as defined by RFC 7519 | +| exp | string | as defined by RFC 7519 | +| subject | object | a json object with property `publicKey` containing the hex representation of the public key of the signing key | +| issuer | object | same as subject | +| claim | object | a json object containing data of the username owner mixed with meta data of applications used by the owner | #### Owner Data @@ -202,7 +201,7 @@ The payload must contain the following claims: | associationToken | string | Signed JWT to access gaia storage of a private gaia hub. | | version | string | Version of this schema, must be "2.0.0" | -## Transport Protocol +## Transport Protocols The communication between application and authenticator can happen in various ways. The subsections below define common transport protocols. @@ -219,7 +218,7 @@ https://github.com/hirosystems/connect/blob/main/packages/connect/src/types/prov The function `authenticationRequest` expects the JWT of the authentication request as parameter and must return the authentication response as encoded JWT. -This transport protocol is implemented by the [Hiro Wallet web extension](https://github.com/blockstack/stacks-wallet-web/). +This transport protocol is implemented by the [Hiro Wallet web extension](https://github.com/blockstack/stacks-wallet-web/). Examples for client libraries are [Connect](https://github.com/blockstack/connect) and [Micro Stacks](https://github.com/fungible-systems/micro-stacks). ### HTTPS @@ -235,8 +234,8 @@ On mobile devices, applications can use app links/deep links to send authenticat This transport protocol is implemented by the following authenticator apps: -- [Wise app](https://github.com/PravicaInc/wise-js) and -- [Circles app](https://github.com/blocoio/stacks-circles-app). +- [Wise app](https://github.com/PravicaInc/wise-js) and client library[wise-js](https://github.com/PravicaInc/wise-js) +- [Circles app](https://github.com/blocoio/stacks-circles-app) for Android. ### Android Accounts @@ -246,37 +245,37 @@ The communication happens via Android Intents. The used data uris must use the q Proof of concept implementation in [OI Calendar](https://github.com/openintents/calendar-sync/blob/master/app/src/main/java/org/openintents/calendar/common/accounts/GenericAccountService.kt). -# Out of Scope +## Client Libraries -This SIP does not specify other communication between application and authenticator like transaction signing or message encryption. +https://github.com/PravicaInc/wise-js -# Backwards Compatibility +# Out of Scope -The specification contains parts that are deprecated like the property `apps` in the public profile. These parts are for information only and are not normative. Versions of the authentication requests and responses older than 1.3.1 are considered deprecated and not covered by this SIP. +This SIP does not specify other communication between application and authenticator like transaction signing or message encryption. -# Related Work +## User collections -## Unstoppabledomains auth +Collections are data items with well-defined schema, for example a collection of contacts (address book). Application can request access to these collection, the scope is defined as `collection._collection type_`. The Response will contain details about how to lookup collections. The collection type for scope `collection.contact` is defined in [blockstack-collections](https://github.com/blockstack/blockstack-collections). -https://unstoppabledomains.com/blog/login-with-unstoppable +Specification of user collections is out of scope of this SIP. -## DID auth +# Backwards Compatibility -https://medium.com/@sethisaab/what-is-did-auth-and-how-does-it-works-1e4884383a53 +The specification contains parts that are deprecated like the property `apps` in the public profile. These parts are for information only and are not normative. Versions of the authentication requests and responses older than 1.3.1 are considered deprecated and not covered by this SIP. -## User collections +# Related Work -Collections are data items with well-defined schema, for example a collection of contacts (address book). Application can request access to these collection, the scope is defined as `collection._collection type_`. The Response will contain details about how to lookup collections. The collection types for scope `collection.contact` was defined in [blockstack-collections](https://github.com/blockstack/blockstack-collections). +## Unstoppable Login -# Implementations +Unstoppable are domain names registered on Polygon blockchain. The login is similar to the HTTPS transport protocol. When a user visits an app and logs in with their domain, the app reads the domain and directs the user to the authorization server saved to that domain name. -## Libraries +It differs in the way how the user authorizes access to private information. The user authenticates and grants access to the information requested by signing a transaction with the key that owns their domain. The app receives an access token and an id token from the authorization server with the user’s contact information (e.g., email address). -https://github.com/blockstack/connect +See the [blog post by unstoppabledomains](https://unstoppabledomains.com/blog/login-with-unstoppable) -https://github.com/fungible-systems/micro-stacks +## DID auth -https://github.com/PravicaInc/wise-js +The generalized form the authentication flow is a cryptographic challenge where users and applications use [DIDs](https://www.w3.org/TR/did-core/) and where the details about the cryptography have to be looked up via a DID resolver. See for example [this article](https://medium.com/@sethisaab/what-is-did-auth-and-how-does-it-works-1e4884383a53). # Activation From 1312b4be70a8502a5517a384d34bf03eace97ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Mon, 10 Jan 2022 15:16:45 +0100 Subject: [PATCH 11/15] add jwt verifcation, add did appendix --- sips/sip-x/sip-x-authentication-protocol.md | 76 +++++++++++++++++---- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index 8b722db1..09b09e13 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -61,24 +61,38 @@ The payloads for the authentication request and the response are specified in th ## Authentication Request -The authentication request is a JWT created by the application. It is signed by a private key that is usually freshly generated. The key is called app transit key. The payload schema is defined as follows: +The authentication request is a JWT created by the application. It is signed by a private key that must be freshly generated. The key is called app transit key. + +### Signed JWT The payload must contain the following claims: -| Claim name | Type | Description | -| ---------------------- | ------ | ------------------------------------------------------------------------------------------------------------- | -| jti | string | As defined in RFC7519 | -| iat | string | As defined in RFC7519 | -| exp | string | As defined in RFC7519 | -| iss | string | Decentralized identifier defined in DID specification representing the user's account. | -| public_keys | array | Single item list with the public key of the signer | -| domain_name | string | The url of the application with schema. | -| manifest_uri | string | The url of the application manifest, usually domain_name + "/manifest.json" | -| redirect_uri | string | The url that should receive the authentication response | -| do_not_include_profile | bool | | -| supports_hub_url | bool | | -| scopes | array | list of strings specifying the requested access to the user's account. See Appendix A for full list of scopes | -| version | string | must be "2.0.0" | +| Claim name | Type | Description | +| ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- | +| jti | string | As defined in RFC7519 | +| iat | string | As defined in RFC7519 | +| exp | string | As defined in RFC7519 | +| iss | string | Decentralized identifier defined in DID specification representing the user's account. See Appendix C for list of well-known DID methods. | +| public_keys | array | Single item list with the public key of the signer | +| domain_name | string | The url of the application with schema. | +| manifest_uri | string | The url of the application manifest, usually domain_name + "/manifest.json" | +| redirect_uri | string | The url that should receive the authentication response | +| do_not_include_profile | bool | | +| supports_hub_url | bool | | +| scopes | array | list of strings specifying the requested access to the user's account. See Appendix A for full list of scopes | +| version | string | must be "2.0.0" | + +### Verification + +Authenticators should verify that the request has the following properties: + +- expiration date (`exp`) is not in the past +- issuance date (`iat`) is in the past +- public keys length is 1 +- public key (`public_keys[0]`) is same as the signer's key +- public key's stacks address is the same as the issuer +- manifest url is same origin as the app domain +- redirect url is same origin as the app domain ## User authorization @@ -174,6 +188,14 @@ If the application requested to share data publicly through the scope `publish_d } ``` +### Verification + +Public profiles owned by users with a username can be looked up via the Stacks blockchain. The retrieved profile token was registered by the user. It must be verified that the token has the following properties: + +- issuer's public key (`issuer.publicKey`) is the same as the signer's key. +- subject's public key (`subject.publicKey`) exists. +- profile (`claim`) exists. + ## Authentication Response The authentication response is a signed JWT that contains the requested and authorized data. The token is signed with the public key of the request signature, i.e. the app transit key. @@ -201,6 +223,22 @@ The payload must contain the following claims: | associationToken | string | Signed JWT to access gaia storage of a private gaia hub. | | version | string | Version of this schema, must be "2.0.0" | +### Verification + +When the application received the authentication response it must verify that the token has the following properties: + +- expiration date (`exp`) is not in the past +- issuance date (`iat`) is in the past +- public keys length is 1 +- public key (`public_keys[0]`) is same as the signer's key +- public key's stacks address is the same as the issuer +- username if provided is owned by issuer + +#### Usernames and DIDs + +If the authentication response contains a username the username must be owned by the issuer. +The issuer of a JWT tokens is represented by a DID in claim `iss`. The DID has to be resolved to a public key and then the blockchain has to confirm that the username indeed is owned by the public key encoded as Stacks address. + ## Transport Protocols The communication between application and authenticator can happen in various ways. The subsections below define common transport protocols. @@ -297,3 +335,11 @@ Well-known JSON schemas used for owner data in `claim` of public profile | Canonical Url | Comment | | https://schema.org/Person | Used for owners that are persons. Data shall contain values for `name` and `description`. Profile pictures must be named `avatar` in property `image.name` if provided as `ImageObject`.| + +# Appendix C + +Well-known DID methods + +| DID method | Comment | +| did:btc | public keys are encoded in the DID directly using b58 encoding.| +| did:stacks:v2 | public keys are derived from the transaction of username registration, update or import. | From 93ee6579158633c657659814c02f54869a7a7193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Tue, 11 Jan 2022 11:31:04 +0100 Subject: [PATCH 12/15] add comparison of json objects, remove camelcase properties in root --- sips/sip-x/sip-x-authentication-protocol.md | 22 ++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index 09b09e13..5560d7e6 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -20,7 +20,7 @@ Sign-off: # Abstract -Decentralized application often require the authentication of their users. This SIP specifies a protocol between the application and an authenticator that results in a public key controlled by the user and a private key specific for the application for the user. +Decentralized application often require the authentication of their users. This SIP specifies a protocol between the application and an authenticator that results in the exchange of a public key controlled by the user and a private key specific for the application for the user. # License and Copyright @@ -33,7 +33,7 @@ Decentralized application do not want to store credentials of their users. Inste The private key for that public key is guarded and managed by a so-called authenticator. When a users visits the app, the app needs to communicate with the authenticator. The authenticator helps the user to choose a public key that should be shared with the application. -In addition to the public key, more information can be shared like email address or profile pictures. Some data can be shared publicly, other only with the application. In particular, a private key is derived by the authenticator that is specific to the application and to the user. This private key can be used by the application to access for example decentralized storage or sign messages in the name of the user of the application. +In addition to the public key, more information can be shared like email address or profile pictures. Some data can be shared publicly, other only with the application. In particular, a private key is derived by the authenticator that is specific to the application and to the user. This private key can be used by the application for example to access decentralized storage detailed in the response or sign messages in the name of the user of the application. # Specification @@ -218,9 +218,8 @@ The payload must contain the following claims: | profile_url | string | Resolvable url of the public profile of the selected account. | | core_token | string? | Usually not used. Encrypted token to access a stacks node. The public key of the app transit key must be used for encryption. | | email | string? | User's email address. Can be null. | -| hub_url | string | User's storage hub url for the current app. | -| blockstackAPIUrl | string? | Deprecated. Url to the user's preferred authenticator | -| associationToken | string | Signed JWT to access gaia storage of a private gaia hub. | +| hub_url | string | User's storage hub url for the current app accessible with the app private key. | +| association_token | string | Signed JWT to access gaia storage of a private gaia hub. | | version | string | Version of this schema, must be "2.0.0" | ### Verification @@ -239,6 +238,19 @@ When the application received the authentication response it must verify that th If the authentication response contains a username the username must be owned by the issuer. The issuer of a JWT tokens is represented by a DID in claim `iss`. The DID has to be resolved to a public key and then the blockchain has to confirm that the username indeed is owned by the public key encoded as Stacks address. +## Comparison of used JSON objects + +Three JSON object are specified in this document: Authentication Request, Authentication Response, Public Profile. + +| Property | Authentication Request | Authentication Response | Public Profile | +| -------- | ---------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------ | +| Format | JWT | JWT | JSON document with property `token` with a JWT as value and property `decodedToken` with the decoded JWT as value. | +| Issuer | `iss`: app transit key | `iss`: data key | `issuer`: wallet key | + +The Authentication Request and Authentication Response are used for communication between authentication and application only and are called auth messages. + +The Public Profile can be used a [DID Document](https://www.w3.org/TR/did-core/) or a self-signed [Verifiable Credential](https://www.w3.org/TR/vc-data-model/). + ## Transport Protocols The communication between application and authenticator can happen in various ways. The subsections below define common transport protocols. From 7b35de622fceae1d7d31634985cfcc5ee5115f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Thu, 20 Jan 2022 15:58:26 +0100 Subject: [PATCH 13/15] remove transport protocols, use VCs for public profile --- sips/sip-x/sip-x-authentication-protocol.md | 228 ++++++++++++-------- 1 file changed, 134 insertions(+), 94 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index 5560d7e6..c7f31b86 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -80,6 +80,7 @@ The payload must contain the following claims: | do_not_include_profile | bool | | | supports_hub_url | bool | | | scopes | array | list of strings specifying the requested access to the user's account. See Appendix A for full list of scopes | +| state | any | value to be echoed in the auth response | | version | string | must be "2.0.0" | ### Verification @@ -116,7 +117,9 @@ If the authentication request contains the scope `storage_write`, then the authe ## Public Profile -Users who own a BNS username can publish a public profile with information about the account that owns the BNS username. The url of the publicly accessible profile is provided in the zone file of the BNS username. The process of attaching a zone file to a BNS username is part of name registration via the BNS contract. +Users can create a public profile that is shared with the application or other users. It contains information similar to a profile of social media. The profile is a self-signed document that can be shared and verified off-chain. + +Users who own a BNS username can publish their public profile under their BNS username. The url of the publicly accessible profile is provided in the zone file of the BNS username. The process of attaching a zone file to a BNS username is part of name registration via the BNS contract. The public profile is used during authentication when the authentication request contains the scope `publish_data`. The profile then contains public meta data about the application that other users can use to find data shared with them. @@ -126,28 +129,25 @@ It is recommended to use the [gaia protocol](https://github.com/blockstack/gaia) The profile must be stored as a JSON array containing a single JSON object with properties `token` and `decodedToken`. The values are a signed JWT token and its decoded representation. -### Signed JWT +### Data Model -The JWT must be signed by the private key of the stacks address that ownes the username of the select account. This should be the Stacks private key using the derivation path `m/44'/5757'/0'/0/n`. Some users might have used the data private key to register a username, therefore, authenticators must verify whether the username is owned by the signing private key at the time of signing. +The public profile is represented as a [verifiable credential](https://www.w3.org/TR/vc-data-model) using the new type `PublicProfileCredential`. -The JWT payload must have the following claims: +The public profile credential must have the following properties: -| Claim | Type | Description | -| ------- | ------ | -------------------------------------------------------------------------------------------------------------- | -| jti | string | as defined by RFC 7519 | -| iat | string | as defined by RFC 7519 | -| exp | string | as defined by RFC 7519 | -| subject | object | a json object with property `publicKey` containing the hex representation of the public key of the signing key | -| issuer | object | same as subject | -| claim | object | a json object containing data of the username owner mixed with meta data of applications used by the owner | +| Property | Type | Description | +| -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------- | +| profile | object | a json object of the public profile. Common profiles types are `Person`, `Organisation`, `Software` as defined on schema.org. | +| appsMeta | object | public meta data of used apps, see below. | +| api | object | information about apis like gaia storage, to be used by applications for the user. | -#### Owner Data +#### Profile -Personal data must not be published by the authenticator without consent of the user. If published, the authenticator must provide a method to remove this data as well. +The profile describes the user. Personal data must not be published by the authenticator without consent of the user. If published, the authenticator must provide a method to remove this data as well. Examples of personal data are name and profile picture. -The owner data shall use a well-known schema. See Appendix B for recommended schemas. +The profile shall use a well-known schema. See Appendix B for recommended schemas. #### Application Meta Data @@ -188,13 +188,81 @@ If the application requested to share data publicly through the scope `publish_d } ``` -### Verification +#### APIs + +User might want to share API endpoints and configurations with applications and other users. The following properties are supported: + +| Property | Type | Description | +| ------------- | ------ | --------------------------------------------------------- | +| gaiaHubConfig | object | config for the user's gaia hub, with property `urlPrefix` | +| gaiaHubUrl | string | The write url of the hub | + +### Proof Format + +The verifiable credential must be encoded as a signed JWT. + +The JWT must be signed by the private key of the stacks address that ownes the username of the select account. This should be the Stacks private key using the derivation path `m/44'/5757'/0'/0/n`. Some users might have used the data private key to register a username, therefore, authenticators must verify whether the username is owned by the signing private key at the time of signing. + +The JWT payload must have the following claims: -Public profiles owned by users with a username can be looked up via the Stacks blockchain. The retrieved profile token was registered by the user. It must be verified that the token has the following properties: +| Claim | Type | Description | +| ----- | ------ | -------------------------------------------------- | +| jti | string | as defined by RFC 7519 | +| iat | string | as defined by RFC 7519 | +| exp | string | as defined by RFC 7519 | +| sub | string | the user | +| iss | string | the user | +| vc | object | a json object containing the verifiable credential | -- issuer's public key (`issuer.publicKey`) is the same as the signer's key. -- subject's public key (`subject.publicKey`) exists. -- profile (`claim`) exists. +### Example + +```json +{ + "jti": "https://gaia.blockstack.org/hub/1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY/profile.json", + "iat": "2021-10-15T21:18:18.984Z", + "exp": "2022-10-15T21:18:18.984Z", + "sub": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH", + "iss": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH", + "vc": { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.stacks.org/2022/credentials/public-profile/v1" + ], + "type": ["VerifiableCredential", "PublicProfileCredential"], + "credentialSubject": { + "profile": { + "@type": "Person", + "@context": "http://schema.org", + "name": "Anon", + "description": "Stacks user", + "image": [ + { + "@type": "ImageObject", + "name": "avatar", + "contentUrl": "https://gaia.blockstack.org/hub/1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE/avatar" + } + ] + }, + "api": { + "gaiaHubConfig": { + "url_prefix": "https://gaia.blockstack.org/hub/" + }, + "gaiaHubUrl": "https://hub.blockstack.org" + }, + "appsMeta": { + "https://app.sigle.io": { + "storage": "https://gaia.blockstack.org/hub/13bzweCrgqiTr9BjzaEq8uRU7F7TisxLDc/", + "publicKey": "0352a6b06db78dda5581a778f59fe45c5b3afe7f0e854644cdff6d9c841d3305cd" + } + } + } + } +} +``` + +### Verification + +Public profiles owned by users with a username can be looked up via the Stacks blockchain. The retrieved verifiable credential was registered by the user. The usual verification for VCs must be applied. ## Authentication Response @@ -202,25 +270,25 @@ The authentication response is a signed JWT that contains the requested and auth The payload must contain the following claims: -| Claim name | Type | Description | -| ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| jti | string | As defined in RFC7519 | -| iat | string | As defined in RFC7519 | -| exp | string | As defined in RFC7519 | -| iss | string | Decentralized identifier defined in DID specification representing the user's account. | -| private_key | string | Encrypted app private key for the provided domain. The key is encrypted with the public key of the app transit key. | -| public_keys | array | Single item array containing the public key of the selected account in hex representation. | -| profile | object | Object containing properties of the users, the object schema should be well-known type of Appendix B. This can be the public profile of the selected account. | -| profile.stxAddress | object | Object containing the user's stx address for mainnet and testnet in the form: `{mainnet: "S...", testnet: "S..."}` | -| profile.apps | object | Deprecated; use appsMeta. Storage endpoints for user data of different apps index by app urls | -| profile.appsMeta | object | Information about user data of different apps. Property names are the domain name of the app. Each property value is an object of containing properties for `storage` and `publicKey`. See "Application Meta Data". | -| username | string | BNS username, owned by the first public key of `public_keys` claim. Can be the empty string | -| profile_url | string | Resolvable url of the public profile of the selected account. | -| core_token | string? | Usually not used. Encrypted token to access a stacks node. The public key of the app transit key must be used for encryption. | -| email | string? | User's email address. Can be null. | -| hub_url | string | User's storage hub url for the current app accessible with the app private key. | -| association_token | string | Signed JWT to access gaia storage of a private gaia hub. | -| version | string | Version of this schema, must be "2.0.0" | +| Claim name | Type | Description | +| ----------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| jti | string | As defined in RFC7519 | +| iat | string | As defined in RFC7519 | +| exp | string | As defined in RFC7519 | +| iss | string | Decentralized identifier defined in DID specification representing the user's account. | +| private_key | string | Encrypted app private key for the provided domain. The key is encrypted with the public key of the app transit key. | +| public_keys | array | Single item array containing the public key of the selected account in hex representation. | +| profile | object | Object containing properties of the users, the object schema should be well-known type of Appendix B. This can be the public profile of the selected account. | +| apps_meta | object | Information about user data of different apps. Property names are the domain name of the app. Each property value is an object of containing properties for `storage` and `publicKey`. See "Application Meta Data". | +| username | string | BNS username, owned by the first public key of `public_keys` claim. Can be the empty string | +| stx_address | object | Object containing the user's stx address for mainnet and testnet in the form: `{mainnet: "S...", testnet: "S..."} | +| profile_url | string | Resolvable url of the public profile of the selected account. | +| core_token | string? | Usually not used. Encrypted token to access a stacks node. The public key of the app transit key must be used for encryption. | +| email | string? | User's email address. Can be null. | +| hub_url | string | User's storage hub url for the current app accessible with the app private key. | +| association_token | string | Signed JWT to access gaia storage of a private gaia hub. | +| state | any | value echoed from the auth request | +| version | string | Version of this schema, must be "2.0.0" | ### Verification @@ -242,68 +310,26 @@ The issuer of a JWT tokens is represented by a DID in claim `iss`. The DID has t Three JSON object are specified in this document: Authentication Request, Authentication Response, Public Profile. -| Property | Authentication Request | Authentication Response | Public Profile | -| -------- | ---------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------ | -| Format | JWT | JWT | JSON document with property `token` with a JWT as value and property `decodedToken` with the decoded JWT as value. | -| Issuer | `iss`: app transit key | `iss`: data key | `issuer`: wallet key | +| Property | Authentication Request | Authentication Response | Public Profile | +| -------- | ---------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------ | +| Format | JWT | JWT | JSON document with property `token` with a JWT as value and property `decodedToken` with the decoded JWT as value. | +| Issuer | `iss`: app transit key | `iss`: wallet key | `iss`: wallet key | The Authentication Request and Authentication Response are used for communication between authentication and application only and are called auth messages. -The Public Profile can be used a [DID Document](https://www.w3.org/TR/did-core/) or a self-signed [Verifiable Credential](https://www.w3.org/TR/vc-data-model/). - -## Transport Protocols - -The communication between application and authenticator can happen in various ways. The subsections below define common transport protocols. +The Public Profile is a self-signed [Verifiable Credential](https://www.w3.org/TR/vc-data-model/). -### Stacks Provider - -Stacks Provider is a common interface used for web applications to communicate with the authenticator via a browser extension. - -It provides functions to handle - -1. authentication -2. transaction signing - -https://github.com/hirosystems/connect/blob/main/packages/connect/src/types/provider.ts - -The function `authenticationRequest` expects the JWT of the authentication request as parameter and must return the authentication response as encoded JWT. - -This transport protocol is implemented by the [Hiro Wallet web extension](https://github.com/blockstack/stacks-wallet-web/). Examples for client libraries are [Connect](https://github.com/blockstack/connect) and [Micro Stacks](https://github.com/fungible-systems/micro-stacks). - -### HTTPS - -Authentication requests can be sent via HTTPS to a hosted authenticator. The encoded JWT of the request must be set as query parameter `authRequest` when calling the url of the authenticator. - -The authentication request must contain a redirect url. The authenticator must open this url with the authentication response as encoded JWT in the query parameter `authResponse`. - -This transport protocol is implemented by the Blockstack Browser and the Stacks cli. - -### App Links - -On mobile devices, applications can use app links/deep links to send authentication requests and receive the response. They must use the same query parameters for the authentication requests and responses as the HTTPS protocol, i.e. `authRequest` and `authResponse`. - -This transport protocol is implemented by the following authenticator apps: - -- [Wise app](https://github.com/PravicaInc/wise-js) and client library[wise-js](https://github.com/PravicaInc/wise-js) -- [Circles app](https://github.com/blocoio/stacks-circles-app) for Android. - -### Android Accounts - -Android provides an open account management system. An authenticator can make use of it and provide an account service that application can use to authenticate and to access content providers of the user. - -The communication happens via Android Intents. The used data uris must use the query parameters `authRequest` and `authResponse`. - -Proof of concept implementation in [OI Calendar](https://github.com/openintents/calendar-sync/blob/master/app/src/main/java/org/openintents/calendar/common/accounts/GenericAccountService.kt). +# Out of Scope -## Client Libraries +## More Message Types -https://github.com/PravicaInc/wise-js +This SIP does not specify other communication between application and authenticator like transaction signing or message encryption. -# Out of Scope +## Transport Protocols -This SIP does not specify other communication between application and authenticator like transaction signing or message encryption. +This SIP does not specify the transport portocol of the messages, how the messages are exchanged. Furthermore, the SIP does not specify the way how application and authenticator find an agreement on the transport protocol. -## User collections +## User Collections Collections are data items with well-defined schema, for example a collection of contacts (address book). Application can request access to these collection, the scope is defined as `collection._collection type_`. The Response will contain details about how to lookup collections. The collection type for scope `collection.contact` is defined in [blockstack-collections](https://github.com/blockstack/blockstack-collections). @@ -313,6 +339,20 @@ Specification of user collections is out of scope of this SIP. The specification contains parts that are deprecated like the property `apps` in the public profile. These parts are for information only and are not normative. Versions of the authentication requests and responses older than 1.3.1 are considered deprecated and not covered by this SIP. +## Upgrade from 1.3.1 to 2.0.0 + +The following changes from version 1.3.1 to 2.0.0 require updates of the existing wallets + +- The public profile is a verifiable credential and must be signed by the owner of the username of the selected account. +- The authentication response must be signed by the same key as the public profile. +- The issuer of a JWT should be given as DID using the DID method `did:stacks:v2`. +- The following properties of the authentication response have been renamed: + - hubUrl -> `hub_url` + - associationToken -> `association_token` + - profile.stxAddress -> `stx_address` +- The following property of the authentication request and response has been added: + - `state` + # Related Work ## Unstoppable Login @@ -353,5 +393,5 @@ Well-known JSON schemas used for owner data in `claim` of public profile Well-known DID methods | DID method | Comment | -| did:btc | public keys are encoded in the DID directly using b58 encoding.| -| did:stacks:v2 | public keys are derived from the transaction of username registration, update or import. | +| did:pkh:btc | User's stacks address in base58 encoding| +| did:stacks:v2 | Public keys are derived from the transaction of username registration, update or import. Only for users with usernames. | From e24a9fb61ab3087290c8e83c4449ef6aa73f6c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Tue, 17 May 2022 11:49:08 +0200 Subject: [PATCH 14/15] require bip32, not bip39 --- sips/sip-x/sip-x-authentication-protocol.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index c7f31b86..e320a8d2 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -72,7 +72,7 @@ The payload must contain the following claims: | jti | string | As defined in RFC7519 | | iat | string | As defined in RFC7519 | | exp | string | As defined in RFC7519 | -| iss | string | Decentralized identifier defined in DID specification representing the user's account. See Appendix C for list of well-known DID methods. | +| iss | string | Decentralized identifier defined in DID specification representing the app transit public key. See Appendix C for list of well-known DID methods. | | public_keys | array | Single item list with the public key of the signer | | domain_name | string | The url of the application with schema. | | manifest_uri | string | The url of the application manifest, usually domain_name + "/manifest.json" | @@ -97,7 +97,7 @@ Authenticators should verify that the request has the following properties: ## User authorization -The authenticator manages the user' private keys. The protocol requires that keys are created from a deterministic wallet using [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki). +The authenticator manages the user' private keys. The protocol requires that keys are created from a deterministic wallet using [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). The authenticator can offer the user a list of accounts. Each account corresponds to a change of the key derivation path by 1. This SIP does not specify how the wallet determines which accounts should be presented. Only requirement is that one account is selected. The selected index shall be called account index `n`. From 58aae536637ad9236365d0873f07d8d831b4add1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Tue, 21 Jun 2022 14:09:11 +0200 Subject: [PATCH 15/15] remove username from auth response, clarify use of Stacks Identity --- sips/sip-x/sip-x-authentication-protocol.md | 72 +++++++++++++-------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/sips/sip-x/sip-x-authentication-protocol.md b/sips/sip-x/sip-x-authentication-protocol.md index e320a8d2..69524451 100644 --- a/sips/sip-x/sip-x-authentication-protocol.md +++ b/sips/sip-x/sip-x-authentication-protocol.md @@ -67,21 +67,21 @@ The authentication request is a JWT created by the application. It is signed by The payload must contain the following claims: -| Claim name | Type | Description | -| ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- | -| jti | string | As defined in RFC7519 | -| iat | string | As defined in RFC7519 | -| exp | string | As defined in RFC7519 | +| Claim name | Type | Description | +| ---------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| jti | string | As defined in RFC7519 | +| iat | string | As defined in RFC7519 | +| exp | string | As defined in RFC7519 | | iss | string | Decentralized identifier defined in DID specification representing the app transit public key. See Appendix C for list of well-known DID methods. | -| public_keys | array | Single item list with the public key of the signer | -| domain_name | string | The url of the application with schema. | -| manifest_uri | string | The url of the application manifest, usually domain_name + "/manifest.json" | -| redirect_uri | string | The url that should receive the authentication response | -| do_not_include_profile | bool | | -| supports_hub_url | bool | | -| scopes | array | list of strings specifying the requested access to the user's account. See Appendix A for full list of scopes | -| state | any | value to be echoed in the auth response | -| version | string | must be "2.0.0" | +| public_keys | array | Single item list with the public key of the signer | +| domain_name | string | The url of the application with schema. | +| manifest_uri | string | The url of the application manifest, usually domain_name + "/manifest.json" | +| redirect_uri | string | The url that should receive the authentication response | +| do_not_include_profile | bool | | +| supports_hub_url | bool | | +| scopes | array | list of strings specifying the requested access to the user's account. See Appendix A for full list of scopes | +| state | any | value to be echoed in the auth response | +| version | string | must be "2.0.0" | ### Verification @@ -97,9 +97,23 @@ Authenticators should verify that the request has the following properties: ## User authorization -The authenticator manages the user' private keys. The protocol requires that keys are created from a deterministic wallet using [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). +The authenticator manages the user' private keys. The protocol requires that +keys are created from a deterministic wallet using +[BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) with a +seed from a secret key using [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki). -The authenticator can offer the user a list of accounts. Each account corresponds to a change of the key derivation path by 1. This SIP does not specify how the wallet determines which accounts should be presented. Only requirement is that one account is selected. The selected index shall be called account index `n`. +The authenticator can offer the user a list of accounts. Each account +corresponds to a change of the key derivation path by 1. This SIP does not specifies how +the wallet determines which accounts should be presented. Only requirement is +that one account is selected. The selected +index shall be called account index `n`. + +Wallets might display the following account details: + +| Description | Derivation path | Comment | +| --------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Stacks identity | `m/44'/5757'/0'/0/n` | Usually owns the BNS username and holds the accounts assets. The uncompressed public key is used to generate the accounts STX address (and a corresponding BTC address). | +| native Bitcoin | `m/44'/0'/n'` or `m/49'/0'/n'` | First unused BTC addresses related to these derivation paths could be shown. | Once the account index has been fixed, authenticator has to do the following operations: @@ -110,7 +124,8 @@ Once the account index has been fixed, authenticator has to do the following ope If the authentication request contains the scope `storage_write`, then the authenticator must create a private key that is specific for the requesting application. It must use the following algorithm: -1. Wallet salt: create the sha256 hash of the hex representation of the public key of derivation path (`m/888'/0'`) +1. Wallet salt: create the sha256 hash of the hex representation of the + compressed public key of derivation path (`m/888'/0'`) 1. Create sha256 hash of concatinated string of the `domain_name` from the request and the hex representation of the wallet salt. 1. Hash code: Create a hash code (as defined in Java and Javascript) from the hex representation of the hash, then apply bitwise `and` to the hash code and 0x7fffffff. 1. Use derivation path `m/888'/0'/n'/0'/_hash code_'` for the private key. @@ -119,7 +134,12 @@ If the authentication request contains the scope `storage_write`, then the authe Users can create a public profile that is shared with the application or other users. It contains information similar to a profile of social media. The profile is a self-signed document that can be shared and verified off-chain. -Users who own a BNS username can publish their public profile under their BNS username. The url of the publicly accessible profile is provided in the zone file of the BNS username. The process of attaching a zone file to a BNS username is part of name registration via the BNS contract. +Users who own a BNS username can publish their public profile under their BNS +username. The url of the publicly accessible profile is provided in the zone +file of the BNS username. The process of attaching a zone file to a BNS username +is part of name registration via the BNS contract. + +Users who do NOT own a BNS username can share the storage location of their public profile off-chain. The public profile is used during authentication when the authentication request contains the scope `publish_data`. The profile then contains public meta data about the application that other users can use to find data shared with them. @@ -201,7 +221,7 @@ User might want to share API endpoints and configurations with applications and The verifiable credential must be encoded as a signed JWT. -The JWT must be signed by the private key of the stacks address that ownes the username of the select account. This should be the Stacks private key using the derivation path `m/44'/5757'/0'/0/n`. Some users might have used the data private key to register a username, therefore, authenticators must verify whether the username is owned by the signing private key at the time of signing. +The signature must be created using the private key of the Stacks Identity of the selected account. The JWT payload must have the following claims: @@ -262,7 +282,9 @@ The JWT payload must have the following claims: ### Verification -Public profiles owned by users with a username can be looked up via the Stacks blockchain. The retrieved verifiable credential was registered by the user. The usual verification for VCs must be applied. +Public profiles owned by users with a username can be looked up via the Stacks +blockchain. Clients should verify that the retrieved verifiable credential was +issued by the user. The usual verification for VCs about expiry, etc. must be applied as well. ## Authentication Response @@ -280,7 +302,6 @@ The payload must contain the following claims: | public_keys | array | Single item array containing the public key of the selected account in hex representation. | | profile | object | Object containing properties of the users, the object schema should be well-known type of Appendix B. This can be the public profile of the selected account. | | apps_meta | object | Information about user data of different apps. Property names are the domain name of the app. Each property value is an object of containing properties for `storage` and `publicKey`. See "Application Meta Data". | -| username | string | BNS username, owned by the first public key of `public_keys` claim. Can be the empty string | | stx_address | object | Object containing the user's stx address for mainnet and testnet in the form: `{mainnet: "S...", testnet: "S..."} | | profile_url | string | Resolvable url of the public profile of the selected account. | | core_token | string? | Usually not used. Encrypted token to access a stacks node. The public key of the app transit key must be used for encryption. | @@ -299,12 +320,6 @@ When the application received the authentication response it must verify that th - public keys length is 1 - public key (`public_keys[0]`) is same as the signer's key - public key's stacks address is the same as the issuer -- username if provided is owned by issuer - -#### Usernames and DIDs - -If the authentication response contains a username the username must be owned by the issuer. -The issuer of a JWT tokens is represented by a DID in claim `iss`. The DID has to be resolved to a public key and then the blockchain has to confirm that the username indeed is owned by the public key encoded as Stacks address. ## Comparison of used JSON objects @@ -343,7 +358,8 @@ The specification contains parts that are deprecated like the property `apps` in The following changes from version 1.3.1 to 2.0.0 require updates of the existing wallets -- The public profile is a verifiable credential and must be signed by the owner of the username of the selected account. +- The public profile is a verifiable credential and must be signed by private + key of the Stacks Identity of the selected account. - The authentication response must be signed by the same key as the public profile. - The issuer of a JWT should be given as DID using the DID method `did:stacks:v2`. - The following properties of the authentication response have been renamed: