Skip to content

Commit

Permalink
Multi algorithm support JWT (#902)
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas MASSART <nicolas.massart@consensys.net>
  • Loading branch information
NicolasMassart authored Dec 14, 2021
1 parent 68dd16e commit 4b18774
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 45 deletions.
1 change: 1 addition & 0 deletions CI/vale/vale_styles/Vocab/Besu/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ JMeter
jnacl
Kafka
kalium
Keycloak
[kK]eystore(s)?
[kK]eytool(s)?
Kibana
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ besu --help

### Prerequisites

* [Java JDK](https://www.oracle.com/java/technologies/javase-downloads.html)
* [Java JDK](https://www.oracle.com/java/technologies/downloads/)

!!!attention

Expand Down
131 changes: 90 additions & 41 deletions docs/HowTo/Interact/APIs/Authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@ description: Hyperledger Besu authentication and authorization for JSON-RPC

Authentication identifies a user, and authorization verifies user access to requested JSON-RPC
methods. Hyperledger Besu verifies users using
[JSON Web Tokens (JWTs)](https://jwt.io/introduction/). JWTs are also used in
[JSON Web Tokens (JWT)](https://jwt.io/introduction/). JWT is also used in
[multi-tenancy](../../../Concepts/Privacy/Multi-Tenancy.md) to verify tenant data access.

Besu supports two mutually exclusive authentication methods:

* [Username and password](#username-and-password-authentication)
* [JWT public key](#jwt-public-key-authentication).

Besu creates JWTs internally with
Besu creates JWT internally with
[username and password authentication](#username-and-password-authentication), and externally with
[JWT public key authentication](#jwt-public-key-authentication).

Using JSON-RPC authentication and authorization with [MetaMask](https://metamask.io/) is not supported.
!!! note
Using JSON-RPC authentication and authorization with [MetaMask](https://metamask.io/) is not supported.

!!! important

To prevent interception of authentication credentials and authenticated tokens, make
authenticated requests over HTTPS. We recommended production deployments run behind a network
authenticated requests over HTTPS. We recommend running production deployments behind a network
layer that provides SSL termination. Besu does not provide a HTTPS connection natively.

## Username and password authentication
Expand All @@ -38,7 +38,7 @@ Using [public key authentication](#jwt-public-key-authentication) disables the `

The `toml` credentials file defines user details and the JSON-RPC methods they can access.

!!! example "Sample credentials file"
!!! example "Sample `auth.toml` credentials file"

```toml
[Users.username1]
Expand All @@ -65,9 +65,17 @@ Each user requiring JSON-RPC access the configuration file lists the:

!!! example "Password hash subcommand"

```bash
besu password hash --password=pegasys
```
=== "Command"

```bash
besu password hash --password=MyPassword
```

=== "Hash output"

```text
$2a$10$L3Xb5G/AJOsEK5SuOn9uzOhpCCfuVWTajc5hwWerY6N5xBM/xlrMK
```

### 2. Enable authentication

Expand All @@ -92,25 +100,25 @@ respectively. HTTP and WS requires a different token.
=== "Generate a token for HTTP"

```bash
curl -X POST --data '{"username":"username1","password":"pegasys"}' <JSON-RPC-http-hostname:http-port>/login
curl -X POST --data '{"username":"username1","password":"MyPassword"}' <JSON-RPC-http-hostname:http-port>/login
```

=== "Example for HTTP"

```bash
curl -X POST --data '{"username":"username1","password":"pegasys"}' http://localhost:8545/login
curl -X POST --data '{"username":"username1","password":"MyPassword"}' http://localhost:8545/login
```

=== "Generate a token for WS"

```bash
curl -X POST --data '{"username":"username1","password":"pegasys"}' <JSON-RPC-ws-hostname:ws-port>/login
curl -X POST --data '{"username":"username1","password":"MyPassword"}' <JSON-RPC-ws-hostname:ws-port>/login
```

=== "Example for WS"

```bash
curl -X POST --data '{"username":"username1","password":"pegasys"}' http://localhost:8546/login
curl -X POST --data '{"username":"username1","password":"MyPassword"}' http://localhost:8546/login
```

=== "JSON result"
Expand All @@ -126,56 +134,97 @@ expires, you need to generate a new token.

Enable authentication from the command line and supply the external JWT provider's public key.

JWT public authentication disables the Besu `/login` endpoint, meaning
[username and password authentication](#username-and-password-authentication) will not work.
!!! important
JWT public authentication disables the Besu `/login` endpoint, meaning
[username and password authentication](#username-and-password-authentication) will not work.

### 1. Generate a private and public key pair

!!!note
The private and accompanying public key files must be in `.pem` format.

This step is for demonstration or testing purposes only. In a production environment the
external JWT provider supplies the public key file.
The [key algorithm](https://datatracker.ietf.org/doc/html/rfc7518#section-3.1) can be:

The private and accompanying public key files must be in `.pem` format.
* RSA with private key length of at least 2048 bits using algorithm `RS256`, `RS384` or `RS512`.
* ECDSA private key, using `ES256` (`secp256r1` or `secp256k1`), `ES384` or `ES512`.

The key must use an RSA private key of at least 2048 bits.
Besu default is `RS256`.

!!! example "Sample using OpenSSL"
!!! example "Example of key generation using OpenSSL"

```bash
openssl genrsa -out privateKey.pem 2048
openssl rsa -pubout -in privateKey.pem -pubout -out publicKey.pem
```
=== "`RS256` RSA Keys"

1. Generate the private key:

```bash
openssl genrsa -out privateRSAKey.pem 2048
```

1. Generate the public key:

```bash
openssl rsa -pubout -in privateRSAKey.pem -pubout -out publicRSAKey.pem
```

=== "`ES256` `secp256r1` ECDSA Keys"

1. Generate the private key:

```bash
openssl ecparam -name secp256r1 -genkey -out privateECDSAKey.pem
```

1. Generate the public key:

```bash
openssl ec -in privateECDSAKey.pem -pubout -out publicECDSAKey.pem
```

!!! critical "Private key security"
The private key must be kept secret. Never share private keys publicly or on a Web site,
even if advertised as secure.

Always keep your private keys safe -- ideally using
[harware](https://connect2id.com/products/nimbus-jose-jwt/examples/pkcs11) or
[vault](https://www.vaultproject.io/docs/secrets/identity/identity-token) --
and define a strong security policy and
[best practices](https://auth0.com/docs/best-practices/token-best-practices).

Compromised keys can provide attackers access to you nodes RPC-API.

### 2. Create the JWT

Create the JWT using an external tool.
Create the JWT using a trusted authentication provider[^1] or [library](https://jwt.io/libraries) in your own code.

!!! important
[^1]: for example [Auth0](https://auth0.com/) or [Keycloak](https://www.keycloak.org/)

See [Java code sample to generate JWT using Vertx](https://github.com/NicolasMassart/java-jwt-sample-generation/)
for an example implementation.

The JWT must use the `RS256` algorithm
!!! important
The JWT must use one of the `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, or `ES512` algorithms.

Each payload for the JWT contains:
Each payload for the JWT must contain:

* [JSON-RPC permissions](#json-rpc-permissions)
* [`exp` (Expiration Time) claim](https://tools.ietf.org/html/rfc7519#section-4.1.4)
* Optionally, the tenant's Tessera public key using `privacyPublicKey`. Only used for
[multi-tenancy](../../../Concepts/Privacy/Multi-Tenancy.md).

!!! example "Example payload"
!!! example "JWT generation example"

```json
{
"permissions": ["*:*"],
"privacyPublicKey": "2UKH3VJThkOoKskrLFpwoxCnnRARyobV1bEdgseFHTs=",
"exp": 1600899999002
}
```
=== "Example JSON Payload"

```json
{
"permissions": ["*:*"],
"privacyPublicKey": "2UKH3VJThkOoKskrLFpwoxCnnRARyobV1bEdgseFHTs=",
"exp": 1600899999002
}
```

The following example uses the [JWT.io](https://jwt.io/) website to create a JWT for testing
purposes.
=== "Example JWT result"

![Create a JSON Web Token](../../../images/JWT.png)
![eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJwZXJtaXNzaW9ucyI6Iio6KiIsInByaXZhY3lQdWJsaWNLZXkiOiIyVUtIM1ZKVGhrT29Lc2tyTEZwd294Q25uUkFSeW9iVjFiRWRnc2VGSFRzPSIsImV4cCI6IjE2MDA4OTk5OTkwMDIiLCJpYXQiOjE2MzkxNTc2Mjd9.FGf-FmfDQlIPCRDGmNnsHZWlwrUr69d7AIDqQrIrUrSJLiwGpR3NCUhVHIDMpQvDHQYf-sFMZTYvZGrvztYRuBKWMbTfIZKN74onzNJbFIPBVQuUX2HMXmI4VQ3UFB11LShiUJHKLna13qdbqfbgJIO3HetxJhJQxTiwtixfHwyPXl-Nx8HbQy_AWH58lLAUeaoLzN7QIA9kborthBpvfK9C7Sv1lXT1cdCDC4oRKBoiMg2RWFZtGtxFsnWyloangwbhCB6Bc_elqY5nd9WkF4ix95xsP_HgBcouy1sDw6jxn5_LveX53H8owczVWP6S1e6hv6hq2fs6YkSntKMK2g](jwt.png){: style='width:15rem' }

### 3. Enable authentication

Expand Down Expand Up @@ -208,7 +257,7 @@ Specify the authentication token as a `Bearer` token in the JSON-RPC request hea

### Postman

In the _Authorization_ tab in the _TYPE_ drop-down list, select *Bearer Token* and specify the
In the **Authorization** tab in the **TYPE** drop-down list, select **Bearer Token** and specify the
token (generated either [externally](#2-create-the-jwt) or by the
[`login` request](#3-generate-an-authentication-token)).

Expand Down
Binary file added docs/HowTo/Interact/APIs/jwt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions docs/Tutorials/Examples/Private-Network-Example-Azure.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ description: Hyperledger Besu private network example on Azure

# Deploy private network example on Azure

The [Quorum Dev Quickstart on Azure](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/consensys.quorum-dev-quickstart)
enables deploying a private IBFT 2.0 network, which includes:
The [Quorum Dev Quickstart on Azure Marketplace] enables deploying a private IBFT 2.0 network, which includes:

* A bootnode.
* An RPC node.
Expand All @@ -30,7 +29,7 @@ To deploy the private network example on Azure:

1. Create a Resource Group in the [Azure Portal](https://portal.azure.com).

1. Go to the [Quorum Dev Quickstart marketplace page](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/consensys.quorum-dev-quickstart).
1. Go to the [Quorum Dev Quickstart on Azure Marketplace].

1. Click **Get It Now** and **Continue**.
The Quickstart landing page is displayed.
Expand Down Expand Up @@ -104,3 +103,5 @@ To list all containers running, run `docker ps`.
Find the complete setup in `/home/<username>/besu-quickstart`.

![Image ssh](../../images/mp_10_ssh.png)

[Quorum Dev Quickstart on Azure Marketplace]: https://azuremarketplace.microsoft.com/en-us/marketplace/apps/consensys.quorum-dev-quickstart

0 comments on commit 4b18774

Please sign in to comment.