docs: styling, concepts cleanup (#2643)

* Architecture Scenarios B2B B2C

* b2b b2c

* cleanup concepts

* homepage links, b2c docs

* b2c, new homepage, custom components

* more content

* fix rxjs

* temp remove architecture scenarios

* temp remove architecture scenarios

* Update docs/src/pages/index.js

Co-authored-by: Florian Forster <florian@caos.ch>

* update docusaurus & review scenarios

* refactor user login guide (#2921)

* Update docs/docs/guides/architecture-scenarios/b2b.mdx

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* Update docs/docs/guides/architecture-scenarios/b2b.mdx

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* Update docs/docs/guides/architecture-scenarios/b2b.mdx

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* Update docs/docs/guides/architecture-scenarios/b2b.mdx

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* Update docs/docs/guides/architecture-scenarios/b2c.mdx

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* Update docs/docs/guides/architecture-scenarios/b2c.mdx

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* Update docs/docs/guides/architecture-scenarios/b2b.mdx

Co-authored-by: mffap <mpa@caos.ch>

* Update docs/docs/guides/architecture-scenarios/b2b.mdx

Co-authored-by: mffap <mpa@caos.ch>

* Update docs/docs/guides/architecture-scenarios/b2b.mdx

Co-authored-by: mffap <mpa@caos.ch>

* Update docs/docs/guides/architecture-scenarios/b2c.mdx

Co-authored-by: mffap <mpa@caos.ch>

* Update docs/docs/guides/architecture-scenarios/b2c.mdx

Co-authored-by: mffap <mpa@caos.ch>

* Update docs/docs/guides/architecture-scenarios/b2c.mdx

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* user-login splitup

* files

* organize files

* cleanup authmethods

* solution scenarios

* add link to authz

* Update docs/docs/guides/authentication/authmethods/implicit.mdx

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* Update docs/docs/guides/authentication/authmethods/implicit.mdx

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix broken links

* Update docs/docs/guides/solution-scenarios/b2c.mdx

Co-authored-by: Florian Forster <florian@caos.ch>

* c for consumer

Co-authored-by: Florian Forster <florian@caos.ch>
Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
Co-authored-by: mffap <mpa@caos.ch>
Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Max Peintner 2022-01-11 20:48:13 +01:00 committed by GitHub
parent 41ec3321b0
commit 68827dfdcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 1434 additions and 539 deletions

View File

@ -2,7 +2,7 @@
title: Eventstore
---
ZITADEL is built on the [event sourcing pattern](../zitadel/architecture.md), where changes are stored as events in an eventstore.
ZITADEL is built on the [event sourcing pattern](./architecture), where changes are stored as events in an eventstore.
## What is an eventstore?

View File

@ -1,7 +0,0 @@
---
title: Introduction
---
This part of the **ZITADEL** documentation contains ZITADEL specific or general concepts required to understand the system or our guides.
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,39 @@
---
title: Introduction
---
import {ListElement, ListWrapper, ICONTYPE} from '../../src/components/list';
import Column from '../../src/components/column';
This part of the **ZITADEL** documentation contains ZITADEL specific or general concepts required to understand the system or our guides.
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.
<Column>
<ListWrapper title="General">
<ListElement link="./principles" type={ICONTYPE.TASKS} title="Principles" description="Design and engineering principles" />
<ListElement link="./eventstore" type={ICONTYPE.STORAGE} title="Eventstore" description="Learn how ZITADEL stores data" />
<ListElement link="./architecture" type={ICONTYPE.ARCHITECTURE} title="Architecture" description="Sotware-, Cluster- and Multi Cluster Architecture" />
</ListWrapper>
<ListWrapper title="Structure">
<Column>
<div>
<ListElement link="./structure/overview" type={ICONTYPE.FOLDER} title="Overview" description="" />
<ListElement link="./structure/organizations" type={ICONTYPE.FILE} title="Organizations" description="" />
<ListElement link="./structure/policies" type={ICONTYPE.FILE} title="Policies" description="" />
<ListElement link="./structure/projects" type={ICONTYPE.FILE} title="Projects" description="" />
</div>
<div>
<ListElement link="./structure/applications" type={ICONTYPE.FILE} title="Applications" description="" />
<ListElement link="./structure/granted_projects" type={ICONTYPE.FILE} title="Granted Projects" description="" />
<ListElement link="./structure/users" type={ICONTYPE.FILE} title="Users" description="" />
<ListElement link="./structure/managers" type={ICONTYPE.FILE} title="Managers" description="" />
</div>
</Column>
</ListWrapper>
<ListWrapper title="Use Cases">
<ListElement link="./usecases/saas" type={ICONTYPE.START} title="SaaS" description="Product with Authentication and Authorization" />
</ListWrapper>
</Column>

View File

@ -18,4 +18,5 @@ As a fourth option there's the API (OAuth Resource Server), which generally has
Depending on the app type registered, there are small differences in the possible settings.
Please read the following guide about the [different-client-profiles](../../../guides/authorization/oauth-recommended-flows#different-client-profiles).
Please read the following guide about the
[different-client-profiles](../../guides/authorization/oauth-recommended-flows#different-client-profiles).

View File

@ -1,5 +1,5 @@
---
title: Structure
title: Overview
---
This overview shows the general structure of ZITADEL.

View File

@ -55,7 +55,7 @@ You can configure all kinds of external identity providers for identity brokerin
Create a new identity provider configuration and enable it in the list afterwards.
For a detailed guide about how to configure a new identity provider for identity brokering have a look at our guide:
[Identity Brokering](../../../guides/authentication/identity-brokering)
[Identity Brokering](../../guides/authentication/identity-brokering)
## Lockout Policy

View File

@ -11,7 +11,7 @@ import ProjectDescription from './_project_description.mdx';
## Project Settings
On default the login screen will be shown in the private labeling settings of the system (e.g zitadel.ch).
With the [primary domain scope](../../../apis/openidoauth/scopes#reserves-scopes) it is possible to trigger the setting of the given organization.
With the [primary domain scope](../../apis/openidoauth/scopes#reserves-scopes) it is possible to trigger the setting of the given organization.
But this will also restrict, the login to user of the given organization.
With the private labeling setting it is possible to choose which settings should trigger.

View File

@ -1,5 +1,5 @@
---
title: Saas Product with Authentication and Authorization
title: SaaS Product with Authentication and Authorization
---
This is an example architecture for a typical SaaS product.

View File

@ -37,7 +37,7 @@ ZITADEL Managers are Users who have permission to manage ZITADEL itself. There a
- **Project Mangers**: In this level the user is able to manage a project.
- **Project Grant Manager**: The project grant manager is for projects, which are granted of another organization.
On each level we have some different Roles. Here you can find more about the different roles: [ZITADEL Manager Roles](../../concepts/zitadel/objects/managers.md)
On each level we have some different Roles. Here you can find more about the different roles: [ZITADEL Manager Roles](../../concepts/structure/managers.md)
## Exercise: Add ORG_OWNER to Service User

View File

@ -5,6 +5,7 @@ import PKCE from "./authmethods/pkce.mdx";
import Basic from "./authmethods/basic.mdx";
import Implicit from "./authmethods/implicit.mdx";
import PKCENative from "./authmethods/pkcenative.mdx";
import JWTPrivateKey from "./authmethods/jwtpk.mdx";
export default function AuthMethods(props) {
return props.selected == "web" ? (
@ -15,7 +16,7 @@ export default function AuthMethods(props) {
values={[
{ label: "PKCE", value: "pkce" },
{ label: "Basic Auth", value: "basic" },
{ label: "JWT with Private Key", value: "jwt" },
{ label: "JWT with Private Key", value: "jwtpk" },
]}
>
<TabItem value="pkce">
@ -24,8 +25,8 @@ export default function AuthMethods(props) {
<TabItem value="basic">
<Basic />
</TabItem>
<TabItem value="implicit">
<Implicit />
<TabItem value="jwtpk">
<JWTPrivateKey />
</TabItem>
</Tabs>
</div>

View File

@ -0,0 +1,78 @@
#### redirect_uri
After selecting the authentication method, you can register a redirect_uri and post_logout_redirect_uri.
The redirect_uri will be called after user authentication for code exchange.
You can even register multiple, but typically one will be enough. If you need to distinguish between different scenarios
or environments we recommend using the `state` parameter for the former and multiple projects for the latter.
## Auth Request
To initialize the user authentication, you will have to create an authorization request using HTTP GET in the user agent (browser)
on /authorize with at least the following parameters:
- `client_id`: this tells the authorization server which application it is, copy from Console
- `redirect_uri`: where the authorization code is sent to after the user authentication, must be one of the registered in the previous step
- `response_type`: if you want to have a code (authorization code flow) or directly a token (implicit flow), so when ever possible use `code`
- `scope`: what scope you want to grant to the access_token / id_token, minimum is `openid`, if you're unsure what you need you might start with `openid profile email`
We recommend always using two additional parameters `state` and `nonce`. The former enables you to transfer a state through
the authentication process. The latter is used to bind the client session with the id_token and to mitigate replay attacks.
You don't need any additional parameter for this request. We're identifying the app by the `client_id` parameter.
So your request might look like this (linebreaks and whitespace for display reasons):
```curl
curl --request GET \
--url 'https://accounts.zitadel.ch/oauth/v2/authorize
?client_id=${client_id}
&redirect_uri=${redirect_uri}
&response_type=code
&scope=openid%20email%20profile'
```
### Additional parameters and customization
There are additional parameters and values you can provide to satisfy your use case and to customize the user's authentication flow.
Please check the [authorization_endpoint reference](/docs/apis/openidoauth/endpoints#authorization_endpoint) in the OAuth / OIDC documentation.
## Callback
Regardless of a successful or error response from the authorization_endpoint, the authorization server will call your
callback endpoint you provided by the `redirect_uri`.
:::note
If the redirect_uri is not provided, was not registered or anything other prevents the auth server form returning the response to the client,
the error will be display directly to the user on the auth server.
:::
Upon successful authentication you'll be given a `code` and if provided the unmodified `state` parameter.
You will need this `code` in the token request.
If a parameter was missing, malformed or any other error occurred, your answer will contain an `error` stating the error type,
possibly an `error_description` providing some information about the error and its reason and the `state` parameter.
Check the [error response section](/docs/apis/openidoauth/endpoints#error-response) in the authorization_endpoint reference.
## Token request
Next you will have to exchange the given `code` for the tokens. For this HTTP POST request (form-urlencoded) you will need to provide the following:
- code: the code that was issued from the authorization request
- grant_type: must be `authorization_code`
- redirect_uri: callback uri where the code was sent to. Must match exactly the redirect_uri of the authorization request
Depending on your authentication method you'll need additional headers and parameters:
Send your `client_id` and `client_secret` as Basic Auth Header. Note that OAuth2 requires client_id and client_secret to be form url encoded.
So check [Client Secret Basic Auth Method](/docs/apis/openidoauth/authn-methods#client-secret-basic) on how to build it correctly.
```curl
curl --request POST \
--url https://api.zitadel.ch/oauth/v2/token \
--header 'Authorization: Basic ${basic}' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=${code} \
--data redirect_uri=${redirect_uri}
```

View File

@ -7,4 +7,43 @@ We therefore discourage the use of Implicit Flow and do not cover the flow in th
:::
If you still need to rely on the implicit flow, simply keep in mind that the response on the authorization_endpoint is
the same you would be given on the token_endpoint and check the [OAuth / OIDC endpoint documentation](../../../apis/openidoauth/endpoints.md) for more information.
the same you would be given on the token_endpoint and check the [OAuth / OIDC endpoint documentation](/docs/apis/openidoauth/endpoints) for more information.
#### redirect_uri
After selecting the authentication method, you can register a redirect_uri and post_logout_redirect_uri.
The redirect_uri will be called after user authentication for code exchange.
You can even register multiple, but typically one will be enough. If you need to distinguish between different scenarios
or environments we recommend using the `state` parameter for the former and multiple projects for the latter.
## Auth Request
To initialize the user authentication, you will have to create an authorization request using HTTP GET in the user agent (browser)
on /authorize with at least the following parameters:
- `client_id`: this tells the authorization server which application it is, copy from Console
- `redirect_uri`: where the authorization code is sent to after the user authentication, must be one of the registered in the previous step
- `response_type`: if you want to have a code (authorization code flow) or directly a token (implicit flow), so when ever possible use `code`
- `scope`: what scope you want to grant to the access_token / id_token, minimum is `openid`, if you're unsure what you need you might start with `openid profile email`
When using the Implicit Flow you will also have to provide a `nonce` parameter to bind the client session to the id_token and to mitigate replay attacks. Furthermore, we recommend using a `state` parameter, which enables you to transfer a state through the authentication process.
### Additional parameters and customization
There are additional parameters and values you can provide to satisfy your use case and to customize the user's authentication flow.
Please check the [authorization_endpoint reference](/docs/apis/openidoauth/endpoints#authorization_endpoint) in the OAuth / OIDC documentation.
## Callback
Regardless of a successful or error response from the authorization_endpoint, the authorization server will call your callback endpoint you provided by the `redirect_uri`.
:::note
If the redirect_uri is not provided, was not registered or anything other prevents the auth server form returning the response to the client, the error will be display directly to the user on the auth server.
:::
Upon successful authentication you'll be given the `access_token`, `id_token`, `expires_in` and if provided the unmodified `state` parameter, as you would be given from the token_endpoint when using Authorization Code Flow.
If a parameter was missing, malformed or any other error occurred, your answer will contain an `error` stating the error type,
possibly an `error_description` providing some information about the error and its reason and the `state` parameter.
Check the [error response section](/docs/apis/openidoauth/endpoints#error-response) in the authorization_endpoint reference.

View File

@ -0,0 +1,79 @@
#### redirect_uri
After selecting the authentication method, you can register a redirect_uri and post_logout_redirect_uri.
The redirect_uri will be called after user authentication for code exchange.
You can even register multiple, but typically one will be enough. If you need to distinguish between different scenarios
or environments we recommend using the `state` parameter for the former and multiple projects for the latter.
## Auth Request
To initialize the user authentication, you will have to create an authorization request using HTTP GET in the user agent (browser)
on /authorize with at least the following parameters:
- `client_id`: this tells the authorization server which application it is, copy from Console
- `redirect_uri`: where the authorization code is sent to after the user authentication, must be one of the registered in the previous step
- `response_type`: if you want to have a code (authorization code flow) or directly a token (implicit flow), so when ever possible use `code`
- `scope`: what scope you want to grant to the access_token / id_token, minimum is `openid`, if you're unsure what you need you might start with `openid profile email`
We recommend always using two additional parameters `state` and `nonce`. The former enables you to transfer a state through
the authentication process. The latter is used to bind the client session with the id_token and to mitigate replay attacks.
You don't need any additional parameter for this request. We're identifying the app by the `client_id` parameter.
So your request might look like this (linebreaks and whitespace for display reasons):
```curl
curl --request GET \
--url 'https://accounts.zitadel.ch/oauth/v2/authorize
?client_id=${client_id}
&redirect_uri=${redirect_uri}
&response_type=code
&scope=openid%20email%20profile'
```
### Additional parameters and customization
There are additional parameters and values you can provide to satisfy your use case and to customize the user's authentication flow.
Please check the [authorization_endpoint reference](/docs/apis/openidoauth/endpoints#authorization_endpoint) in the OAuth / OIDC documentation.
## Callback
Regardless of a successful or error response from the authorization_endpoint, the authorization server will call your
callback endpoint you provided by the `redirect_uri`.
:::note
If the redirect_uri is not provided, was not registered or anything other prevents the auth server form returning the response to the client,
the error will be display directly to the user on the auth server.
:::
Upon successful authentication you'll be given a `code` and if provided the unmodified `state` parameter.
You will need this `code` in the token request.
If a parameter was missing, malformed or any other error occurred, your answer will contain an `error` stating the error type,
possibly an `error_description` providing some information about the error and its reason and the `state` parameter.
Check the [error response section](/docs/apis/openidoauth/endpoints#error-response) in the authorization_endpoint reference.
## Token request
Next you will have to exchange the given `code` for the tokens. For this HTTP POST request (form-urlencoded) you will need to provide the following:
- code: the code that was issued from the authorization request
- grant_type: must be `authorization_code`
- redirect_uri: callback uri where the code was sent to. Must match exactly the redirect_uri of the authorization request
Depending on your authentication method you'll need additional headers and parameters:
Send a JWT in the `client_assertion` and set the `client_assertion_type` to `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`
for us to validate the signature against the registered public key:
```curl
curl --request POST \
--url https://api.zitadel.ch/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=${code} \
--data redirect_uri=${redirect_uri} \
--data client_assertion=${client_assertion} \
--data client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
```

View File

@ -5,3 +5,84 @@ The redirect_uri will be called after user authentication for code exchange.
You can even register multiple, but typically one will be enough. If you need to distinguish between different scenarios
or environments we recommend using the `state` parameter for the former and multiple projects for the latter.
## Auth Request
To initialize the user authentication, you will have to create an authorization request using HTTP GET in the user agent (browser)
on /authorize with at least the following parameters:
- `client_id`: this tells the authorization server which application it is, copy from Console
- `redirect_uri`: where the authorization code is sent to after the user authentication, must be one of the registered in the previous step
- `response_type`: if you want to have a code (authorization code flow) or directly a token (implicit flow), so when ever possible use `code`
- `scope`: what scope you want to grant to the access_token / id_token, minimum is `openid`, if you're unsure what you need you might start with `openid profile email`
We recommend always using two additional parameters `state` and `nonce`. The former enables you to transfer a state through
the authentication process. The latter is used to bind the client session with the id_token and to mitigate replay attacks.
PKCE stands for Proof Key for Code Exchange. So other than "normal" code exchange, the does not authenticate using
client_id and client_secret but an additional code. You will have to generate a random string, hash it and send this hash
on the authorization_endpoint. On the token_endpoint you will then send the plain string for the authorization to compute
the hash as well and to verify it's correct. In order to do so you're required to send the following two parameters as well:
- `code_challenge`: the base64url representation of the (sha256) hash of your random string
- `code_challenge_method`: must always be `S256` standing for sha256, this is the only algorithm we support
For example for `random-string` the code_challenge would be `9az09PjcfuENS7oDK7jUd2xAWRb-B3N7Sr3kDoWECOY`
The request would finally look like (linebreaks and whitespace for display reasons):
```curl
curl --request GET \
--url 'https://accounts.zitadel.ch/oauth/v2/authorize
?client_id=${client_id}
&redirect_uri=${redirect_uri}
&response_type=code
&scope=openid%20email%20profile
&code_challenge=${code_challenge}
&code_challenge_method=S256'
```
### Additional parameters and customization
There are additional parameters and values you can provide to satisfy your use case and to customize the user's authentication flow.
Please check the [authorization_endpoint reference](/docs/apis/openidoauth/endpoints#authorization_endpoint) in the OAuth / OIDC documentation.
## Callback
Regardless of a successful or error response from the authorization_endpoint, the authorization server will call your
callback endpoint you provided by the `redirect_uri`.
:::note
If the redirect_uri is not provided, was not registered or anything other prevents the auth server form returning the response to the client,
the error will be display directly to the user on the auth server.
:::
Upon successful authentication you'll be given a `code` and if provided the unmodified `state` parameter.
You will need this `code` in the token request.
If a parameter was missing, malformed or any other error occurred, your answer will contain an `error` stating the error type,
possibly an `error_description` providing some information about the error and its reason and the `state` parameter.
Check the [error response section](/docs/apis/openidoauth/endpoints#error-response) in the authorization_endpoint reference.
## Token request
Next you will have to exchange the given `code` for the tokens. For this HTTP POST request (form-urlencoded) you will need to provide the following:
- code: the code that was issued from the authorization request
- grant_type: must be `authorization_code`
- redirect_uri: callback uri where the code was sent to. Must match exactly the redirect_uri of the authorization request
Depending on your authentication method you'll need additional headers and parameters:
Send your `client_id` and the previously generated string as `code_verifier` for us to recompute the `code_challenge` of the authorization request:
```curl
curl --request POST \
--url https://api.zitadel.ch/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=${code} \
--data redirect_uri=${redirect_uri} \
--data client_id=${client_id} \
--data code_verifier=${code_verifier}
```

View File

@ -16,3 +16,48 @@ by the user agent. If one is sent we will check if the origin is allowed for you
origins of the redirect_uri list are allowed.
So if your native app is built with a JavaScript base framework like ReactNative and you only specified redirect_uris
with a custom protocol, you will need to add the origin where the app is served from, e.g. `http://localhost:8100`.
### Additional parameters and customization
There are additional parameters and values you can provide to satisfy your use case and to customize the user's authentication flow.
Please check the [authorization_endpoint reference](/docs/apis/openidoauth/endpoints#authorization_endpoint) in the OAuth / OIDC documentation.
## Callback
Regardless of a successful or error response from the authorization_endpoint, the authorization server will call your
callback endpoint you provided by the `redirect_uri`.
:::note
If the redirect_uri is not provided, was not registered or anything other prevents the auth server form returning the response to the client,
the error will be display directly to the user on the auth server.
:::
Upon successful authentication you'll be given a `code` and if provided the unmodified `state` parameter.
You will need this `code` in the token request.
If a parameter was missing, malformed or any other error occurred, your answer will contain an `error` stating the error type,
possibly an `error_description` providing some information about the error and its reason and the `state` parameter.
Check the [error response section](/docs/apis/openidoauth/endpoints#error-response) in the authorization_endpoint reference.
## Token request
Next you will have to exchange the given `code` for the tokens. For this HTTP POST request (form-urlencoded) you will need to provide the following:
- code: the code that was issued from the authorization request
- grant_type: must be `authorization_code`
- redirect_uri: callback uri where the code was sent to. Must match exactly the redirect_uri of the authorization request
Depending on your authentication method you'll need additional headers and parameters:
Send your `client_id` and the previously generated string as `code_verifier` for us to recompute the `code_challenge` of the authorization request:
```curl
curl --request POST \
--url https://api.zitadel.ch/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=${code} \
--data redirect_uri=${redirect_uri} \
--data client_id=${client_id} \
--data code_verifier=${code_verifier}
```

View File

@ -71,7 +71,6 @@ recommend using POST and will not cover it in this guide.
Please change the authentication method here as well, if you did so in the wizard, so we can better guide you through the process:
<AuthMethods selected="web" />
</TabItem>
<TabItem value="native">
@ -81,8 +80,8 @@ Please change the authentication method here as well, if you did so in the wizar
When selecting Native the authentication method always needs to be PKCE.
<AuthMethods selected="native" />
</TabItem>
<TabItem value="spa">
#### Authentication method
@ -93,179 +92,3 @@ are able to successfully authenticate with PKCE. Our Managament UI Console for i
<AuthMethods selected="spa" />
</TabItem>
</Tabs>
## Auth Request
To initialize the user authentication, you will have to create an authorization request using HTTP GET in the user agent (browser)
on /authorize with at least the following parameters:
- `client_id`: this tells the authorization server which application it is, copy from Console
- `redirect_uri`: where the authorization code is sent to after the user authentication, must be one of the registered in the previous step
- `response_type`: if you want to have a code (authorization code flow) or directly a token (implicit flow), so when ever possible use `code`
- `scope`: what scope you want to grant to the access_token / id_token, minimum is `openid`, if you're unsure what you need you might start with `openid profile email`
We recommend always using two additional parameters `state` and `nonce`. The former enables you to transfer a state through
the authentication process. The latter is used to bind the client session with the id_token and to mitigate replay attacks.
Depending on your authentication method you might need to provide additional parameters:
<Tabs
groupId="auth-type"
default="pkce"
values={[
{'label': 'PKCE', 'value': 'pkce'},
{'label': 'Basic Auth', 'value': 'basic'},
{'label': 'JWT with Private Key', 'value': 'jwt'},
]}
>
<TabItem value="pkce">
PKCE stands for Proof Key for Code Exchange. So other than "normal" code exchange, the does not authenticate using
client_id and client_secret but an additional code. You will have to generate a random string, hash it and send this hash
on the authorization_endpoint. On the token_endpoint you will then send the plain string for the authorization to compute
the hash as well and to verify it's correct. In order to do so you're required to send the following two parameters as well:
- `code_challenge`: the base64url representation of the (sha256) hash of your random string
- `code_challenge_method`: must always be `S256` standing for sha256, this is the only algorithm we support
For example for `random-string` the code_challenge would be `9az09PjcfuENS7oDK7jUd2xAWRb-B3N7Sr3kDoWECOY`
The request would finally look like (linebreaks and whitespace for display reasons):
```curl
curl --request GET \
--url 'https://accounts.zitadel.ch/oauth/v2/authorize
?client_id=${client_id}
&redirect_uri=${redirect_uri}
&response_type=code
&scope=openid%20email%20profile
&code_challenge=${code_challenge}
&code_challenge_method=S256'
```
</TabItem>
<TabItem value="basic">
You don't need any additional parameter for this request. We're identifying the app by the `client_id` parameter.
So your request might look like this (linebreaks and whitespace for display reasons):
```curl
curl --request GET \
--url 'https://accounts.zitadel.ch/oauth/v2/authorize
?client_id=${client_id}
&redirect_uri=${redirect_uri}
&response_type=code
&scope=openid%20email%20profile'
```
</TabItem>
<TabItem value="jwt">
You don't need any additional parameter for this request. We're identifying the app by the `client_id` parameter.
So your request might look like this (linebreaks and whitespace for display reasons):
```curl
curl --request GET \
--url 'https://accounts.zitadel.ch/oauth/v2/authorize
?client_id=${client_id}
&redirect_uri=${redirect_uri}
&response_type=code
&scope=openid%20email%20profile'
```
</TabItem>
</Tabs>
### Additional parameters and customization
There are additional parameters and values you can provide to satisfy your use case and to customize the user's authentication flow.
Please check the [authorization_endpoint reference](../../apis/openidoauth/endpoints#authorization_endpoint) in the OAuth / OIDC documentation.
## Callback
Regardless of a successful or error response from the authorization_endpoint, the authorization server will call your
callback endpoint you provided by the `redirect_uri`.
:::note
If the redirect_uri is not provided, was not registered or anything other prevents the auth server form returning the response to the client,
the error will be display directly to the user on the auth server.
:::
Upon successful authentication you'll be given a `code` and if provided the unmodified `state` parameter.
You will need this `code` in the token request.
If a parameter was missing, malformed or any other error occurred, your answer will contain an `error` stating the error type,
possibly an `error_description` providing some information about the error and its reason and the `state` parameter.
Check the [error response section](../../apis/openidoauth/endpoints#error-response) in the authorization_endpoint reference.
## Token request
Next you will have to exchange the given `code` for the tokens. For this HTTP POST request (form-urlencoded) you will need to provide the following:
- code: the code that was issued from the authorization request
- grant_type: must be `authorization_code`
- redirect_uri: callback uri where the code was sent to. Must match exactly the redirect_uri of the authorization request
Depending on your authentication method you'll need additional headers and parameters:
<Tabs
groupId="auth-type"
defaultValue="pkce"
values={[
{label: 'PKCE', value: 'pkce'},
{label: 'Basic Auth', value: 'basic'},
{label: 'JWT with Private Key', value: 'jwt'},
]}
>
<TabItem value="pkce">
Send your `client_id` and the previously generated string as `code_verifier` for us to recompute the `code_challenge` of the authorization request:
```curl
curl --request POST \
--url https://api.zitadel.ch/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=${code} \
--data redirect_uri=${redirect_uri} \
--data client_id=${client_id} \
--data code_verifier=${code_verifier}
```
</TabItem>
<TabItem value="basic">
Send your `client_id` and `client_secret` as Basic Auth Header. Note that OAuth2 requires client_id and client_secret to be form url encoded.
So check [Client Secret Basic Auth Method](../../apis/openidoauth/authn-methods#client-secret-basic) on how to build it correctly.
```curl
curl --request POST \
--url https://api.zitadel.ch/oauth/v2/token \
--header 'Authorization: Basic ${basic}' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=${code} \
--data redirect_uri=${redirect_uri}
```
</TabItem>
<TabItem value="jwt">
Send a JWT in the `client_assertion` and set the `client_assertion_type` to `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`
for us to validate the signature against the registered public key:
```curl
curl --request POST \
--url https://api.zitadel.ch/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=${code} \
--data redirect_uri=${redirect_uri} \
--data client_assertion=${client_assertion} \
--data client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
```
</TabItem>
</Tabs>

View File

@ -29,7 +29,7 @@ title: Service Users
</table>
import UserDescription from '../../concepts/zitadel/objects/_user_description.mdx';
import UserDescription from '../../concepts/structure/_user_description.mdx';
<UserDescription name="UserDescription" />

View File

@ -43,3 +43,4 @@ After creating your project you can start integrating your applications.
After choosing your [project](https://console.zitadel.ch/projects) add a client application on the top of the page.
The wizard should provide some guidance what client is the proper for you. If you are still unsure consult our [Guide Project](projects).
## Learn more

View File

@ -11,7 +11,7 @@ title: Organizations
## What is an organization?
import OrgDescription from '../../concepts/zitadel/objects/_org_description.mdx';
import OrgDescription from '../../concepts/structure/_org_description.mdx';
import Column from '../../../src/components/column';
<OrgDescription name="OrgDescription" />

View File

@ -11,7 +11,7 @@ title: Projects
## What is a project?
import ProjectDescription from '../../concepts/zitadel/objects/_project_description.mdx';
import ProjectDescription from '../../concepts/structure/_project_description.mdx';
<ProjectDescription name="ProjectDescription" />
@ -57,7 +57,7 @@ Now create another project (eg. “My second project”) and verify that there a
## What is a granted project?
import GrantedProjectDescription from '../../concepts/zitadel/objects/_granted_project_description.mdx';
import GrantedProjectDescription from '../../concepts/structure/_granted_project_description.mdx';
<GrantedProjectDescription name="GrantedProjectDescription" />

View File

@ -2,8 +2,8 @@
title: Overview
---
import {ListElement, ListWrapper, ICONTYPE} from '../../src/components/list';
import Column from '../../src/components/column';
import { ListElement, ListWrapper, ICONTYPE } from "../../src/components/list";
import Column from "../../src/components/column";
With our guides you will learn everything you need to know about specific topics. You get step-by-step instructions for certain tasks and have a knowledge check at the end.
@ -13,22 +13,85 @@ When you are familiar with the ZITADEL usage, you can choose to stay on [zitadel
<Column>
<ListWrapper title="Get to know ZITADEL">
<ListElement link="/docs/guides/basics/get-started" type={ICONTYPE.START} title="Get started" description="Try out zitadel.ch" />
<ListElement link="/docs/guides/basics/organizations" type={ICONTYPE.START} title="Organizations" description="Learn how ZITADEL ist organized" />
<ListElement link="/docs/guides/basics/projects" type={ICONTYPE.START} title="Projects" description="Understand projects and grants" />
<ListElement
link="/docs/guides/basics/get-started"
type={ICONTYPE.START}
title="Get started"
description="Try out zitadel.ch"
/>
<ListElement
link="/docs/guides/basics/organizations"
type={ICONTYPE.START}
title="Organizations"
description="Learn how ZITADEL ist organized"
/>
<ListElement
link="/docs/guides/basics/projects"
type={ICONTYPE.START}
title="Projects"
description="Understand projects and grants"
/>
</ListWrapper>
<ListWrapper title="Authentication">
<ListElement link="/docs/guides/authentication/login-users" type={ICONTYPE.LOGIN} title="Login users" description="Authenticate users in ZITADEL" />
<ListElement link="/docs/guides/authentication/identity-brokering" type={ICONTYPE.LOGIN} title="Identity Brokering" description="Identity Brokering and Federated Identities" />
<ListElement
link="/docs/guides/authentication/login-users"
type={ICONTYPE.LOGIN}
title="Login users"
description="Authenticate users in ZITADEL"
/>
<ListElement
link="/docs/guides/authentication/identity-brokering"
type={ICONTYPE.LOGIN}
title="Identity Brokering"
description="Identity Brokering and Federated Identities"
/>
</ListWrapper>
<ListWrapper title="APIs">
<ListElement link="/docs/guides/api/access-zitadel-apis" type={ICONTYPE.APIS} title="APIs" description="Authorize Service Users to access ZITADEL APIs" />
<ListElement
link="/docs/guides/api/access-zitadel-apis"
type={ICONTYPE.APIS}
title="APIs"
description="Authorize Service Users to access ZITADEL APIs"
/>
</ListWrapper>
<ListWrapper title="Customization">
<ListElement link="/docs/guides/customization/branding" type={ICONTYPE.PRIVATELABELING} title="Private Labeling" description="Customize your organization to your brand" />
<ListElement link="/docs/guides/customization/texts" type={ICONTYPE.TEXTS} title="Texts" description="Login interface texts and notification texts" />
<ListElement
link="/docs/guides/customization/branding"
type={ICONTYPE.PRIVATELABELING}
title="Private Labeling"
description="Customize your organization to your brand"
/>
<ListElement
link="/docs/guides/customization/texts"
type={ICONTYPE.TEXTS}
title="Texts"
description="Login interface texts and notification texts"
/>
</ListWrapper>
<ListWrapper title="Solution Scenarios">
<ListElement
link="./solution-scenarios/b2c"
iconClasses="las la-paragraph"
roundClasses="rounded rounded-service"
label="B2C"
title="Business to Consumer"
description=""
/>
<ListElement
link="./solution-scenarios/b2b"
iconClasses="las la-paragraph"
roundClasses="rounded rounded-login"
label="B2B"
title="Business to Business"
description=""
/>
</ListWrapper>
<ListWrapper title="Installation">
<ListElement link="/docs/guides/installation/shared-cloud" type={ICONTYPE.SYSTEM} title="Managed" description="Shared ZITADEL Cloud or Dedicated Instance" />
<ListElement
link="/docs/guides/installation/shared-cloud"
type={ICONTYPE.SYSTEM}
title="Managed"
description="Shared ZITADEL Cloud or Dedicated Instance"
/>
</ListWrapper>
</Column>

View File

@ -0,0 +1,85 @@
---
title: B2B
---
import { B2B } from '../../../src/components/b2b';
## Business to Business
B2B describes the situation where an organization interacts with other organizations.
This **multiple organization architecture** usually adds some form of complexity to an Identity and Access Management System.
In ZITADEL a B2B organization represents a business partner or partner who typically has its own branding and has different access settings like an additional federated login for its users.
B2B can be a simple scenario where an organization only shares one of its projects with another organization or have a more complex case where an organization is offering a portal application to all its partners with included (self)administration.
<!-- This guide describes an application -->
## Sample scenario
Octagon is a fictitious company which is used throughout this guide to explain the details and key concepts of such a B2B scenario.
Octagon tries to solve multiple tasks in the banking field. Its portfolio includes several applications for their employees, customers, and partners. Some of which are web-based, some of which are used by machine users only.
### Portal Application
Octagon has a **Portal application** where its employees can access their account and list all applications they are allowed to use.
Employees work for a department within Octagon or for Octagon itself.
Some of the users have enhanced features because they supervise certain teams. Those can onboard new employees and manage their roles and features.
Target groups of the application can be split into:
- **Employees:** users who are using the application as a starting point for their work.
- **Supervisors:** users who are mainly using the application to manage users and their access of their department.
- **Administrators:** this users are able to grant additional organizations or departments and elect supervisors.
### Planning considerations
In order to define the need of the **Portal Application** some planning considerations about organizations have to be made:
- **Login and Access:** Does a user have a preset organization to login? Does the application show the default login page or does each organization use its own branding?
- **Organizations:** Does a user have access in multiple organizations? Is a user required to use a different federated login for those organizations?
- **Roles** Does the application need users to have specific roles assigned within their organizations? Which roles are needed to enable certain features of the application?
### Login
You can decide whether a organization is preselected for the login or if the user is redirected to the default login screen. You can send the user to a specific organization by defining the organization in a custom scope. (primary domain)
Settings to the branding or the login options of the organization can be made from the organization section in [Console](https://console.zitadel.ch/org).
The behaviour of the login branding can be set in your projects detail page. You can choose the branding of the selected organization, the user resource owner, or the projects resource owner.
### Organizations
Generally a user belongs to and is managed by one organization, however the user can receive authorizations from multiple other organizations (delegated authorizations). Anyways, a user should be able to use the same identity to switch between organizations.
If this feature is not desired, a separate user for each organization should be created.
Adding a user from a different organization to the audience of a project can be as easy as adding a new user authorization (user grant). A user grant combines a user from any organization with a project and 0-N roles.
In our sample scenario, we assume to have the following users:
- **Dimitri:** a team leader who is employed by Pentagon, an Octagon department. Dimitri uses his Microsoft Account in combination with his one time password to access the portal. Pentagon therefore has set up Microsoft as Identity Provider. Pentagon also requires its users to secure their accounts with additional factors.
- **Michael:** a trainee of Pentagon only using the portal to access his workspace apps. Michael uses his Google Account in combination with his laptops fingerprint.
- **Bill:** is employed at Octagon as Administrator of the Portal Application. Bill also uses a Microsoft Account in combination with a Security Key to secure his account.
After having determined the constellation of the organizations and its users, all the necessary data (Portal project with roles and app, users, login requirements, identity providers, branding) should be set up in [Console](https://console.zitadel.ch/org).
A B2B sample application for NextJS can be found in our [Example Repo](https://github.com/caos/zitadel-examples).
To allow another organization to use a project, a project grant has to be created. Upon creation, roles for a grant can be limited to a subset of the total project roles.
In our scenario, Octagon creates a project grant for Pentagon. Pentagon is limited to use `writer` and `reader` role. The `admin` role is reserved for the Octagon organization itself.
<B2B></B2B>
### Roles
In this scenario, Dimitri and Michael share the same organization Pentagon, where as Bill belongs to Octagon. Octagon is owner of the Portal project with its Web App, having Bill configured as user grant with `admin` role. Dimitri owns the `writer` role, whereas Michael only is `reader`.
> Note: Roles are meant for internal business logic and therefore need to be validated separately, none of the users described are allowed to create user grants, at least if they do not own a ZITADEL manager role.
If you made a dashboard where some users are able to create user grants, the Management API to do such operations should be triggered with the personal access token of the users, not with a token of a machine user, to create a meaningful audit log.
If you had such a use case, ZITADEL manager roles must be assigned to those users.
### Noteworthy
Due to the fact that ZITADEL includes unlimited users, projects, and applications and comes with all security features in the FREE tier, ZITADEL can be considered a great alternative to other SaaS IAM systems such as Auth0 or Okta.
In such a case with this high potential of scalability where user counts can grow explosively, ZITADEL does not become the bottleneck and therefore is the valid choice. You can learn more on ZITADELs benefits and the pricing [here](https://zitadel.ch/pricing).
### Learn more
- [Creating an organization](../basics/organizations#exercise---create-a-new-organization)
- [Organization Branding](../customization/branding)
- [Authorization](../authorization/oauth-recommended-flows)

View File

@ -0,0 +1,107 @@
---
title: B2C
---
import Column from "../../../src/components/column";
## Business to Consumer
Users in general come with different needs. You may have end users, employees, or even customers from other parties (B2B).
This groups of users usually don't share the same intentions and use applications differently.
When planning your applications, investing time in researching your apps architecture is vital for later feature upgrades and enhancements as those changes come in with heftier price points if you have to make bigger changes.
This guide introduces you to the grouping and structuring of ZITADEL projects which forms the base for all projects. This can be used as a quick start to the [B2B scenario](./b2b), which is merely focused on planning considerations if you are having projects with multiple organizations.
The journey of this guide starts with creating an Organization, the outermost layer of ZITADEL, as it is the vessel for projects, roles, applications and users.
Creation can be done from [ZITADEL Console](https://console.zitadel.ch/org/create). You can choose your current account for the organization owner or create a new one.
Depending on your Software Development Life Cycle (SDLC) you can create multiple organizations or projects to keep your applications environments seperated.
### Custom domain
Right after org creation you'll be greeted with the domain section of your organization. ZITADEL automatically creates a custom domain of the form `[orgname].zitadel.ch`, but you can set your own by saving a verification file on the specified location.
We recommend that you create your domains early as they create a sense of confidence and trust for your application and changes later on might create additional migration effort.
You can read more about how ZITADEL handles usernames [here](../basics/organizations#how-zitadel-handles-usernames).
### Data Provisioning
ZITADEL gives you a basic storage for users and manages phone and email addresses. It also allows you to store your own application data such as preferences or external identifiers to the metadata of a user.
If you are migrating an existing project and you already have an external identity store you can consider bulk importing your user datasets.
Read our [Management API definitions](../../apis/proto/management#importhumanuser) for more info. If the users email is not verified or no password is set, a initialization mail will be send.
:::info
Requests to the management API are rate limited. Read our [Rate limit Policy](../../legal/rate-limit-policy) for more info.
:::
### User Authentication
User Authentication can be performed in multiple ways. Default method in ZITADEL is username and password with MFA enabled.
ZITADEL allows you to configure Multifactor- and Passwordless Authentication in order to enhance security for your users. All authentication methods are available from the FREE Tier.
To setup your organizations login policy, go to your organizations detail in [Console](https://console.zitadel.ch/org).
When planning your application consider the following questions about User Authentication:
- What are the methods to authenticate your users?
- Where will your users enter their credentials?
- Do you offer password authentication?
- What do you do to keep your users credentials safe?
- Do you offer Multifactor Authentication?
- Do you offer Login via Identity Provider?
- Which languages do you have to provide?
When looking at this questions, you may have to admit that building an Identity Management System is much more complex and complicated than you thought initially and implementing if yourself may be too much work.
Particularly because you should focus building your applications.
### Federation
ZITADEL supports signup with OIDC Identity providers as well as JWT Identity Providers. On signup, ZITADEL imports user information to the own profile.
//TODO extend this passage
### Hosted Login
ZITADEL offers a "secure by default approach" and comes with a Hosted Login which is a fixed endpoint for your users to authenticate.
It's safe and secure and comes with Multifactor, Federated Login and Passwordless capabilities.
OIDC (OpenID Connect) opens the doors to Single Sign On (SSO). Especially if you have more than one application, you may want a central and familiar authentication experience.
With SSO, ZITADEL provides a seamless experience across all your apps.
### Branding
<Column>
<div>
Branding and customization is a very important part of your application.
With ZITADEL you can modify colors, logos, icons as well as configure your typography styles, such that you can provide a consistent design throughout your applications.
In addition to visual modifications, you can edit notification texts for your users.
ZITADEL gives you handlebar similar templating for variables. Of course you can define texts for any language.
We'd appreciate if you could contribute to our repo with translations of your language. Read on how to contribute [here](../../guides/customization/texts).
> Note that your console design changes to your design too
</div>
<img src="/img/guides/branding.jpeg" alt="branding in console"/>
</Column>
### Projects and applications
As our Hosted Login is a separate authentication screen, you have to determine how you are directing your users from your applications.
ZITADEL's Applications live under ZITADEL's Projects. You may add multiple applications for your different client-types (Native, Web, User Agent, or API). When setting up your applications consider reading our guide about [Authentication Flows](../authentication/login-users).
### Access Control
By having authenticated a user you need to ensure users and services have access to your application and APIs. This process is called Access Control and comprises User Authentication, Authorization and Policy Enforcement.
Take the following considerations:
- Does your application call your own APIs?
- Does your application need to call third-party APIs?
- Do **you** offer an API for third-party applications?
The data required to check if a user has access to a certain API is stored within a user grant. This information typically is stored within roles or custom claims and can be accessed with an `access` or OIDC `id` token.
Read more about Authorization in our [Guide](../authorization/oauth-recommended-flows).
## Learn more
- [Creating an organization](../basics/organizations#exercise---create-a-new-organization)
- [Organization Branding](../customization/branding)
- [Authorization](../authorization/oauth-recommended-flows)

View File

@ -0,0 +1,34 @@
---
title: Introduction
---
import {
ListElement,
ListWrapper,
ICONTYPE,
} from "../../../src/components/list";
import Column from "../../../src/components/column";
## Solution Scenarios
Customers of an SaaS Identity and Access Management System usually have all distinct use cases and requirements.
This guide attempts to explain real-world implementations and break them down into **Solution Scenarios** which aim to help you getting started with ZITADEL.
<ListWrapper title="Solution Scenarios">
<ListElement
link="./b2c"
iconClasses="las la-paragraph"
roundClasses="rounded rounded-split"
label="B2C"
title="Business to Consumer"
description="Organizations with your SDLC, Domains, Authentication, Hosted Login"
/>
<ListElement
link="./b2b"
iconClasses="las la-paragraph"
roundClasses="rounded rounded-split"
label="B2B"
title="Business to Business"
description="Planning considerations, B2B Sample Case"
/>
</ListWrapper>

View File

@ -74,4 +74,4 @@ Performance SLO | up to [rate limits](https://docs.zitadel.ch/docs/legal/rate-li
### Backup
ZITADEL Cloud creates hourly backups. We do not guarantee recovery time objective. Recovery point objective is in the context of our [event-sourcing pattern](/docs/concepts/general/eventstore) not meaningful.
ZITADEL Cloud creates hourly backups. We do not guarantee recovery time objective. Recovery point objective is in the context of our [event-sourcing pattern](../concepts/eventstore) not meaningful.

View File

@ -1,288 +1,286 @@
module.exports = {
quickstarts: [
'quickstarts/introduction',
quickstarts: [
"quickstarts/introduction",
{
type: "category",
label: "Integrate ZITADEL Login in your App",
items: [
"quickstarts/login/angular",
"quickstarts/login/react",
"quickstarts/login/flutter",
"quickstarts/login/nextjs",
],
collapsed: false,
},
{
type: "category",
label: "Secure your API",
items: ["quickstarts/secure-api/go", "quickstarts/secure-api/dot-net"],
collapsed: false,
},
{
type: "category",
label: "Call the ZITADEL API",
items: [
"quickstarts/call-zitadel-api/go",
"quickstarts/call-zitadel-api/dot-net",
],
collapsed: false,
},
{
type: "category",
label: "Identity Aware Proxy",
items: ["quickstarts/identity-proxy/oauth2-proxy"],
collapsed: false,
},
],
guides: [
"guides/overview",
{
type: "category",
label: "Get to know ZITADEL",
collapsed: false,
items: [
"guides/basics/get-started",
"guides/basics/organizations",
"guides/basics/projects",
],
},
{
type: "category",
label: "Solution Scenarios",
collapsed: false,
items: [
"guides/solution-scenarios/introduction",
"guides/solution-scenarios/b2c",
"guides/solution-scenarios/b2b",
],
},
{
type: "category",
label: "Authentication",
collapsed: false,
items: [
"guides/authentication/login-users",
"guides/authentication/identity-brokering",
"guides/authentication/serviceusers",
],
},
{
type: "category",
label: "Authorization",
collapsed: false,
items: ["guides/authorization/oauth-recommended-flows"],
},
{
type: "category",
label: "API",
collapsed: false,
items: ["guides/api/access-zitadel-apis"],
},
{
type: "category",
label: "Customization",
collapsed: false,
items: ["guides/customization/branding", "guides/customization/texts"],
},
{
type: "category",
label: "Installation",
collapsed: true,
items: [
{
type: 'category',
label: 'Integrate ZITADEL Login in your App',
items: ['quickstarts/login/angular', 'quickstarts/login/react', 'quickstarts/login/flutter', 'quickstarts/login/nextjs'],
collapsed: false,
},
{
type: 'category',
label: 'Secure your API',
items: ['quickstarts/secure-api/go', 'quickstarts/secure-api/dot-net'],
collapsed: false,
},
{
type: 'category',
label: 'Call the ZITADEL API',
items: ['quickstarts/call-zitadel-api/go', 'quickstarts/call-zitadel-api/dot-net'],
collapsed: false,
},
{
type: 'category',
label: 'Identity Aware Proxy',
items: ['quickstarts/identity-proxy/oauth2-proxy'],
collapsed: false,
}
],
guides: [
'guides/overview',
{
type: 'category',
label: 'Get to know ZITADEL',
collapsed: false,
items: [
'guides/basics/get-started',
'guides/basics/organizations',
'guides/basics/projects',
],
},
{
type: 'category',
label: 'Authentication',
collapsed: false,
items: [
'guides/authentication/login-users',
'guides/authentication/identity-brokering',
'guides/authentication/serviceusers',
],
},
{
type: 'category',
label: 'Authorization',
collapsed: false,
items: [
'guides/authorization/oauth-recommended-flows',
],
},
{
type: 'category',
label: 'API',
collapsed: false,
items: [
'guides/api/access-zitadel-apis'
],
},
{
type: 'category',
label: 'Customization',
collapsed: false,
items: [
'guides/customization/branding',
'guides/customization/texts',
],
},
{
type: 'category',
label: 'Installation',
collapsed: false,
items: [
{
type: 'category',
label: 'CAOS Managed',
collapsed: true,
items: [
'guides/installation/shared-cloud',
'guides/installation/managed-dedicated-instance'
],
},
{
type: 'category',
label: 'CAOS Service Packages',
collapsed: true,
items: [
'guides/installation/setup',
'guides/installation/setup-orbos',
'guides/installation/checkup'
],
},
{
type: 'category',
label: 'Self Managed',
collapsed: true,
items: [
'guides/installation/crd',
'guides/installation/gitops',
'guides/installation/orbos'
],
},
],
},
{
type: 'category',
label: 'Trainings',
collapsed: false,
items: [
'guides/trainings/introduction',
{
type: 'category',
label: 'Support Service',
collapsed: true,
items: [
'guides/trainings/supportservice/operations',
'guides/trainings/supportservice/application',
'guides/trainings/supportservice/recurring',
],
},
],
}
],
apis: [
'apis/introduction',
{
type: 'category',
label: 'API Definition',
collapsed: false,
items: [
{
type: 'category',
label: 'Proto',
collapsed: true,
items: [
'apis/proto/auth',
'apis/proto/management',
'apis/proto/admin',
'apis/proto/org',
'apis/proto/user',
'apis/proto/app',
'apis/proto/policy',
'apis/proto/auth_n_key',
'apis/proto/change',
'apis/proto/idp',
'apis/proto/member',
'apis/proto/metadata',
'apis/proto/message',
'apis/proto/text',
'apis/proto/object',
'apis/proto/options'
],
},
{
type: 'category',
label: 'Assets API',
collapsed: true,
items: [
'apis/assets/assets',
],
},
],
},
{
type: 'category',
label: 'OpenID Connect & OAuth',
collapsed: false,
items: [
'apis/openidoauth/endpoints',
'apis/openidoauth/scopes',
'apis/openidoauth/claims',
'apis/openidoauth/authn-methods',
'apis/openidoauth/grant-types'
],
},
{
type: 'category',
label: 'Rate Limits',
collapsed: false,
type: "category",
label: "CAOS Managed",
collapsed: true,
items: [
'legal/rate-limit-policy',
'apis/ratelimits/accounts',
'apis/ratelimits/api',
"guides/installation/shared-cloud",
"guides/installation/managed-dedicated-instance",
],
},
],
concepts: [
'concepts/introduction',
{
type: 'category',
label: 'ZITADEL',
collapsed: false,
items: [
'concepts/zitadel/architecture',
{
type: 'category',
label: "Object Overview",
collapsed: false,
items: [
'concepts/zitadel/objects/overview',
'concepts/zitadel/objects/organizations',
'concepts/zitadel/objects/policies',
'concepts/zitadel/objects/projects',
'concepts/zitadel/objects/applications',
'concepts/zitadel/objects/granted_projects',
'concepts/zitadel/objects/users',
'concepts/zitadel/objects/managers',
],
},
],
}, {
type: 'category',
label: 'General',
collapsed: false,
items: [
'concepts/general/principles',
'concepts/general/eventstore',
],
type: "category",
label: "CAOS Service Packages",
collapsed: true,
items: [
"guides/installation/setup",
"guides/installation/setup-orbos",
"guides/installation/checkup",
],
},
{
type: 'category',
label: 'Use Cases',
collapsed: false,
items: [
'concepts/usecases/saas'
],
type: "category",
label: "Self Managed",
collapsed: true,
items: [
"guides/installation/crd",
"guides/installation/gitops",
"guides/installation/orbos",
],
},
],
manuals: [
'manuals/introduction',
],
},
{
type: "category",
label: "Trainings",
collapsed: true,
items: [
"guides/trainings/introduction",
{
type: 'category',
label: 'User',
items: ['manuals/user-register', 'manuals/user-login', 'manuals/user-passwordless', 'manuals/user-password', 'manuals/user-factors', 'manuals/user-email', 'manuals/user-phone', 'manuals/user-social-login',],
collapsed: false,
type: "category",
label: "Support Service",
collapsed: true,
items: [
"guides/trainings/supportservice/operations",
"guides/trainings/supportservice/application",
"guides/trainings/supportservice/recurring",
],
},
'manuals/troubleshooting'
],
legal: [
'legal/introduction',
'legal/terms-of-service',
'legal/data-processing-agreement',
],
},
],
apis: [
"apis/introduction",
{
type: "category",
label: "API Definition",
collapsed: false,
items: [
{
type: 'category',
label: 'Service Descriptions',
collapsed: false,
items: [
'legal/service-level-description',
'legal/support-services',
],
type: "category",
label: "Proto",
collapsed: true,
items: [
"apis/proto/auth",
"apis/proto/management",
"apis/proto/admin",
"apis/proto/org",
"apis/proto/user",
"apis/proto/app",
"apis/proto/policy",
"apis/proto/auth_n_key",
"apis/proto/change",
"apis/proto/idp",
"apis/proto/member",
"apis/proto/metadata",
"apis/proto/message",
"apis/proto/text",
"apis/proto/object",
"apis/proto/options",
],
},
{
type: 'category',
label: 'Dedicated Instance',
collapsed: false,
items: [
'legal/terms-of-service-dedicated',
'legal/dedicated-instance-annex',
],
type: "category",
label: "Assets API",
collapsed: true,
items: ["apis/assets/assets"],
},
{
type: 'category',
label: 'Support Program',
collapsed: false,
items: [
'legal/terms-support-service'
],
},
{
type: 'category',
label: 'Policies',
collapsed: false,
items: [
'legal/privacy-policy',
'legal/acceptable-use-policy',
'legal/rate-limit-policy'
],
}
],
],
},
{
type: "category",
label: "OpenID Connect & OAuth",
collapsed: false,
items: [
"apis/openidoauth/endpoints",
"apis/openidoauth/scopes",
"apis/openidoauth/claims",
"apis/openidoauth/authn-methods",
"apis/openidoauth/grant-types",
],
},
{
type: "category",
label: "Rate Limits",
collapsed: false,
items: [
"legal/rate-limit-policy",
"apis/ratelimits/accounts",
"apis/ratelimits/api",
],
},
],
concepts: [
"concepts/introduction",
"concepts/principles",
"concepts/eventstore",
"concepts/architecture",
{
type: "category",
label: "Structure",
collapsed: true,
items: [
"concepts/structure/overview",
"concepts/structure/organizations",
"concepts/structure/policies",
"concepts/structure/projects",
"concepts/structure/applications",
"concepts/structure/granted_projects",
"concepts/structure/users",
"concepts/structure/managers",
],
},
{
type: "category",
label: "Use Cases",
collapsed: false,
items: ["concepts/usecases/saas"],
},
],
manuals: [
"manuals/introduction",
{
type: "category",
label: "User",
items: [
"manuals/user-register",
"manuals/user-login",
"manuals/user-passwordless",
"manuals/user-password",
"manuals/user-factors",
"manuals/user-email",
"manuals/user-phone",
"manuals/user-social-login",
],
collapsed: false,
},
"manuals/troubleshooting",
],
legal: [
"legal/introduction",
"legal/terms-of-service",
"legal/data-processing-agreement",
{
type: "category",
label: "Service Descriptions",
collapsed: false,
items: ["legal/service-level-description", "legal/support-services"],
},
{
type: "category",
label: "Dedicated Instance",
collapsed: false,
items: [
"legal/terms-of-service-dedicated",
"legal/dedicated-instance-annex",
],
},
{
type: "category",
label: "Support Program",
collapsed: false,
items: ["legal/terms-support-service"],
},
{
type: "category",
label: "Policies",
collapsed: false,
items: [
"legal/privacy-policy",
"legal/acceptable-use-policy",
"legal/rate-limit-policy",
],
},
],
};

View File

@ -0,0 +1,47 @@
import React from 'react';
export function B2B() {
return (
<div className="flexrowbetween">
<div className="b2borg">
<span>Octagon <small>(owner)</small></span>
<div className="b2bproject">
<span>Portal Project</span>
<div className="b2bapp">
<strong>WEBAPP</strong>
</div>
<span className="b2bprojectrole">reader, writer, admin</span>
</div>
<div className="b2buser">
Bill <small>(admin)</small>
</div>
</div>
<svg className="arrowright" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path></svg>
<div className="b2borg">
<span>Pentagon</span>
<div className="b2bproject">
<span>Portal Project <small>(grant)</small></span>
<div className="b2bapp">
<strong>WEBAPP</strong>
</div>
<span className="b2bprojectrole">reader, writer</span>
</div>
<div className="b2buser">
Dimitri <small>(writer)</small>
</div>
<div className="b2buser">
Michael <small>(reader)</small>
</div>
</div>
</div>
);
}

View File

@ -6,6 +6,12 @@ export const ICONTYPE = {
START: <div className="rounded rounded-start">
<i className={`las la-play-circle`}></i>
</div>,
TASKS: <div className="rounded rounded-start">
<i className={`las la-tasks`}></i>
</div>,
ARCHITECTURE: <div className="rounded rounded-architecture">
<i className={`las la-sitemap`}></i>
</div>,
LOGIN: <div className="rounded rounded-login">
<i className={`las la-sign-in-alt`}></i>
</div>,
@ -21,6 +27,15 @@ export const ICONTYPE = {
SERVICE: <div className="rounded rounded-service">
<i className={`las la-concierge-bell`}></i>
</div>,
STORAGE: <div className="rounded rounded-storage">
<i className={`las la-database`}></i>
</div>,
FOLDER: <div className="rounded rounded-storage">
<i className={`las la-folder`}></i>
</div>,
FILE: <div className="rounded rounded-storage">
<i className={`las la-file-alt`}></i>
</div>,
SYSTEM: <div className="rounded rounded-system">
<i className={`las la-server`}></i>
</div>,
@ -58,11 +73,13 @@ export const ICONTYPE = {
</div>,
};
export function ListElement({ link, iconClasses, type, title, description}) {
export function ListElement({ link, iconClasses,roundClasses, label, type, title, description}) {
return (
<a className={styles.listelement} href={link}>
{type ? type :
iconClasses && <div><i className={`${styles.icon} ${iconClasses}`}></i></div>
iconClasses && <div className={roundClasses}>
{ label ? <span className={styles.listlabel}>{label}</span>: <i className={`${iconClasses}`}></i> }
</div>
}
<div>
<h3>{title}</h3>
@ -75,8 +92,19 @@ export function ListElement({ link, iconClasses, type, title, description}) {
export function ListWrapper({children, title, columns}) {
return (
<div className={styles.listWrapper}>
<span className={styles.listWrapperTitle}>{title}</span>
{title && <span className={styles.listWrapperTitle}>{title}</span>}
{children}
</div>
)
}
export function HomeListWrapper({children, image}) {
return (
<div className={styles.homerow}>
{image}
<div className={styles.homecontent}>
{children}
</div>
</div>
)
}

View File

@ -58,6 +58,12 @@
--apimgmtbackground: linear-gradient(40deg, #c6d7f3 30%, #c7c6e3);
--apiadminbackground: linear-gradient(40deg, #c192c790, #c192c790);
--apiassetbackground: linear-gradient(40deg, #e4eaf1, #eef2f9);
--overlaycolor: #6c90b420;
--ifm-hero-text-color: #ffffff;
}
.get-started {
border-radius: 50vw;
}
.apicard-right {
@ -211,6 +217,12 @@ h2 {
--apimgmtbackground: linear-gradient(40deg, #595d8090 30%, #595d8090);
--apiadminbackground: linear-gradient(40deg, #6a506e90, #6a506e90);
--apiassetbackground: linear-gradient(40deg, #3c4257, #3c4257);
--overlaycolor: #ffffff15;
--ifm-hero-text-color: #023c2a;
}
.get-started:hover {
color: #ffffff !important;
}
.menu li li a {
@ -234,6 +246,8 @@ main .container img {
padding: .5rem;
margin-right: 1rem;
border-radius: 50%;
width: 40px;
height: 40px;
}
.rounded svg {
@ -262,12 +276,18 @@ main .container img {
.rounded-privatelabel,
.rounded-phone,
.rounded-email,
.rounded-storage,
.rounded-service {
background: linear-gradient(40deg, #3b82f6 30%, #4f46e5);
}
.rounded-split {
background: linear-gradient(40deg, #3b82f6, #4f46e5);
}
.rounded-texts,
.rounded-help {
.rounded-help,
.rounded-architecture {
background: linear-gradient(40deg, #dc2626 30%, #db2777);
}
@ -284,6 +304,10 @@ main .container img {
padding: 0 var(--ifm-pre-padding);
}
.hero__title {
color: white;
}
.get-started {
border: 2px solid var(--get-started);
background-color: var(--get-started);
@ -295,6 +319,10 @@ main .container img {
color: var(--ifm-hero-text-color);
}
.docs-link {
margin-bottom: 2rem;
}
.docs-link a {
text-decoration: none;
color: inherit;
@ -306,4 +334,51 @@ main .container img {
.docs-link img {
margin: 40px;
}
.b2borg,
.b2bproject,
.b2bapp,
.b2buser {
border-radius: 1rem;
background: var(--overlaycolor);
padding: 1rem;
}
.b2buser {
margin-top: 1rem;
}
.b2borg span,
.b2bproject span,
.b2bapp span,
.b2buser span {
margin-left: 1rem;
margin-bottom: 1rem;
display: block;
}
.flexrowbetween {
display: flex;
justify-content: space-around;
margin: 2rem 0;
}
.arrowright {
height: 2rem;
width: auto;
align-self: center;
min-width: 2rem;
}
.b2bprojectrole {
margin: 1rem 0 0 1rem !important;
}
.footer__link-item {
font-size: 14px;
}
.footer__link-item svg {
margin-left: .5rem;
}

View File

@ -31,11 +31,15 @@
padding: .5rem 1rem .5rem .5rem;
}
.listlabel {
color: white;
}
.listWrapper {
display: flex;
flex-direction: column;
background: var(--list-background);
border-radius: .5rem;
border-radius: 1rem;
padding: 1rem;
}
@ -44,4 +48,18 @@
font-size: 16px;
margin-bottom: .5rem;
display: block;
}
.homerow {
display: flex;
flex-direction: row;
align-items: flex-start;
}
.homecontent {
flex: 1;
display: flex;
flex-direction: column;
align-items: stretch;
padding: 1rem 0;
}

View File

@ -6,98 +6,274 @@ import ThemedImage from '@theme/ThemedImage';
import clsx from 'clsx';
import React from 'react';
import Column from '../components/column';
import { HomeListWrapper, ICONTYPE, ListElement, ListWrapper } from '../components/list';
import styles from './styles.module.css';
const features = [
{
title: 'Guides',
darkImageUrl: 'img/index/Guides-dark.svg',
lightImageUrl: 'img/index/Guides-light.svg',
link: 'docs/guides/overview',
title: "Guides",
darkImageUrl: "img/index/Guides-dark.svg",
lightImageUrl: "img/index/Guides-light.svg",
link: "docs/guides/overview",
description: (
<>
Read our guides on how to manage your data and role associations in ZITADEL and on what we recommend.
Read our guides on how to manage your data and role associations in
ZITADEL and on what we recommend.
</>
),
content: (
<ListWrapper>
<Column>
<div>
<ListElement
link="docs/guides/basics/get-started"
type={ICONTYPE.START}
title="Get started"
description=""
/>
<ListElement
link="docs/guides/authentication/login-users"
type={ICONTYPE.LOGIN}
title="Authentication"
description=""
/>
<ListElement
link="docs/guides/authorization/oauth-recommended-flows"
type={ICONTYPE.LOGIN}
title="Authorization"
description=""
/>
<ListElement
link="docs/guides/api/access-zitadel-apis"
type={ICONTYPE.APIS}
title="Access APIs"
description=""
/>
</div>
<div>
<ListElement
link="docs/guides/solution-scenarios/introduction"
iconClasses="las la-paragraph"
roundClasses="rounded rounded-split"
label="B2C"
title="Solution Scenarios"
description=""
/>
<ListElement
link="docs/guides/customization/branding"
type={ICONTYPE.PRIVATELABELING}
title="Customization"
description=""
/>
<ListElement
link="docs/guides/installation/shared-cloud"
type={ICONTYPE.STORAGE}
title="Installation"
description=""
/>
<ListElement
link="docs/guides/trainings/introduction"
type={ICONTYPE.STORAGE}
title="Trainings"
description=""
/>
</div>
</Column>
</ListWrapper>
),
},
{
title: 'Quickstarts',
darkImageUrl: 'img/index/Quickstarts-dark.svg',
lightImageUrl: 'img/index/Quickstarts-light.svg',
link: 'docs/quickstarts/introduction',
title: "Quickstarts",
darkImageUrl: "img/index/Quickstarts-dark.svg",
lightImageUrl: "img/index/Quickstarts-light.svg",
link: "docs/quickstarts/introduction",
description: (
<>
Learn how to integrate your applications and build secure workflows and APIs with ZITADEL
</>
<>
Learn how to integrate your applications and build secure workflows and
APIs with ZITADEL
</>
),
content: (
<div className={styles.quickstartcontainer}>
<QuickstartLink
link="/docs/quickstarts/login/angular"
imageSource="/img/tech/angular.svg"
title="Angular"
description="Add the user login to your application and query some data from the userinfo endpoint"
/>
<QuickstartLink
link="/docs/quickstarts/login/react"
imageSource="/img/tech/react.png"
title="React"
description="Logs into your application and queries some data from the userinfo endpoint"
/>
<QuickstartLink
link="/docs/quickstarts/login/flutter"
imageSource="/img/tech/flutter.svg"
title="Flutter"
description="Mobile Application working for iOS and Android that authenticates your user."
/>
<QuickstartLink
link="/docs/quickstarts/login/nextjs"
imageSource="/img/tech/nextjslight.svg"
lightImageSource="/img/tech/nextjs.svg"
title="NextJS"
description="A simple application to log into your user account and query some data from User endpoint."
/>
</div>
),
},
{
title: 'APIs',
darkImageUrl: 'img/index/APIs-dark.svg',
lightImageUrl: 'img/index/APIs-light.svg',
link: '/docs/apis/introduction',
title: "APIs",
darkImageUrl: "img/index/APIs-dark.svg",
lightImageUrl: "img/index/APIs-light.svg",
link: "/docs/apis/introduction",
description: (
<>
Learn more about our APIs and how to integrate them in your apps.
</>
<>Learn more about our APIs and how to integrate them in your apps.</>
),
content: (
<div className={styles.apilinks}>
<ListWrapper>
<ListElement
link="./docs/apis/proto/auth"
type={ICONTYPE.APIS}
title="Proto Definitions"
description=""
/>
<ListElement
link="./docs/apis/openidoauth/endpoints"
type={ICONTYPE.APIS}
title="OpenID Connect and OAuth"
description="Scopes, Claims, Authentication Methods, Grant Types"
/>
</ListWrapper>
</div>
),
},
{
title: 'Concepts',
darkImageUrl: 'img/index/Concepts-dark.svg',
lightImageUrl: 'img/index/Concepts-light.svg',
link: 'docs/concepts/introduction',
title: "Concepts",
darkImageUrl: "img/index/Concepts-dark.svg",
lightImageUrl: "img/index/Concepts-light.svg",
link: "docs/concepts/introduction",
description: (
<>
Learn more about engineering and design principles, ZITADELs architecture and used technologies.
Learn more about engineering and design principles, ZITADELs
architecture and used technologies.
</>
),
content: (
<ListWrapper>
<ListElement
link="./docs/concepts/principles"
type={ICONTYPE.TASKS}
title="Principles"
description="Design and engineering principles"
/>
<ListElement
link="./docs/concepts/eventstore"
type={ICONTYPE.STORAGE}
title="Eventstore"
description="Learn how ZITADEL stores data"
/>
<ListElement
link="./docs/concepts/architecture"
type={ICONTYPE.ARCHITECTURE}
title="Architecture"
description="Sotware-, Cluster- and Multi Cluster Architecture"
/>
<ListElement
link="./docs/concepts/structure/overview"
type={ICONTYPE.ARCHITECTURE}
title="Structure"
description="Object structure of ZITADEL"
/>
</ListWrapper>
),
},
];
function Feature({darkImageUrl, lightImageUrl, title, description, link}) {
function QuickstartLink({ link, title, imageSource, lightImageSource }) {
return (
<Link href={link} className={clsx("", styles.quickstart)}>
{/* <img className={styles.quickstartlinkimg} src={imageSource} alt={`${title}`}/> */}
<ThemedImage
className={styles.quickstartlinkimg}
alt={title}
sources={{
light: lightImageSource ? lightImageSource : imageSource,
dark: imageSource,
}}
/>
<p>{title}</p>
</Link>
);
}
function Feature({
darkImageUrl,
lightImageUrl,
title,
description,
link,
content,
}) {
const darkImgUrl = useBaseUrl(darkImageUrl);
const lightImgUrl = useBaseUrl(lightImageUrl);
const themedImage = (
<ThemedImage
className={styles.featureImage}
alt={title}
sources={{
light: lightImgUrl,
dark: darkImgUrl,
}}
/>
);
return (
<div className={clsx('col col--4 docs-link', styles.feature)}>
<Link to={useBaseUrl(link)}>
{darkImgUrl && lightImgUrl && (
<div className="text--center">
<ThemedImage
className={styles.featureImage}
alt={title}
sources={{
light: lightImgUrl,
dark: darkImgUrl,
}}
/>
</div>
)}
<h3 className="text--center">{title}</h3>
<p className="text--center">{description}</p>
</Link>
<div className={clsx("col col--6 docs-link", styles.feature)}>
{darkImgUrl && lightImgUrl && (
<div className="">
<HomeListWrapper image={themedImage}>
<Link to={useBaseUrl(link)}>
<h3 className={styles.homelink}>
{title}
<i
className={clsx("las la-angle-right", styles.homelinkicon)}
></i>
</h3>
</Link>
<p className="">{description}</p>
{content}
</HomeListWrapper>
</div>
)}
</div>
);
}
export default function Home() {
const context = useDocusaurusContext();
const {siteConfig = {}} = context;
const { siteConfig = {} } = context;
return (
<Layout
title={`${siteConfig.title}`}
description="This site bundles ZITADELs Documentations">
<header className={clsx('hero', styles.heroBanner)}>
description="This site bundles ZITADELs Documentations"
>
<header className={clsx("hero", styles.heroBanner)}>
<div className="container">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className={clsx(
'button button--outline button--lg get-started',
styles.getStarted,
"button button--outline button--lg get-started",
styles.getStarted
)}
to={useBaseUrl('docs/guides/basics/get-started')}>
to={useBaseUrl("docs/guides/basics/get-started")}
>
Get Started
</Link>
</div>

View File

@ -32,6 +32,72 @@
}
.featureImage {
height: 200px;
width: 200px;
height: 70px;
width: 70px;
margin: 1rem 1rem 1rem 0 !important;
}
.homelink:hover,
.homelink:hover i {
color: var(--ifm-link-color);
}
.homelinkicon {
font-size: 1.2rem;
}
.quickstartcontainer {
padding: 0;
border-radius: 1rem;
display: flex;
flex-wrap: wrap;
flex-direction: row;
margin: -0.5rem;
}
.quickstart {
flex: 1;
padding: 1rem;
margin: 0.5rem;
min-width: 200px;
display: flex;
align-items: center;
background: var(--list-background);
border-radius: 1rem;
}
.quickstart p {
margin: 0;
font-size: 1.5rem;
}
.quickstartlinkimg {
height: 80px;
width: 80px;
margin: 1rem 1rem 1rem 0 !important;
border-radius: 1rem;
background-size: cover;
object-fit: contain;
background-position: center;
}
@media screen and (max-width: 600px) {
.quickstartcontainer {
flex-direction: column;
}
.quickstartlinkimg {
height: 60px;
width: 60px;
}
.featureImage {
height: 50px;
width: 50px;
}
}
.apilinks h2 {
font-size: 1rem;
}

BIN
docs/static/img/guides/branding.jpeg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

18
docs/static/img/tech/nextjslight.svg vendored Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="207px" height="124px" viewBox="0 0 207 124" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
<title>next-black</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Black-Next.js" transform="translate(-247.000000, -138.000000)" fill="#ffffff" fill-rule="nonzero">
<g id="next-black" transform="translate(247.000000, 138.000000)">
<g id="EXT-+-Type-something">
<path d="M48.9421964,32.6320058 L87.9011585,32.6320058 L87.9011585,35.7136421 L52.5134345,35.7136421 L52.5134345,58.9070103 L85.7908813,58.9070103 L85.7908813,61.9886466 L52.5134345,61.9886466 L52.5134345,87.4526941 L88.306981,87.4526941 L88.306981,90.5343303 L48.9421964,90.5343303 L48.9421964,32.6320058 Z M91.3912326,32.6320058 L95.5306221,32.6320058 L113.8738,58.0960534 L132.622801,32.6320058 L158.124498,0.286809811 L116.22757,60.7722112 L137.817329,90.5343303 L133.51561,90.5343303 L113.8738,63.4483691 L94.1508254,90.5343303 L89.9302715,90.5343303 L111.682358,60.7722112 L91.3912326,32.6320058 Z M139.359455,35.713642 L139.359455,32.6320058 L183.756439,32.6320058 L183.756439,35.7136421 L163.302983,35.7136421 L163.302983,90.5343303 L159.731745,90.5343303 L159.731745,35.7136421 L139.359455,35.713642 Z" id="EXT"></path>
<polygon id="Type-something" points="0.202923647 32.6320058 4.66697141 32.6320058 66.2235778 124.303087 40.785176 90.5343303 3.93649086 37.0111732 3.77416185 90.5343303 0.202923647 90.5343303"></polygon>
</g>
<path d="M183.396622,86.5227221 C184.134938,86.5227221 184.673474,85.9601075 184.673474,85.233037 C184.673474,84.5059658 184.134938,83.9433513 183.396622,83.9433513 C182.666993,83.9433513 182.11977,84.5059658 182.11977,85.233037 C182.11977,85.9601075 182.666993,86.5227221 183.396622,86.5227221 Z M186.905793,83.1297235 C186.905793,85.2763149 188.460599,86.678523 190.727662,86.678523 C193.142388,86.678523 194.601647,85.233037 194.601647,82.7229099 L194.601647,73.8855335 L192.655968,73.8855335 L192.655968,82.7142542 C192.655968,84.1078073 191.952397,84.8521899 190.710289,84.8521899 C189.598473,84.8521899 188.842785,84.1597409 188.816727,83.1297235 L186.905793,83.1297235 Z M197.146664,83.0172011 C197.285642,85.2503478 199.153145,86.678523 201.932686,86.678523 C204.903321,86.678523 206.762139,85.1811034 206.762139,82.792155 C206.762139,80.9138876 205.702439,79.8752151 203.131364,79.2779777 L201.750279,78.9404092 C200.117298,78.5595622 199.457158,78.0488813 199.457158,77.1573541 C199.457158,76.0321243 200.482113,75.296398 202.019547,75.296398 C203.478806,75.296398 204.48639,76.0148135 204.668797,77.1660091 L206.562359,77.1660091 C206.44944,75.0626962 204.590622,73.5825873 202.045605,73.5825873 C199.309495,73.5825873 197.48542,75.0626962 197.48542,77.2871878 C197.48542,79.1221767 198.519063,80.2127835 200.786126,80.7407758 L202.401734,81.1302779 C204.060773,81.5197807 204.790402,82.091051 204.790402,83.0431676 C204.790402,84.1510859 203.643842,84.9560573 202.08035,84.9560573 C200.403939,84.9560573 199.240006,84.2030196 199.074971,83.0172011 L197.146664,83.0172011 Z" id=".JS"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB