feat: docs rehaul, fix missing context in console, quickstarts (#1212)

* onboarding components, routing, steps

* onboarding component, toc

* fix onboarding mixin

* header

* refactor docs

* fix layout

* cleanup routing

* docs routing

* fix conventions

* de en routing

* docs, guide contents, nav

* rem i18n support

* fix routing from docs

* rollup onwarn changes, preload

* update svelte plugin, update rollup config

* move docs

* revert img style, remove code table

* rem de completely

* rollup optim, template

* angular quickstart, quickstart overview page, update deps

* fix link

* pack, slug

* prefetch binding, hidden links

* export log

* guards route ch

* fix homepage

* angular docs

* docs

* resolve fsh

* overview

* docs

* docs

* packages fix race condition

* nav, home link

* add vue, aspnet

* doc optimizations

* embed status pal

* angular guide

* angular guide

* dotnet, angular guide

* viewbox

* typo

* block onboarding route for non iam writers

* set links from component data

* fix: fetch org context in guard, more main cnt (#1192)

* change get started guide, fix code blockquotes, typos

* flutter guide

* h2 spacing

* highlight strong

* plus

* rm start sublinks

* add proxy quickstart

* regex

* prevent outside click, fix project grant write

Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Max Peintner
2021-02-16 16:59:18 +01:00
committed by GitHub
parent 30a06e5bec
commit 27be460c07
168 changed files with 2306 additions and 1652 deletions

View File

@@ -0,0 +1,15 @@
---
title: Overview
---
<i class="las la-project-diagram" style="font-size: 100px; height: 100px; color:#6c8eef"></i>
> All documentations are under active work and subject to change soon!
This part of the **ZITADEL** documentation comprises three major subject areas:
1. Principles
2. Architecture
3. Protocols
Please be reminded that ZITADEL is open source — and so is the documentation. Should you happen to stumble over an incorrectness, a spelling mistake, a hard-to-understand text passage, please dont hesitate to leave a comment or propose a corresponding change.

View File

@@ -0,0 +1,23 @@
---
title: Principles
---
### ZITADEL engineering and design principles
- Be transparent about your decisions
- Embrace stateless application design
- System of records is the event store
- Everything else needs to be able to be regenerated
- Try not so solve complex problems outside of the IAM Domain
- Use a scalable storage for the event store and read models
- Try to be idempotent whenever possible
- Reduce necessity of external systems or dependencies as much as possible
- Embrace automation
- Design API first
- Optimize all components for day-two operations
- Use only open source projects with permissive licenses
- Don't roll your own crypto algorithm
- Embrace (industry) standard as much as possible
- Make use of platform features
- Be able to run with a CDN and WAF
- Releases utilized semantic versioning and release whenever feasible

View File

@@ -0,0 +1,100 @@
---
title: Architecture
---
> Images in better quality follow soon.
### Software Architecture
**ZITADEL** is built with two essential patterns. Eventsourcing and CQRS. Due to the nature of eventsourcing **ZITADEL** provides the unique capability to generate a strong audit trail of ALL the things that happen to its resources, without compromising on storage cost or audit trail length.
The combination with CQRS makes **ZITADEL** eventual consistent which, from our perspective is a great benefit. It allows us to build a SOR (Source of Records) which is the one single point of truth for all computed states. The SOR needs to be transaction safe to make sure all operations are in order.
Each **ZITADEL** contains all components of the IAM, from serving as API, rendering / serving GUI's, background processing of events and task or being a GITOPS style operator. This AiO (All in One) approach makes scaling from a single machine to a multi region (multi cluster) seamless.
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="img/zitadel_software_architecture.png" itemprop="contentUrl" data-size="1530x681">
<img src="img/zitadel_software_architecture.png" itemprop="thumbnail" alt="Software Architecture" />
</a>
<figcaption itemprop="caption description">Software Architecture</figcaption>
</figure>
</div>
#### Component Command Side
The **command handler** receives all operations who alter a IAM resource. For example if a user changes his name.
This information is then passed to **command validation** for processing of the business logic, for example to make sure that the user actually can change his name. If this succeeds all generated events are inserted into the eventstore when required all within one transaction.
- Transaction safety is a MUST
- Availability MUST be high
> When we classify this with the CAP theorem we would choose **Consistent** and **Available** but leave **Performance** aside.
#### Component Spooler
The spoolers job is it to keep a query view up-to-date or at least look that it does not have a too big lag behind the eventstore.
Each query view has its own spooler who is responsible to look for the events who are relevant to generate the query view. It does this by triggering the relevant projection.
Spoolers are especially necessary where someone can query datasets instead of single ids.
> The query side has the option to dynamically check the eventstore for newer events on a certain id, see query side for more information
> Each view can have exactly one spooler, but spoolers are dynamically leader elected, so even if a spooler crashes it will be replaced in a short amount of time.
#### Component Query Side
The query handler receives all read relevant operations. These can either be query or simple `getById` calls.
When receiving a query it will proceed by passing this to the repository which will call the database and return the dataset.
If a request calls for a specific id the call will, most of the times, be revalidated against the eventstore. This is achieved by triggering the projection to make sure that the last sequence of a id is loaded into the query view.
- Easy to query
- Short response times (80%of queries below 100ms on the api server)
- Availability MUST be high
> When we classify this with the CAP theorem we would choose **Available** and **Performance** but leave **Consistent** aside
> TODO explain more here
#### Component HTTP Server
The http server is responsible for serving the management GUI called **ZITADEL Console**, serving the static assets and as well rendering server side html (login, password-reset, verification, ...)
### Cluster Architecture
A **ZITADEL Cluster** is a highly available IAM system with each component critical for serving traffic laid out at least three times.
As our storage (CockroachDB) relies on Raft it is also necessary to always utilizes odd numbers to address for "split brain" scenarios.
Hence our reference design is to have three application nodes and three Storage Nodes.
If you deploy **ZITADEL** with our GITOPS Tooling [**ORBOS**](https://github.com/caos/orbos) we create 7 seven nodes. One management, three application and three storage nodes.
> You can horizontaly scale zitadel, but we recommend to use multiple cluster instead to reduce the blast radius from impacts to a single cluster
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="img/zitadel_cluster_architecture.png" itemprop="contentUrl" data-size="1530x681">
<img src="img/zitadel_cluster_architecture.png" itemprop="thumbnail" alt="Cluster Architecture" />
</a>
<figcaption itemprop="caption description">Cluster Architecture</figcaption>
</figure>
</div>
### Multi Cluster Architecture
To scale **ZITADEL** is recommend to create smaller clusters, see cluster architecture and then create a fabric which interconnects the database.
In our reference design we recommend to create a cluster per cloud provider or availability zone and to group them into regions.
For example, you can run three cluster for the region switzerland. On with GCE, one with cloudscale and one with inventx.
With this design even the outage of a whole data-center would have a minimal impact as all data is still available at the other two locations.
> Cockroach needs to be configured with locality flags to proper distribute data over the zones
> East - West connectivity for the database can be solved at you discretion. We recommend to expose the public ips and run traffic directly without any VPN or Mesh
> Use MTLS in combination with IP Allowlist in the firewalls!
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="img/zitadel_multicluster_architecture.png" itemprop="contentUrl" data-size="1530x681">
<img src="img/zitadel_multicluster_architecture.png" itemprop="thumbnail" alt="Multi-Cluster Architecture" />
</a>
<figcaption itemprop="caption description">Multi-Cluster Architecture</figcaption>
</figure>
</div>

View File

@@ -0,0 +1,289 @@
---
title: OpenID Connect 1.0 & OAuth 2.0
---
### Endpoints and Domains
This chapter documents the [OpenID Connect 1.0](https://openid.net/connect/) and [OAuth 2.0](https://oauth.net/2/) features provided by **ZITADEL**.
Under normal circumstances **ZITADEL** need four domain names to operate properly.
| Domain Name | Example | Description |
|:------------|:----------------------|--------------------------------------------------------------------------------------------------------------------------------------|
| issuer | `issuer.zitadel.ch` | Provides the [OpenID Connect 1.0 Discovery Endpoint](#OpenID_Connect_1_0_Discovery) |
| api | `api.zitadel.ch` | All ZITADEL API's are located under this domain see [API explanation](apis#APIs) for details |
| login | `accounts.zitadel.ch` | The accounts.* page provides server renderer pages like login and register and as well the authorization_endpoint for OpenID Connect |
| console | `console.zitadel.ch` | With the console.* domain we serve the assets for the management gui |
#### OpenID Connect 1.0 Discovery
The OpenID Connect Discovery Endpoint is located within the issuer domain.
For example with [zitadel.ch](https://zitadel.ch), issuer.zitadel.ch would be the domain. This would give us [https://issuer.zitadel.ch/.well-known/openid-configuration](https://issuer.zitadel.ch/.well-known/openid-configuration).
**Link to spec.** [OpenID Connect Discovery 1.0 incorporating errata set 1](https://openid.net/specs/openid-connect-discovery-1_0.html)
#### authorization_endpoint
[https://accounts.zitadel.ch/oauth/v2/authorize](https://accounts.zitadel.ch/oauth/v2/authorize)
> The authorization_endpoint is located with the login page, due to the need of accessing the same cookie domain
#### token_endpoint
[https://api.zitadel.ch/oauth/v2/token](https://api.zitadel.ch/oauth/v2/token)
#### userinfo_endpoint
[https://api.zitadel.ch/oauth/v2/userinfo](https://api.zitadel.ch/oauth/v2/userinfo)
#### end_session_endpoint
[https://accounts.zitadel.ch/oauth/v2/endsession](https://accounts.zitadel.ch/oauth/v2/endsession)
> The end_session_endpoint is located with the login page, due to the need of accessing the same cookie domain
#### jwks_uri
[https://api.zitadel.ch/oauth/v2/keys](https://api.zitadel.ch/oauth/v2/keys)
> Be aware that these keys can be rotated without any prior notice. We will however make sure that a proper `kid` is set with each key!
#### OAuth 2.0 Metadata
**ZITADEL** does not yet provide a OAuth 2.0 Metadata endpoint but instead provides a [OpenID Connect Discovery Endpoint](#OpenID_Connect_1_0_Discovery).
### Scopes
ZITADEL supports the usage of scopes as way of requesting information from the IAM and also instruct ZITADEL to do certain operations.
#### Standard Scopes
| Scopes | Example | Description |
|:--------|:----------|------------------------------------------------------|
| openid | `openid` | When using openid connect this is a mandatory scope |
| profile | `profile` | Optional scope to request the profile of the subject |
| email | `email` | Optional scope to request the email of the subject |
| address | `address` | Optional scope to request the address of the subject |
#### Custom Scopes
> This feature is not yet released
#### Reserved Scopes
In addition to the standard compliant scopes we utilize the following scopes.
| Scopes | Example | Description |
|:------------------------------------------------|:-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| urn:zitadel:iam:org:project:role:{rolename} | `urn:zitadel:iam:org:project:role:user` | By using this scope a [client](administrate#clients) can request the claim urn:zitadel:iam:roles:rolename} to be asserted when possible. As an alternative approach you can enable all [roles](administrate#Roles) to be asserted from the [project](administrate#projects) a [client](administrate#clients) belongs to. See details [here](administrate#RBAC_Settings) |
| urn:zitadel:iam:org:domain:primary:{domainname} | `urn:zitadel:iam:org:domain:primary:acme.ch` | When requesting this scope **ZITADEL** will enforce that the user is a member of the selected organization. If the organization does not exist a failure is displayed |
| urn:zitadel:iam:role:{rolename} | | |
| urn:zitadel:iam:org:project:id:{projectid}:aud | ZITADEL's Project id is `urn:zitadel:iam:org:project:id:69234237810729019:aud` | By adding this scope, the requested projectid will be added to the audience of the access and id token |
> If access to ZITADEL's API's is needed with a service user the scope `urn:zitadel:iam:org:project:id:69234237810729019:aud` needs to be used with the JWT Profile request
### Claims
ZITADEL asserts claims on different places according to the corresponding specifications or project and clients settings.
Please check below the matrix for an overview where which scope is asserted.
| Claims | Userinfo | ID Token | Access Token |
|:------------------------------------------------|:-------------------|----------------------------------------|------------------------------------------|
| acr | Yes | Yes | No |
| address | Yes when requested | Yes only when response type `id_token` | No |
| amr | Yes | Yes | No |
| aud | No | Yes | Yes when JWT |
| auth_time | Yes | Yes | No |
| azp | No | Yes | Yes when JWT |
| email | Yes when requested | Yes only when response type `id_token` | No |
| email_verified | Yes when requested | Yes only when response type `id_token` | No |
| exp | No | Yes | Yes when JWT |
| family_name | Yes when requested | Yes when requested | No |
| gender | Yes when requested | Yes when requested | No |
| given_name | Yes when requested | Yes when requested | No |
| iat | No | Yes | Yes when JWT |
| iss | No | Yes | Yes when JWT |
| locale | Yes when requested | Yes when requested | No |
| name | Yes when requested | Yes when requested | No |
| nonce | No | Yes | No |
| phone | Yes when requested | Yes only when response type `id_token` | No |
| preferred_username | Yes when requested | Yes | No |
| sub | Yes | Yes | Yes when JWT |
| urn:zitadel:iam:org:domain:primary:{domainname} | Yes when requested | Yes when requested | Yes when JWT and requested |
| urn:zitadel:iam:org:project:roles:{rolename} | Yes when requested | Yes when requested or configured | Yes when JWT and requested or configured |
#### Standard Claims
| Claims | Example | Description |
|:-------------------|:-----------------------------------------|-----------------------------------------------------------------------------------------------|
| acr | TBA | TBA |
| address | `Teufener Strasse 19, 9000 St. Gallen` | TBA |
| amr | `pwd mfa` | Authentication Method References as defined in [RFC8176](https://tools.ietf.org/html/rfc8176) |
| aud | `69234237810729019` | By default all client id's and the project id is included |
| auth_time | `1311280969` | Unix time of the authentication |
| azp | `69234237810729234` | Client id of the client who requested the token |
| email | `road.runner@acme.ch` | Email Address of the subject |
| email_verified | `true` | Boolean if the email was verified by ZITADEL |
| exp | `1311281970` | Time the token expires as unix time |
| family_name | `Runner` | The subjects family name |
| gender | `other` | Gender of the subject |
| given_name | `Road` | Given name of the subject |
| iat | `1311280970` | Issued at time of the token as unix time |
| iss | `https://issuer.zitadel.ch` | Issuing domain of a token |
| locale | `en` | Language from the subject |
| name | `Road Runner` | The subjects full name |
| nonce | `blQtVEJHNTF0WHhFQmhqZ0RqeHJsdzdkd2d...` | The nonce provided by the client |
| phone | `+41 79 XXX XX XX` | Phone number provided by the user |
| preferred_username | `road.runner@acme.caos.ch` | ZITADEL's login name of the user. Consist of `username@primarydomain` |
| sub | `77776025198584418` | Subject ID of the user |
#### Custom Claims
> This feature is not yet released
#### Reserved Claims
ZITADEL reserves some claims to assert certain data.
| Claims | Example | Description |
|:------------------------------------------------|:-----------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| urn:zitadel:iam:org:domain:primary:{domainname} | `{"urn:zitadel:iam:org:domain:primary": "acme.ch"}` | This claim represents the primary domain of the organization the user belongs to. |
| urn:zitadel:iam:org:project:roles:{rolename} | `{"urn:zitadel:iam:org:project:roles": [ {"user": {"id1": "acme.zitade.ch", "id2": "caos.ch"} } ] }` | When roles are asserted, ZITADEL does this by providing the `id` and `primaryDomain` below the role. This gives you the option to check in which organization a user has the role. |
| urn:zitadel:iam:roles:{rolename} | TBA | TBA |
### Grant Types
For a list of supported or unsupported `Grant Types` please have a look at the table below.
| Grant Type | Supported |
|:------------------------------------------------------|:--------------------|
| Authorization Code | yes |
| Authorization Code with PKCE | yes |
| Client Credentials | yes |
| Device Authorization | under consideration |
| Implicit | yes |
| JSON Web Token (JWT) Profile | partially |
| Refresh Token | work in progress |
| Resource Owner Password Credentials | no |
| Security Assertion Markup Language (SAML) 2.0 Profile | no |
| Token Exchange | work in progress |
#### Authorization Code
**Link to spec.** [The OAuth 2.0 Authorization Framework Section 1.3.1](https://tools.ietf.org/html/rfc6749#section-1.3.1)
#### Proof Key for Code Exchange
**Link to spec.** [Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636)
#### Implicit
**Link to spec.** [The OAuth 2.0 Authorization Framework Section 1.3.2](https://tools.ietf.org/html/rfc6749#section-1.3.2)
#### Client Credentials
**Link to spec.** [The OAuth 2.0 Authorization Framework Section 1.3.4](https://tools.ietf.org/html/rfc6749#section-1.3.4)
#### Refresh Token
**Link to spec.** [The OAuth 2.0 Authorization Framework Section 1.5](https://tools.ietf.org/html/rfc6749#section-1.5)
#### JSON Web Token (JWT) Profile
**Link to spec.** [JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants](https://tools.ietf.org/html/rfc7523)
##### Using JWTs as Authorization Grants
Our service user work with the JWT profile to authenticate them against ZITADEL.
1. Create or use an existing service user
2. Create a new key and download it
3. Generate a JWT with the structure below and sing it with the downloaded key
4. Send the JWT Base64 encoded to ZITADEL's token endpoint
5. Use the received access token
---
Key JSON
| Key | Example | Description |
|:-------|:--------------------------------------------------------------------|:-------------------------------------------------------------------|
| type | `"serviceaccount"` | The type of account, right now only serviceaccount is valid |
| keyId | `"81693565968772648"` | This is unique ID of the key |
| key | `"-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----"` | The private key generated by ZITADEL, this can not be regenerated! |
| userId | `78366401571647008` | The service users ID, this is the same as the subject from tokens |
```JSON
{
"type": "serviceaccount",
"keyId": "81693565968772648",
"key": "-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----",
"userId": "78366401571647008"
}
```
---
JWT
| Claim | Example | Description |
|:------|:------------------------------|:--------------------------------------------------------------------------------------------------------------|
| aud | `"https://issuer.zitadel.ch"` | String or Array of intended audiences MUST include ZITADEL's issuing domain |
| exp | `1605183582` | Unix timestamp of the expiry, MUST NOT be longer than 1h |
| iat | `1605179982` | Unix timestamp of the creation singing time of the JWT |
| iss | `"77479219772321307"` | String which represents the requesting party (owner of the key), normally the `userId` from the json key file |
| sub | `"77479219772321307"` | The subject ID of the service user, normally the `userId` from the json key file |
```JSON
{
"iss": "77479219772321307",
"sub": "77479219772321307",
"aud": "https://issuer.zitadel.ch",
"exp": 1605183582,
"iat": 1605179982
}
```
---
Access Token Request
| Parameter | Example | Description |
|:-------------|:----------------------------------------------------------------------------|:----------------------------------------------|
| Content-Type | `application/x-www-form-urlencoded` | |
| grant_type | `urn:ietf:params:oauth:grant-type:jwt-bearer` | Using JWTs as Authorization Grants |
| assertion | `eyJhbGciOiJSUzI1Ni...` | The base64 encoded JWT created above |
| scope | `openid profile email urn:zitadel:iam:org:project:id:69234237810729019:aud` | Scopes you would like to request from ZITADEL |
```BASH
curl --request POST \
--url https://api.zitadel.ch/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \
--data assertion=eyJhbGciOiJSUzI1Ni...
--data scope=openid profile email address
```
##### Using JWTs for Client Authentication
> Not yet supported
#### Token Exchange
**Link to spec.** [OAuth 2.0 Token Exchange](https://tools.ietf.org/html/rfc8693)
### Device Authorization
**Link to spec.** [OAuth 2.0 Device Authorization Grant](https://tools.ietf.org/html/rfc8628)
### Not Supported Grant Types
#### Resource Owner Password Credentials
> Due to growing security concerns we do not support this grant type. With OAuth 2.1 it looks like this grant will be removed.
**Link to spec.** [OThe OAuth 2.0 Authorization Framework Section 1.3.3](https://tools.ietf.org/html/rfc6749#section-1.3.3)
#### Security Assertion Markup Language (SAML) 2.0 Profile
**Link to spec.** [Security Assertion Markup Language (SAML) 2.0 Profile for OAuth 2.0 Client Authentication and Authorization Grants](https://tools.ietf.org/html/rfc7522)