docs: update to current state (#1556)
* fix: site folder * fix: site folder
@ -6,7 +6,7 @@ WORKDIR /site
|
||||
|
||||
RUN npm install
|
||||
|
||||
RUN npx sapper export --legacy
|
||||
RUN npm run export
|
||||
|
||||
FROM scratch as final
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
---
|
||||
title: Overview
|
||||
---
|
||||
|
||||
This documentation describes the structure of ZITADEL, its role system and in parallel the use of [console](https://console.zitadel.ch), our administration UI for ZITADEL.
|
||||
|
||||
> All documentations are under active work and subject to change soon!
|
||||
|
||||
### Features
|
||||
|
||||
- Single-Sign On (SSO) and Single-Log Out (SLO) for
|
||||
- Web applications
|
||||
- Server Renderer
|
||||
- Single Page
|
||||
- Native Clients
|
||||
- Windows
|
||||
- MacOS
|
||||
- Linux
|
||||
- Mobile Clients
|
||||
- Android
|
||||
- iOS / iPadOS
|
||||
- Bearer Tokens (JWT and opaque) to use with APIs
|
||||
- REST
|
||||
- GRPC
|
||||
- GraphQL
|
||||
- Role Based Access Control (RBAC) with delegation to let organisations manage authorisations on their own
|
||||
- OpenID Connect 1.0 (OIDC) support
|
||||
- OAuth 2.0 support
|
||||
- Identity Brokering
|
||||
- Federation with OIDC and OAuth 2.0 Identity Providers
|
||||
- Social Login
|
||||
- Management Console for central management of your data
|
||||
- Multi-factor Authentication
|
||||
- Support for TOTP/HOTP with any app, like authy, google authenticator, ...
|
||||
- U2F (CTAP1)
|
||||
- Passwordless Authentication
|
||||
- WebAuthN (FIDO2 / CTAP2)
|
||||
- User self-registration, recover password, email and phone verification, etc.
|
||||
- Organisation self-registration, domain verification, policy management
|
||||
- API's for easy integration in your application
|
||||
|
||||
### Concepts
|
||||
|
||||
With ZITADEL there are some key concepts some should be aware of before using it to secure your applications and services.
|
||||
You find these definitions in the "What is/are..." heading of each resource.
|
@ -1,71 +0,0 @@
|
||||
---
|
||||
title: Console
|
||||
---
|
||||
|
||||
### What is Console
|
||||
|
||||
Console is the ZITADEL Graphical User Interface.
|
||||
|
||||
ZITADEL Console can be reached at [console.zitadel.ch](https://console.zitadel.ch/).
|
||||
For dedicated ZITADEL instances this URL might be different, but in most cases should be something like `https://console.YOURDOMAIN.TLD`
|
||||
|
||||
#### ZITADEL Users
|
||||
|
||||
**Users** can manage some information on their own.
|
||||
|
||||
- profile information
|
||||
- credentials
|
||||
- external logins
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_user_entry.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_user_entry.png" itemprop="thumbnail" alt="User Entry" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">User Entry</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_user_personal_information.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_user_personal_information.png" itemprop="thumbnail" alt="User Personal Information" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">User Personal Information</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
#### ZITADEL Organisation Owners
|
||||
|
||||
Users who manage organisations (**organisation owners**) do this also with Console.
|
||||
|
||||
- Organisation settings (policies, domains, idps)
|
||||
- Manage users
|
||||
- Manage projects, clients and roles
|
||||
- Give access to users
|
||||
|
||||
#### ZITADEL Administrators
|
||||
|
||||
For the **IAM Administrators** there is also a section in Console solely intended to manage the system.
|
||||
|
||||
- Check failed events
|
||||
- Reset read models
|
||||
- Manage system settings and policies
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_admin_entry.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_admin_entry.png" itemprop="thumbnail" alt="Adminstrator Entry" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Adminstrator Entry</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_admin_system.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_admin_system.png" itemprop="thumbnail" alt="System Administration" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">System Administration</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
> ZITADEL does display a banner to warn the administrator that his account has elevated privileges!
|
||||
|
||||
### Technologies
|
||||
|
||||
Console is built with Angular and interfaces with ZITADEL by utilizing the GRPC APIs over GRPC-web.
|
@ -1,152 +0,0 @@
|
||||
---
|
||||
title: Organizations
|
||||
---
|
||||
|
||||
### What are organizations
|
||||
|
||||
Organizations are comparable to tenants of a system or OU's (organizational units) if we speak of a directory based system.
|
||||
ZITADEL is organized around the idea that
|
||||
* multiple organizations share the same [System](administrate#What_is_meant_by_system)
|
||||
* these organizations can grant each other rights to self-manage certain things (eg, delegating roles)
|
||||
* organizations are a vessels for [users](administrate#What_are_users) and [projects](administrate#What_are_projects)
|
||||
|
||||
#### Global organization
|
||||
|
||||
The global organization holds users that are not assigned to any other organization in the [System](administrate#What_is_meant_by_system). Thus ZITADEL provides a global organization for users who manage their accounts on their own.
|
||||
|
||||
<details open>
|
||||
<summary>
|
||||
Example
|
||||
</summary>
|
||||
Let's look at our example company `acme.ch`: Suppose ACME sells online-tickets for concert venues. ACME created an organization `iam` to manage their own enterprise users (employees) and projects to manage the provided services. They also created an organization `b2b-partner-1`, allowing the partner self-manage their access. A partner could be a concert venue, that can administrate the backend of the service (e.g. posting new concerts, setting up billing, ...), and you want to allow them to self-manage access of users (e.g. employees of the venue) to their backend. Lastly, the organization `global` holds all the b2c customers of `acme.ch` that registered to the service to buy concert tickets.
|
||||
</details>
|
||||
|
||||
### Create an organization without existing login
|
||||
|
||||
ZITADEL allows you to create a new organization without a pre-existing user. For [ZITADEL.ch](https://zitadel.ch) you can create a org by visiting the [Register organization](https://accounts.zitadel.ch/register/org)
|
||||
|
||||
> Screenshot here
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Dedicated Instance
|
||||
</summary>
|
||||
For dedicated ZITADEL instances this URL might be different, but in most cases should be something like https://accounts.YOURDOMAIN.TLD/register/org
|
||||
</details>
|
||||
|
||||
### Create an organization with existing login
|
||||
|
||||
You can simply create a new organization by visiting the [ZITADEL Console](https://console.zitadel.ch) and clicking "new organization" in the upper left corner.
|
||||
|
||||
> Screenshot here
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Dedicated Instance
|
||||
</summary>
|
||||
For dedicated ZITADEL instances this URL might be different, but in most cases should be something like `https://console.YOURDOMAIN.TLD`
|
||||
</details>
|
||||
|
||||
### Verify a domain name
|
||||
|
||||
Once you created your organization you will receive a generated domain name from ZITADEL for your organization. For example if you call your organization `ACME` you will receive `acme.zitadel.ch` as name. Furthermore the users you create will be suffixed with this domain name. To improve the user experience you can verify a domain name which you control. If you control acme.ch you can verify the ownership by DNS or HTTP challenge.
|
||||
After the domain is verified your users can use both domain names to log-in. The user "coyote" can now use "coyote@acme.zitadel.ch" and "coyote@acme.ch".
|
||||
An organization can have multiple domain names, but only one of it can be primary. The primary domain defines which login name ZITADEL displays to the user, and also what information gets asserted in access_tokens (preferred_username).
|
||||
|
||||
Browse to your [organization](administrate#Organizations) by visiting [https://console.zitadel.ch/org](https://console.zitadel.ch/org).
|
||||
|
||||
Add the domain to your [organization](administrate#Organizations) by clicking the button **Add Domain**.
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_domain_default.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_domain_default.png" itemprop="thumbnail" alt="Organization Overview" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization Overview</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
Input the domain in the input field and click **Add**
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_domain_add.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_domain_add.png" itemprop="thumbnail" alt="Organization Add Domain" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization Add Domain</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_domain_added.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_domain_added.png" itemprop="thumbnail" alt="Organization Domain Added" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization Domain Added</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
To start the domain verification click the domain name and a dialog will appear, where you can choose between DNS or HTTP challenge methods.
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_domain_verify.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_domain_verify.png" itemprop="thumbnail" alt="Organization Domain Verify" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization Domain Verify</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
For example, create a TXT record with your DNS provider for the used domain and click verify. **ZITADEL** will then proceed an check your DNS.
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_domain_verify_dns.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_domain_verify_dns.png" itemprop="thumbnail" alt="Organization Domain Verify DNS" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization Domain Verify DNS</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
> Do not delete the verification code **ZITADEL** will recheck the ownership from time to time
|
||||
|
||||
When the verification is successful you have the option to activate the domain by clicking **Set as primary**
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_domain_verified.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_domain_verified.png" itemprop="thumbnail" alt="Organization Domain Verified" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization verified</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
> This changes the **preferred loginnames** of your [users](administrate#Users) as indicated [here](administrate#How_ZITADEL_handles_usernames).
|
||||
|
||||
Congratulations your are done! You can check this by visiting [https://console.zitadel.ch/users/me](https://console.zitadel.ch/users/me)
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_user_personal_info.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_user_personal_info.png" itemprop="thumbnail" alt="User Personal Information" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">User Personal Information</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
> This only works when the [user](administrate#Users) is member of this [organization](administrate#Organizations)
|
||||
|
||||
### Manage Organization ZITADEL Roles
|
||||
|
||||
You can assign users [management roles](https://docs.zitadel.ch/administrate#ZITADEL_s_management_Roles) to your new organization.
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_manage_roles_1.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_manage_roles_1.png" itemprop="thumbnail" alt="Manage ZITADEL Roles 1" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage ZITADEL Roles 1</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_manage_roles_2.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_manage_roles_2.png" itemprop="thumbnail" alt="Manage ZITADEL Roles 2" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage ZITADEL Roles 2</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
### Audit organization changes
|
||||
|
||||
All changes to the organization are displayed on the organization menu within [ZITADEL Console](https://console.zitadel.ch/org) organization menu. Located on the right hand side under "activity".
|
||||
|
||||
> Screenshot here
|
@ -1,103 +0,0 @@
|
||||
---
|
||||
title: Projects
|
||||
---
|
||||
|
||||
### What are projects
|
||||
|
||||
The idea of projects is to have a vessel for all components who are closely related to each other.
|
||||
In ZITADEL all clients located in the same project share their roles, grants and authorizations.
|
||||
From an access management perspective you manage who has what role in the project and your application consumes this information. A project belongs to exactly one [organisation](administrate#Organisations).
|
||||
|
||||
The attribute `project role assertion` defines, if the roles should be integrated in the tokens without sending corresponding scope (`urn:zitadel:iam:org:project:role:{rolename}`)
|
||||
|
||||
With the project role check you can define, if a user should have a requested role to be able to logon.
|
||||
|
||||
**Clients**
|
||||
|
||||
These are your applications who initiate the authorization flow (see [What are clients](administrate#What_are_clients)).
|
||||
|
||||
**Roles**
|
||||
|
||||
[Roles (or Project Roles)](administrate#Roles) are a means of managing users access rights for a certain project. These [roles](administrate#Roles) are opaque for ZITADEL and have no weight in relation to each other.
|
||||
|
||||
As example, if [user](administrate#Users) has two roles, `admin` and `user` in a certain project, the information will be treated additive. There is no meaning or hierarchy implied by these roles.
|
||||
|
||||
**Grants**
|
||||
|
||||
With ZITADEL it is possible to give third parties (other organisations) the possibility to manage certain roles on their own. As a service provider, you will find this feature useful, as it allows you to establish a self-service culture for your business customers.
|
||||
|
||||
The owner of a project can grant (some would say "delegate") certain roles or all roles to another organisation. The target organization can then independently manage the assignment of their users to the role within the [granted project](administrate#Project_vs_granted_Project).
|
||||
|
||||
**Authorizations**
|
||||
|
||||
> TODO, Link to authorizations
|
||||
|
||||
#### Project vs. granted Project
|
||||
|
||||
A project belongs to your organisation. You can [grant certain roles](administrate#Grant_project_to_a_third_party) to another organization. A granted project, on the other hand, belongs to a third party, granting you some rights to manage certain roles of their project.
|
||||
|
||||
To make it more easier to differentiate ZITADEL Console displays these both as separate menu in the project section.
|
||||
|
||||
### Manage a project
|
||||
|
||||
#### Create a project
|
||||
|
||||
To create your project go to [https://console.zitadel.ch/projects](https://console.zitadel.ch/projects)
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_projects_empty.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_projects_empty.png" itemprop="thumbnail" alt="Manage Projects" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage Projects</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
Create a new project with a name which explains what's the intended use of this project.
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_projects_my_first_project.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_projects_my_first_project.png" itemprop="thumbnail" alt="Manage Projects" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage Projects</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
#### RBAC Settings
|
||||
|
||||
- Authorisation Check option (Check if the user at least has one role granted)
|
||||
- Enable Project_Role Assertion (if this is enabled assert project_roles, with the config of the corresponding client)
|
||||
|
||||
#### Define project specific roles
|
||||
|
||||
> Screenshot here
|
||||
|
||||
### Grant project to a third party
|
||||
|
||||
> Screenshot here
|
||||
|
||||
### Manage Project Authorisations
|
||||
|
||||
> Screenshot here
|
||||
|
||||
### Manage Project ZITADEL Roles
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_project_manage_roles_1.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_project_manage_roles_1.png" itemprop="thumbnail" alt="Manage ZITADEL Roles 1" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage ZITADEL Roles 1</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_project_manage_roles_2.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_project_manage_roles_2.png" itemprop="thumbnail" alt="Manage ZITADEL Roles 2" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage ZITADEL Roles 2</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
### Audit project changes
|
||||
|
||||
> Screenshot here
|
@ -1,82 +0,0 @@
|
||||
---
|
||||
title: Clients
|
||||
---
|
||||
|
||||
### What are clients
|
||||
|
||||
Clients are applications that share the same security context and interface with an "authorization server" (issuer of access tokens).
|
||||
|
||||
For example you could have a software project existing out of a web app and a mobile app, both of these applications might consume the same roles because the end user might use both of them.
|
||||
|
||||
Typical types of applications are:
|
||||
* Web
|
||||
* User Agent (Single-Page-Application)
|
||||
* Native
|
||||
|
||||
Check out our [Integration Guide](quickstarts#Overview) for more information.
|
||||
|
||||
### Manage clients
|
||||
|
||||
Clients might use different protocols for integrating with an IAM. With ZITADEL it is possible to use OpenID Connect 1.0 / OAuth 2.0. In the future SAML 2.0 support is planned as well.
|
||||
|
||||
#### OIDC Configuration
|
||||
|
||||
> Document Settings
|
||||
|
||||
### Create a client
|
||||
|
||||
To make configuration of a client easy we provide a wizard which generates a specification conferment setup.
|
||||
The wizard can be skipped for people who are needing special settings.
|
||||
|
||||
> For use cases where your configuration is not compliant we provide you a "dev mode" which disables conformance checks.
|
||||
|
||||
To create a new client start by browsing to your [project](administrate#Projects), this is normally something like [https://console.zitadel.ch/projects/78562301657017889](https://console.zitadel.ch/projects/78562301657017889)
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_projects_my_first_project.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_projects_my_first_project.png" itemprop="thumbnail" alt="Manage Clients" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage Clients</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
Click the **New** button and a wizard will appear which will guide you through the process.
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_clients_my_first_spa_wizard_1.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_clients_my_first_spa_wizard_1.png" itemprop="thumbnail" alt="Client Wizard 1" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Client Wizard 1</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_clients_my_first_spa_wizard_2.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_clients_my_first_spa_wizard_2.png" itemprop="thumbnail" alt="Client Wizard 2" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Client Wizard 2</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_clients_my_first_spa_wizard_3.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_clients_my_first_spa_wizard_3.png" itemprop="thumbnail" alt="Client Wizard 3" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Client Wizard 3</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_clients_my_first_spa_wizard_4.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_clients_my_first_spa_wizard_4.png" itemprop="thumbnail" alt="Client Wizard 4" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Client Wizard 4</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
When the wizard is complete, the clients configuration will be displayed and you can now use this client.
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_clients_my_first_spa_config.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_clients_my_first_spa_config.png" itemprop="thumbnail" alt="Client Wizard Complete" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Client Wizard Complete</figcaption>
|
||||
</figure>
|
||||
</div>
|
@ -1,41 +0,0 @@
|
||||
---
|
||||
title: Roles
|
||||
---
|
||||
|
||||
### What are Roles
|
||||
|
||||
**ZITADEL** lets [projects](administrate#projects) define their **role based access control**.
|
||||
|
||||
**Roles** can be consumed by the [clients](administrate#clients) which exist within a specific [project](administrate#projects).
|
||||
|
||||
For more information about how **roles** can be consumed, have a look the protocol specific information.
|
||||
|
||||
- [OpenID Connect / OAuth](quickstarts#How_to_consume_authorizations_in_your_application_or_service)
|
||||
|
||||
### Manage Roles
|
||||
|
||||
Each **role** consist of three fields.
|
||||
|
||||
| Field | Description | Example |
|
||||
|:-------------|:-----------------------------------------------------------------------------|--------------------------------------------------|
|
||||
| Key | This is the **Roles** actual name which can be used to verify the users roles. | User |
|
||||
| Display Name | A descriptive text for the purpose of the **Role** | User is the default role provided to each person |
|
||||
| Group | The group field allows to group certain roles who belong in the same context | User and Admin in the group **default** |
|
||||
|
||||
### Granting Roles
|
||||
|
||||
To give someone (or somewhat) access to a [project's](administrate#projects) resources and services **ZITADEL** provides two processes: **Roles** can either be granted to [users](administrate#Users) or to [organisations](administrate#Organisations).
|
||||
|
||||
#### Grant Roles to Organisations
|
||||
|
||||
The possibility to grant **roles** to an [organisation](administrate#Organisations) is intended as "delegation" so that a [organisation](administrate#Organisations) can on their own grant access to [users](administrate#Users).
|
||||
|
||||
For example a **service provider** could grant the **roles** `user`, and `manager` to an [organisation](administrate#Organisations) as soon as they purchases his service. This can be automated by utilising a [service user](administrate#Manage_Service_Users) in the **service providers** business process.
|
||||
|
||||
> Screenshot here
|
||||
|
||||
#### Grant Roles to Users
|
||||
|
||||
By granting **roles** to [users](administrate#Users), be it [humans or machines](administrate#Human_vs_Service_Users), this [user](administrate#Users) receives the authorization to access a project's resources.
|
||||
|
||||
> Screenshot here
|
@ -1,105 +0,0 @@
|
||||
---
|
||||
title: Users
|
||||
---
|
||||
|
||||
### What are users
|
||||
|
||||
In **ZITADEL** there are different [users](administrate#Users). Some belong to dedicated [organisations](administrate#Organisations) other belong to the [global organisation](administrate#Global_organisation). Some of them are human [users](administrate#Users) others are machines.
|
||||
Nonetheless we treat them all the same in regard to [roles](administrate#Roles) management and audit trail.
|
||||
|
||||
#### Human vs. Service Users
|
||||
|
||||
The major difference between human vs. machine [users](administrate#Users) is the type of credentials that can be used: With machine [users](administrate#Users) there is only a non-interactive logon process possible. As such we utilize “JWT as Authorization Grant”.
|
||||
|
||||
> TODO Link to “JWT as Authorization Grant” explanation.
|
||||
|
||||
### How ZITADEL handles usernames
|
||||
|
||||
**ZITADEL** is built around the concept of [organisations](administrate#Organisations). Each [organisation](administrate#Organisations) has its own pool of usernames which includes human and service [users](administrate#Users).
|
||||
|
||||
For example a [user](administrate#Users) with the username `road.runner` can only exist once in the [organisation](administrate#Organisations) `ACME`. **ZITADEL** will automatically generate a "logonname" for each [user](administrate#Users) consisting of `{username}@{domainname}.{zitadeldomain}`. Without [verifying the domain name](administrate#Verify_a_domain_name) this would result in the logonname `road.runner@acme.zitadel.ch`.
|
||||
|
||||
> If you use a dedicated instance **ZITADEL** replace `zitadel.ch` with your domain name.
|
||||
|
||||
If someone [verifies a domain name](administrate#Verify_a_domain_name) within the organisation, **ZITADEL** will generate additional logonames for each [user](administrate#Users) with the verified domain. For example if the domain is `acme.ch` the resulting logonname would be `road.runner@acme.ch` in addition to the already generated `road.runner@acme.zitadel.ch`.
|
||||
|
||||
> Domain verification also removes the logonname from all [users](administrate#Users), who might have used this combination in the [global organisation](administrate#Global_organisation).
|
||||
> Relating to example with `acme.ch` if a user in the [global organisation](administrate#Global_organisation), let's call him `coyote`, used `coyote@acme.ch` this logonname will be replaced with `coyote@randomvalue.tld`
|
||||
> **ZITADEL** notifies the user about this change
|
||||
|
||||
### Manage Users
|
||||
|
||||
#### Search Users
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_user_list_search.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_user_list_search.png" itemprop="thumbnail" alt="User list Search" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">User list Search</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
Image 1: User List Search
|
||||
|
||||
#### Create Users
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_user_list.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_user_list.png" itemprop="thumbnail" alt="User list" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">User list</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_user_create_form.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_user_create_form.png" itemprop="thumbnail" alt="User Create Form" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">User Create Form</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_user_create_done.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_user_create_done.png" itemprop="thumbnail" alt="User Create Done" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">User Create Done</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
#### Set Password
|
||||
|
||||
> Screenshot here
|
||||
|
||||
### Manage Service Users
|
||||
|
||||
> Screenshot here
|
||||
|
||||
### Manage User Authorisations
|
||||
|
||||
> Screenshot here
|
||||
|
||||
### Manage User ZITADEL Roles
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_user_manage_roles_1.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_user_manage_roles_1.png" itemprop="thumbnail" alt="Manage ZITADEL Roles 1" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage ZITADEL Roles 1</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_user_manage_roles_2.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_user_manage_roles_2.png" itemprop="thumbnail" alt="Manage ZITADEL Roles 2" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage ZITADEL Roles 2</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
### Audit user changes
|
||||
|
||||
> Screenshot here
|
@ -1,53 +0,0 @@
|
||||
---
|
||||
title: Policies
|
||||
---
|
||||
|
||||
### What are policies
|
||||
|
||||
Policies are a means of enforcing certain behaviour of ZITADEL.
|
||||
ZITADEL defines a default policy on the system level. However an organisation owner can change these aspects within his own organisation.
|
||||
|
||||
### Available policies
|
||||
|
||||
Below is a list of available policies
|
||||
|
||||
#### Password complexity
|
||||
|
||||
This policy enforces passwords of users within the organization to be compliant.
|
||||
|
||||
- min length
|
||||
- has number
|
||||
- has symbol
|
||||
- has lower case
|
||||
- has upper case
|
||||
|
||||
> Screenshot here
|
||||
|
||||
#### IAM Access Preference
|
||||
|
||||
If enabled, this policy enforces that usernames are suffixed with the organisations domain.
|
||||
Under normal operation this policy is only false on the `global` organisation, so that users can choose their email as their username.
|
||||
|
||||
Only available for the [IAM Administrator](administrate#ZITADEL_Administrators).
|
||||
|
||||
> Screenshot here
|
||||
|
||||
#### Login Options
|
||||
|
||||
With this policy it is possible to define what options a user sees in the login process:
|
||||
|
||||
- Username Password allowed
|
||||
- Self Register allowed
|
||||
- External IDP allowed
|
||||
- List of allowed external IDPs
|
||||
|
||||
> Screenshot here
|
||||
|
||||
#### Audit policy changes
|
||||
|
||||
> Screenshot here
|
||||
|
||||
### Upcoming Policies
|
||||
|
||||
- Password age
|
||||
- Password failure count
|
@ -1,77 +0,0 @@
|
||||
---
|
||||
title: Identity Providers
|
||||
---
|
||||
|
||||
### What are Identity Providers
|
||||
|
||||
Identity providers or in short idps are external systems to which **ZITADEL** can create a **federation** or use their **directory service**.
|
||||
Normally federation uses protocols like [OpenID Connect 1.0](https://openid.net/connect/), [OAuth 2.0](https://oauth.net/2/) and [SAML 2.0](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html).
|
||||
|
||||
Some examples include:
|
||||
|
||||
**Social Providers**
|
||||
|
||||
- Google Account
|
||||
- Microsoft Live Account
|
||||
- Apple ID
|
||||
- GitHub
|
||||
- GitLab
|
||||
- ...
|
||||
|
||||
**Enterprise Providers**
|
||||
|
||||
- Azure AD Tenant
|
||||
- Gsuite hosted domain
|
||||
- ...
|
||||
|
||||
**Generic**
|
||||
|
||||
- ADFS
|
||||
- ADDS
|
||||
- Keycloak
|
||||
- LDAP
|
||||
|
||||
### What is Identity Brokering
|
||||
|
||||
ZITADEL supports the usage as identity broker, by linking multiple external IDPs into one user.
|
||||
With identity brokering the client, that relies on ZITADEL, doesn't need to care about the linking of identity.
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
tbd.
|
||||
</details>
|
||||
|
||||
### Manage Identity Providers
|
||||
|
||||
> Screenshot here
|
||||
|
||||
### Federation Protocols
|
||||
|
||||
Currently supported are the following protocols.
|
||||
|
||||
- OpenID Connect 1.0
|
||||
- OAuth 2.0
|
||||
|
||||
SAML 2.0 will follow later on.
|
||||
|
||||
### Storage Federation
|
||||
|
||||
> This is a work in progress.
|
||||
|
||||
Storage federation is a means of integrating existing identity storage like [LDAP](https://tools.ietf.org/html/rfc4511) and [ADDS](https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/get-started/virtual-dc/active-directory-domain-services-overview).
|
||||
With this process **ZITADEL** can authenticate users with LDAP Binding and SPNEGO for ADDS. It is also possible to synchronize the users just-in-time or scheduled.
|
||||
|
||||
#### Sync Settings
|
||||
|
||||
Here we will document all the different sync options
|
||||
|
||||
- Read-only
|
||||
- Writeback
|
||||
- just-in-time sync
|
||||
- scheduled sync
|
||||
|
||||
> TBD
|
||||
|
||||
### Audit identity provider changes
|
||||
|
||||
> Screenshot here
|
@ -1,42 +0,0 @@
|
||||
---
|
||||
title: Authorizations
|
||||
---
|
||||
|
||||
### What are Authorizations
|
||||
|
||||
**ZITADEL** thinks of authorizations as resource who clearly defines which user has what roles. Authorizations are also called "user grant".
|
||||
|
||||
### Manage Authorizations
|
||||
|
||||
You can grant Roles directly on a project. Or, if the user is in your organisation, by apply in the roles to the user directly.
|
||||
Additionaly you can use the authorization menu item to search for a user and project.
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_authz_overview.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_authz_overview.png" itemprop="thumbnail" alt="Manage Authorisations Overview" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage Authorisations Overview</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_authz_add_1.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_authz_add_1.png" itemprop="thumbnail" alt="Manage Authorisations 1" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage Authorisations 1</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_authz_add_2.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_authz_add_2.png" itemprop="thumbnail" alt="Manage Authorisations 2" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage Authorisations 2</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_authz_add_3.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_authz_add_3.png" itemprop="thumbnail" alt="Manage Authorisations 3" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Manage Authorisations 3</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
- [Manage Project Authorisations](administrate#Manage_Project_Authorisations)
|
||||
- [Manage User Authorisations](administrate#Manage_User_Authorisations)
|
@ -1,50 +0,0 @@
|
||||
---
|
||||
title: Management roles
|
||||
---
|
||||
|
||||
### ZITADEL's management roles
|
||||
|
||||
ZITADEL's own role model is built around the IAM resource. The roles have some hierarchies to them. For example a IAM_OWNER can view and edit every resource of the system. ORG_OWNERS can only manage their resources included within their organization. This includes projects, clients, users, and so on.
|
||||
|
||||
#### How to give a user ZITADEL roles
|
||||
|
||||
|
||||
> Screenshots
|
||||
|
||||
##### System roles
|
||||
|
||||
IAM_OWNER
|
||||
|
||||
IAM_OWNER_VIEWER
|
||||
|
||||
##### Organisation roles
|
||||
|
||||
ORG_OWNER
|
||||
|
||||
ORG_OWNER_VIEWER
|
||||
|
||||
ORG_USER_PERMISSION_EDITOR
|
||||
|
||||
ORG_PROJECT_PERMISSION_EDITOR
|
||||
|
||||
ORG_PROJECT_CREATOR
|
||||
|
||||
##### Owned Project roles
|
||||
|
||||
PROJECT_OWNER
|
||||
|
||||
PROJECT_OWNER_VIEWER
|
||||
|
||||
PROJECT_OWNER_GLOBAL
|
||||
|
||||
PROJECT_OWNER_VIEWER_GLOBAL
|
||||
|
||||
##### Granted Project roles
|
||||
|
||||
PROJECT_GRANT_OWNER
|
||||
|
||||
PROJECT_GRANT_OWNER_VIEWER
|
||||
|
||||
##### Project roles management
|
||||
|
||||
> Explain Project Authorization
|
@ -1,49 +0,0 @@
|
||||
---
|
||||
title: ZITADEL Roles
|
||||
---
|
||||
|
||||
### ZITADEL's Roles
|
||||
|
||||
**ZITADEL's** own role model is built around the IAM resources. The roles have some hierarchies to them. For example a IAM_OWNER can view and edit every resource of the system. ORG_OWNERS can only manage their resources included within their organisation. This includes projects, clients, users, and so on.
|
||||
|
||||
#### System Roles
|
||||
|
||||
IAM_OWNER
|
||||
|
||||
IAM_OWNER_VIEWER
|
||||
|
||||
#### Organisation Roles
|
||||
|
||||
ORG_OWNER
|
||||
|
||||
ORG_OWNER_VIEWER
|
||||
|
||||
ORG_USER_PERMISSION_EDITOR
|
||||
|
||||
ORG_PROJECT_PERMISSION_EDITOR
|
||||
|
||||
ORG_PROJECT_CREATOR
|
||||
|
||||
#### Owned Project Roles
|
||||
|
||||
PROJECT_OWNER
|
||||
|
||||
PROJECT_OWNER_VIEWER
|
||||
|
||||
PROJECT_OWNER_GLOBAL
|
||||
|
||||
PROJECT_OWNER_VIEWER_GLOBAL
|
||||
|
||||
#### Granted Project Roles
|
||||
|
||||
PROJECT_GRANT_OWNER
|
||||
|
||||
PROJECT_GRANT_OWNER_VIEWER
|
||||
|
||||
### Manage ZITADEL Roles
|
||||
|
||||
You can grant ZITADEL Roles directly on a resource like organisation or project. Or, if the user is in your organisation, by applying the roles to the user directly:
|
||||
|
||||
- [Manage Organisation ZITADEL Roles](administrate#Manage_Organisation_ZITADEL_Roles)
|
||||
- [Manage Project ZITADEL Roles](administrate#Manage_Organisation_ZITADEL_Roles)
|
||||
- [Manage User ZITADEL Roles](administrate#Manage_Organisation_ZITADEL_Roles)
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
title: Audit
|
||||
---
|
||||
|
||||
### What about Audit
|
||||
|
||||
ZITADEL is built upon the concept of Event sourcing. With this ZITADEL can track each operation of all objects it maintains over an infinite amount of time. The only limit is the storage system.
|
||||
|
||||
With these events ZITADEL can provide you with a super detailed audit trail where you can see who changed what and when.
|
||||
|
||||
Over the next few releases we will steadily enhance and build features tailored to reporting and audit.
|
||||
|
||||
> It is important to mention that even if ZITADEL does not yet supply the Graphical User Interface for certain audit aspects it still has all the data to generate these reports later on!
|
@ -1,73 +0,0 @@
|
||||
---
|
||||
title: System Administration
|
||||
---
|
||||
|
||||
### What is meant by system
|
||||
|
||||
System describes the root of ZITADEL and includes all other elements like organisations, users and so on. Most of the time this part is managed by an user with the role IAM_OWNER.
|
||||
|
||||
### Default Policies
|
||||
|
||||
When ZITADEL is set up for the first time we establish certain default policies for the whole system.
|
||||
|
||||
> TODO Document default policy settings
|
||||
|
||||
### Manage Read Models
|
||||
|
||||
Read Models are a way to normalize data out of the event stream for certain aspects. For example there is a model which consists of logonname and the password hash so that the login process can query that data.
|
||||
|
||||
All read models are eventually consistent by nature and sometimes an administrator would like to verify they are still up-to-date.
|
||||
In the ZITADEL Console is a section called administration available where the admin can check all read models and their current state.
|
||||
There is even a possibility to regenerate a read model.
|
||||
|
||||
> When a read model is regenerated it might take up some time to be fully operational again
|
||||
> Depending on the model which is regenerated this might have a operational impact for the end-users
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_iam_admin_views.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_iam_admin_views.png" itemprop="thumbnail" alt="IAM View Management" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">IAM View Management</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_iam_admin_failed.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_iam_admin_failed.png" itemprop="thumbnail" alt="IAM Failed Events" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">IAM Failed Events</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
> Additional infos to the architecture of ZITADEL is located in [Architecture Docs](architecture#Architecture)
|
||||
|
||||
### Secret Handling
|
||||
|
||||
ZITADEL stores secrets always encrypted or hashed in it's storage.
|
||||
Whenever feasible we try to utilize public / private key mechanics to handle secrets.
|
||||
|
||||
**Encryption**
|
||||
We use `AES256` as default mechanic for storing secrets.
|
||||
|
||||
**Password Hashing**
|
||||
By default `bcrypt` is used with a salt of `14`.
|
||||
|
||||
> This mechanic is used for user passwords and client secrets
|
||||
|
||||
**Signing Keys**
|
||||
These keys are randomly generated within ZITADEL and are rotated on a regular basis (e.g all 6h).
|
||||
|
||||
> Signing keys are stored with AES256 encryption
|
||||
|
||||
**TLS**
|
||||
Under normal operations ZITADEL's API nodes are located behind a reverse proxy. So the TLS Key handling are out of context in this regard.
|
||||
However ZITADEL can use TLS keys at runtime level.
|
||||
|
||||
> TODO Document TLS config
|
||||
|
||||
### IAM Configuration
|
||||
|
||||
> TODO Document ZITADEL config
|
||||
|
||||
### Audit system changes
|
||||
|
||||
> Screenshot here
|
@ -13,4 +13,4 @@ It demonstrates how to add a user login to your application and fetch some data
|
||||
|
||||
At the end of the guide you should have an application able to login a user and read the user profile.
|
||||
|
||||
> Note that our **ZITADEL Console** is also written in Angular and can therefore be used as a reference.
|
||||
> This documentation refers to our [Template](https://github.com/caos/zitadel-angular-template) in Github. Note that our **ZITADEL Console** is also written in Angular and can therefore be used as a reference.
|
@ -9,13 +9,13 @@ You will need to provide some information about your app. We recommend creating
|
||||
Select Web Application and continue.
|
||||
We recommend that you use [Authorization Code](architecture#Authorization_Code) in combination with [Proof Key for Code Exchange](architecture#Proof_Key_for_Code_Exchange) for all web applications.
|
||||
|
||||
> Make sure Authentication Method is set to `NONE` and the Application Type is set to `SPA` or `NATIVE`.
|
||||
<img src="img/angular/app-create-light.png" height="260px" alt="create app in console"/>
|
||||
|
||||
#### Redirect URLs
|
||||
|
||||
A redirect URL is a URL in your application where ZITADEL redirects the user after they have authenticated. Set your url to the domain the web app will be deployed to or use `localhost:4200` for development as Angular will be running on port 4200.
|
||||
|
||||
> If you are following along with the sample project you downloaded from our templates, you should set the Allowed Callback URL to http://localhost:4200/auth/callback. You will also have to set dev mode to `true` as this will enable unsecure http for the moment.
|
||||
> If you are following along with the [sample](https://github.com/caos/zitadel-angular-template) project you downloaded from our templates, you should set the Allowed Callback URL to http://localhost:4200/auth/callback. You will also have to set dev mode to `true` as this will enable unsecure http for the moment.
|
||||
|
||||
If you want to redirect the users back to a route on your application after they have logged out, add an optional redirect in the post redirectURI field.
|
||||
|
||||
@ -25,5 +25,3 @@ Continue and Create the application.
|
||||
|
||||
After successful app creation a popup will appear showing you your clientID as well as a secret.
|
||||
Copy your client ID as it will be needed in the next step.
|
||||
|
||||
> Note: You will be able to regenerate the secret at a later time, though it is not needed for SPAs with Authorization Code Flow.
|
||||
|
@ -21,11 +21,15 @@ Add the Auth module to your Angular imports in AppModule and setup the AuthConfi
|
||||
import { AuthConfig, OAuthModule } from 'angular-oauth2-oidc';
|
||||
|
||||
const authConfig: AuthConfig = {
|
||||
clientId: 'YOUR CLIENT ID',
|
||||
redirectUri: 'http://localhost:4200/auth/callback', // change this to your domain later or use window.location.origin.
|
||||
scope: 'openid profile email',
|
||||
responseType: 'code',
|
||||
oidc: true,
|
||||
clientId: 'YOUR-CLIENT-ID', // replace with your appid
|
||||
dummyClientSecret: 'YOUR-SECRET', // required by library
|
||||
issuer: 'https://issuer.zitadel.ch',
|
||||
redirectUri: 'http://localhost:4200/auth/callback',
|
||||
postLogoutRedirectUri: 'http://localhost:4200/signedout', // optional
|
||||
requireHttps: false // required for running locally
|
||||
};
|
||||
|
||||
@NgModule({
|
||||
@ -44,17 +48,16 @@ Then create a Authentication Service to provide the functions to authenticate yo
|
||||
You can use Angulars schematics to do so:
|
||||
|
||||
``` bash
|
||||
ng g component services/auth
|
||||
ng g component services/authentication
|
||||
```
|
||||
This will create an AuthService automatically for you.
|
||||
This will create an AuthenticationService automatically for you.
|
||||
|
||||
Copy the following code to your service. This code provides a function `authenticate()` which redirects the user to ZITADEL. After the user has logged in it will be redirected back to your redirectURI set in Auth Module and Console. Make sure both correspond, otherwise ZITADEL will throw an error.
|
||||
|
||||
```ts
|
||||
import { AuthConfig, OAuthService } from 'angular-oauth2-oidc';
|
||||
|
||||
export default class AuthService {
|
||||
private authConfig!: AuthConfig;
|
||||
export class AuthenticationService {
|
||||
private _authenticated: boolean = false;
|
||||
private readonly _authenticationChanged: BehaviorSubject<
|
||||
boolean
|
||||
@ -62,6 +65,7 @@ export default class AuthService {
|
||||
|
||||
constructor(
|
||||
private oauthService: OAuthService,
|
||||
private authConfig: AuthConfig,
|
||||
private statehandler: StatehandlerService,
|
||||
) { }
|
||||
|
||||
@ -77,7 +81,10 @@ export default class AuthService {
|
||||
return from(this.oauthService.loadUserProfile());
|
||||
}
|
||||
|
||||
public async authenticate(): Promise<boolean> {
|
||||
public async authenticate(
|
||||
setState: boolean = true,
|
||||
): Promise<boolean> {
|
||||
console.log('auth');
|
||||
this.oauthService.configure(this.authConfig);
|
||||
|
||||
this.oauthService.strictDiscoveryDocumentValidation = false;
|
||||
@ -85,7 +92,7 @@ export default class AuthService {
|
||||
|
||||
this._authenticated = this.oauthService.hasValidAccessToken();
|
||||
|
||||
if (!this.oauthService.hasValidIdToken() || !this.authenticated || partialConfig || force) {
|
||||
if (!this.oauthService.hasValidIdToken() || !this.authenticated) {
|
||||
const newState = setState ? await this.statehandler.createState().toPromise() : undefined;
|
||||
this.oauthService.initCodeFlow(newState);
|
||||
}
|
||||
@ -102,6 +109,44 @@ export default class AuthService {
|
||||
}
|
||||
```
|
||||
|
||||
Our template includes a statehandler service to redirect the user back to the route where he initially came from. It saves the route information to a unique id so that the user can be redirected back after a successful authentication.
|
||||
If you don't need such a behaviour you can escape the following lines from the `authenticate()` method above.
|
||||
```ts
|
||||
...
|
||||
const newState = setState ? await this.statehandler.createState().toPromise() : undefined;
|
||||
...
|
||||
```
|
||||
|
||||
If you decide to use it provide the service in the `app.module` and make sure it gets initialized first using angulars `APP_INITIALIZER`.
|
||||
|
||||
```ts
|
||||
|
||||
const stateHandlerFn = (stateHandler: StatehandlerService) => {
|
||||
return () => {
|
||||
return stateHandler.initStateHandler();
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
providers: [
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: stateHandlerFn,
|
||||
multi: true,
|
||||
deps: [StatehandlerService],
|
||||
},
|
||||
{
|
||||
provide: StatehandlerProcessorService,
|
||||
useClass: StatehandlerProcessorServiceImpl,
|
||||
},
|
||||
{
|
||||
provide: StatehandlerService,
|
||||
useClass: StatehandlerServiceImpl,
|
||||
},
|
||||
]
|
||||
...
|
||||
```
|
||||
|
||||
### Add Login in your application
|
||||
|
||||
To login a user, a component or a guard is needed.
|
||||
@ -160,6 +205,16 @@ const routes: Routes = [
|
||||
...
|
||||
```
|
||||
|
||||
> Note: To complete the code flow, `authenticate()` needs to be called twice. You may have to add a guard to your callback url to make sure it will complete the flow.
|
||||
|
||||
```ts
|
||||
{
|
||||
path: 'auth/callback',
|
||||
canActivate: [AuthGuard],
|
||||
redirectTo: 'user',
|
||||
},
|
||||
```
|
||||
|
||||
### Add Logout in your application
|
||||
|
||||
The authService and Library also provides a useful function for logging out your users. Just call `auth.signout()` to log out your user. Note that you can also configure your Logout Redirect URL if you want your Users to be redirected after logout.
|
||||
@ -182,17 +237,20 @@ To fetch user data, ZITADELS user info endpoint has to be called. This data cont
|
||||
Our AuthService already includes a function called getOIDCUser(). You can call it whereever you need this information.
|
||||
|
||||
```ts
|
||||
import { AuthService } from 'src/app/services/auth.service.ts';
|
||||
import { AuthenticationService } from 'src/app/services/auth.service.ts';
|
||||
|
||||
export class SomeComponentWithUserInfo {
|
||||
constructor(public authService: AuthService){}
|
||||
public user$: Observable<any>;
|
||||
|
||||
constructor(private auth: AuthenticationService) {
|
||||
this.user$ = this.auth.getOIDCUser();
|
||||
}
|
||||
```
|
||||
|
||||
and in your html
|
||||
|
||||
```html
|
||||
<div *ngIf="(authService.getOIDCUser | async) as oidcInfo">
|
||||
<p>{{oidcInfo | json}}</p>
|
||||
<div *ngIf="user$ | async as user">
|
||||
<p>{{user | json}}</p>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -2,8 +2,14 @@
|
||||
title: Completion
|
||||
---
|
||||
|
||||
### What next?
|
||||
You have successfully integrated ZITADEL in your Angular Application!
|
||||
|
||||
You have successfully integrated ZITADEL in your Angular Application! Now you can proceed implementing our APIs to include Authorization. Refer to our [Docs](apis#Authentication_API) or checkout our Console Code on [Github](https://github.com/caos/zitadel) which is using GRPC to access data.
|
||||
If you get stuck consider checking out our [template](https://github.com/caos/zitadel-angular-template) application which includes all the mentioned functionality of this quickstart. You can simply start by cloning the repo and replacing the AuthConfig in the app.module with your own configuration. If your run into issues don't hesitate to contact us or raise an issue on [Github](https://github.com/caos/zitadel).
|
||||
|
||||
<img src="img/angular/app-screen.png" height="260px" alt="create app in console"/>
|
||||
|
||||
### Whats next?
|
||||
|
||||
Now you can proceed implementing our APIs to include Authorization. Refer to our [Docs](apis#Authentication_API) or checkout our Console Code on [Github](https://github.com/caos/zitadel) which is using GRPC to access data.
|
||||
|
||||
For more information about creating an angular application we refer to [Angular](https://angular.io/start) and for more information about the used oauth/oidc library consider reading their docs at [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc).
|
@ -27,10 +27,167 @@ For example with [zitadel.ch](https://zitadel.ch), issuer.zitadel.ch would be th
|
||||
|
||||
> The authorization_endpoint is located with the login page, due to the need of accessing the same cookie domain
|
||||
|
||||
Required request Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| client_id | The id of your client as shown in Console. |
|
||||
| redirect_uri | Callback uri of the authorization request where the code or tokens will be sent to. Must match exactly one of the preregistered in Console. |
|
||||
| response_type | Determines whether a `code`, `id_token token` or just `id_token` will be returned. Most use cases will need `code`. See flow guide for more info. |
|
||||
| scope | `openid` is required, see [Scopes](architecture#Scopes) for more possible values. Scopes are space delimited, e.g. `openid email profile` |
|
||||
|
||||
Required parameters for PKCE (see PKCE guide for more information)
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------------------|-------------------------------------------------------|
|
||||
| code_challenge | The SHA-256 value of the generated code_verifier |
|
||||
| code_challenge_method | Method used to generate the challenge, must be `S256` |
|
||||
|
||||
Optional parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|---------------|------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| id_token_hint | Valid `id_token` (of an existing session) used to identity the subject. Should be provided when using prompt `none`. |
|
||||
| login_hint | A valid logon name of a user. Will be used for username inputs or preselecting a user on `select_account` |
|
||||
| max_age | Seconds since the last active successful authentication of the user |
|
||||
| nonce | Random string value to associate the client session with the ID Token and for replay attacks mitigation. |
|
||||
| prompt | If the Auth Server prompts the user for (re)authentication. <br>no prompt: the user will have to choose a session if more than one session exists<br>`none`: user must be authenticated without interaction, an error is returned otherwise <br>`login`: user must reauthenticate / provide a user name <br>`select_account`: user is prompted to select one of the existing sessions or create a new one |
|
||||
| state | Opaque value used to maintain state between the request and the callback. Used for Cross-Site Request Forgery (CSRF) mitigation as well. |
|
||||
|
||||
Successful Code Response
|
||||
|
||||
| Property | Description |
|
||||
|----------|-------------------------------------------------------------------------------|
|
||||
| code | Opaque string which will be necessary to request tokens on the token endpoint |
|
||||
| state | Unmodified `state` parameter from the request |
|
||||
|
||||
Successful Implicit Response
|
||||
|
||||
| Property | Description |
|
||||
|--------------|-------------------------------------------------------------|
|
||||
| access_token | Only returned if `response_type` included `token` |
|
||||
| expires_in | Number of second until the expiration of the `access_token` |
|
||||
| id_token | Only returned if `response_type` included `id_token` |
|
||||
| token_type | Type of the `access_token`. Value is always `Bearer` |
|
||||
|
||||
Error Response
|
||||
|
||||
Regardless of the authorization flow chosen, if an error occurs the following response will be returned to the redirect_uri.
|
||||
|
||||
> 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
|
||||
|
||||
|
||||
| Property | Description |
|
||||
|-------------------|----------------------------------------------------------------------|
|
||||
| error | An OAuth / OIDC error_type |
|
||||
| error_description | Description of the error type or additional information of the error |
|
||||
| state | Unmodified `state` parameter from the request |
|
||||
|
||||
#### token_endpoint
|
||||
|
||||
[https://api.zitadel.ch/oauth/v2/token](https://api.zitadel.ch/oauth/v2/token)
|
||||
|
||||
##### Authorization Code Grant (Code Exchange)
|
||||
|
||||
Required request Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|---------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| code | Code that was issued from the authorization request. |
|
||||
| grant_type | Must be `authorization_code` |
|
||||
| redirect_uri | Callback uri where the code was be sent to. Must match exactly the redirect_uri of the authorization request. |
|
||||
|
||||
Depending on your authorization method you will have to provide additional parameters or headers:
|
||||
|
||||
When using `client_secret_basic`
|
||||
|
||||
Send your `client_id` and `client_secret` as Basic Auth Header. Check [Client Secret Basic Auth Method](architecture#Client_Secret_Basic) on how to build it correctly.
|
||||
|
||||
When using `client_secret_post`
|
||||
|
||||
Send your `client_id` and `client_secret` as parameters in the body:
|
||||
|
||||
| Parameter | Description |
|
||||
|---------------|----------------------------------|
|
||||
| client_id | client_id of the application |
|
||||
| client_secret | client_secret of the application |
|
||||
|
||||
When using `none` (PKCE)
|
||||
|
||||
Send your code_verifier for us to recompute the code_challenge of the authorization request.
|
||||
|
||||
| Parameter | Description |
|
||||
|---------------|--------------------------------------------------------------|
|
||||
| code_verifier | code_verifier previously used to generate the code_challenge |
|
||||
|
||||
When using `private_key_jwt`
|
||||
|
||||
Send a client assertion as JWT for us to validate the signature against the registered public key.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------------------|-----------------------------------------------------------------------------------------------------------------|
|
||||
| client_assertion | JWT built and signed according to [Using JWTs for Client Authentication](#Using JWTs for Client Authentication) |
|
||||
| client_assertion_type | Must be `urn:ietf:params:oauth:client-assertion-type:jwt-bearer` |
|
||||
|
||||
##### JWT Profile Grant
|
||||
|
||||
---
|
||||
|
||||
Required request Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|------------|-------------------------------------------------------------------------------------------------------------------------------|
|
||||
| grant_type | Must be `urn:ietf:params:oauth:grant-type:jwt-bearer` |
|
||||
| assertion | JWT built and signed according to [Using JWTs for Client Authentication](#Using JWTs for Client Authentication) |
|
||||
| scope | [Scopes](architecture#Scopes) you would like to request from ZITADEL. Scopes are space delimited, e.g. `openid email profile` |
|
||||
|
||||
```BASH
|
||||
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=DKLvnksjndjsflkdjlkfgjslow... \
|
||||
--data client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
|
||||
--data client_assertion=eyJhbGciOiJSUzI1Ni...
|
||||
```
|
||||
|
||||
|
||||
#### introspection_endpoint
|
||||
|
||||
[https://api.zitadel.ch/oauth/v2/introspect](https://api.zitadel.ch/oauth/v2/introspect)
|
||||
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-----------------|
|
||||
| token | An access token |
|
||||
|
||||
Depending on your authorization method you will have to provide additional parameters or headers:
|
||||
|
||||
When using `client_secret_basic`
|
||||
|
||||
Send your `client_id` and `client_secret` as Basic Auth Header. Check [Client Secret Basic Auth Method](architecture#Client_Secret_Basic) on how to build it correctly.
|
||||
|
||||
---
|
||||
|
||||
When using `private_key_jwt`
|
||||
|
||||
Send a client assertion as JWT for us to validate the signature against the registered public key.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------------------|-------------------------------------------------------------------------------------------------------------|
|
||||
| client_assertion | JWT built and signed according to [Using JWTs for Client Authentication](architecture#JWT_with_Private_Key) |
|
||||
| client_assertion_type | must be `urn:ietf:params:oauth:client-assertion-type:jwt-bearer` |
|
||||
|
||||
```BASH
|
||||
curl --request POST \
|
||||
--url https://api.zitadel.ch/oauth/v2/introspect \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
|
||||
--data client_assertion=eyJhbGciOiJSUzI1Ni... \
|
||||
--data token=VjVxyCZmRmWYqd3_F5db9Pb9mHR5fqzhn...
|
||||
```
|
||||
|
||||
#### userinfo_endpoint
|
||||
|
||||
[https://api.zitadel.ch/oauth/v2/userinfo](https://api.zitadel.ch/oauth/v2/userinfo)
|
||||
@ -74,7 +231,7 @@ 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:project:role:{rolename} | `urn:zitadel:iam:org:project:role:user` | By using this scope a client can request the claim urn:zitadel:iam:roles:rolename} to be asserted when possible. As an alternative approach you can enable all roles to be asserted from the [project](zitadel-projects) a client belongs to. |
|
||||
| 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 |
|
||||
@ -86,30 +243,31 @@ In addition to the standard compliant scopes we utilize the following scopes.
|
||||
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 |
|
||||
| Claims | Userinfo | Introspection | ID Token | Access Token |
|
||||
|:------------------------------------------------|:---------------|----------------|---------------------------------------------|--------------------------------------|
|
||||
| acr | No | No | Yes | No |
|
||||
| address | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| amr | No | No | Yes | No |
|
||||
| aud | No | No | Yes | When JWT |
|
||||
| auth_time | No | No | Yes | No |
|
||||
| azp | No | No | Yes | When JWT |
|
||||
| email | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| email_verified | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| exp | No | No | Yes | When JWT |
|
||||
| family_name | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| gender | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| given_name | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| iat | No | No | Yes | When JWT |
|
||||
| iss | No | No | Yes | When JWT |
|
||||
| locale | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| name | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| nonce | No | No | Yes | No |
|
||||
| phone | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| phone_verified | When requested | When requested | When requested amd response_type `id_token` | No |
|
||||
| preferred_username (username when Introspect ) | When requested | When requested | Yes | No |
|
||||
| sub | Yes | Yes | Yes | When JWT |
|
||||
| urn:zitadel:iam:org:domain:primary:{domainname} | When requested | When requested | When requested | When JWT and requested |
|
||||
| urn:zitadel:iam:org:project:roles:{rolename} | When requested | When requested | When requested or configured | When JWT and requested or configured |
|
||||
|
||||
#### Standard Claims
|
||||
|
||||
@ -150,6 +308,76 @@ ZITADEL reserves some claims to assert certain data.
|
||||
| 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 |
|
||||
|
||||
### Auth Methods
|
||||
|
||||
#### Client Secret Basic
|
||||
|
||||
When using `client_secret_basic` on token or introspection endpoints, provide an`Authorization` header with a Basic auth value in the following form:
|
||||
|
||||
```markdown
|
||||
Authorization: "Basic " + base64( formUrlEncode(client_id) + ":" + formUrlEncode(client_secret) )
|
||||
```
|
||||
|
||||
Given the client_id `78366401571920522@amce` and client_secret `veryweaksecret!`, this would result in the following `Authorization` header:
|
||||
`Basic NzgzNjY0MDE1NzE5MjA1MjIlNDBhbWNlOnZlcnl3ZWFrc2VjcmV0JTIx`
|
||||
|
||||
#### JWT with Private Key
|
||||
|
||||
When using `private_key_jwt` for token or introspection endpoints, provide a JWT as assertion generated with the following structure and signed with a downloaded key:
|
||||
|
||||
---
|
||||
|
||||
Key JSON
|
||||
|
||||
| Key | Example | Description |
|
||||
|:---------|:--------------------------------------------------------------------|:-------------------------------------------------------------------------------|
|
||||
| type | `"application"` | The type of account, right now only application is valid |
|
||||
| keyId | `"81693565968962154"` | 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! |
|
||||
| clientId | `78366401571920522@acme` | The client_id of the application, this is the same as the subject from tokens |
|
||||
| appId | `78366403256846242` | The id of the application (just for completeness, not used for JWT) |
|
||||
|
||||
```JSON
|
||||
{
|
||||
"type": "application",
|
||||
"keyId": "81693565968962154",
|
||||
"key": "-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----",
|
||||
"clientId": "78366401571920522@acme",
|
||||
"appId": "78366403256846242"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
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 | `"78366401571920522@acme"` | String which represents the requesting party (owner of the key), normally the `clientID` from the json key file |
|
||||
| sub | `"78366401571920522@acme"` | The subject ID of the application, normally the `clientID` from the json key file |
|
||||
|
||||
```JSON
|
||||
{
|
||||
"iss": "78366401571920522@acme",
|
||||
"sub": "78366401571920522@acme",
|
||||
"aud": "https://issuer.zitadel.ch",
|
||||
"exp": 1605183582,
|
||||
"iat": 1605179982
|
||||
}
|
||||
```
|
||||
|
||||
> To identify your key, it is necessary that you provide a JWT with a `kid` header claim representing your keyId from the Key JSON:
|
||||
> ```json
|
||||
> {
|
||||
> "alg": "RS256",
|
||||
> "kid": "81693565968962154"
|
||||
> }
|
||||
> ```
|
||||
|
||||
|
||||
### Grant Types
|
||||
|
||||
For a list of supported or unsupported `Grant Types` please have a look at the table below.
|
||||
@ -161,7 +389,7 @@ For a list of supported or unsupported `Grant Types` please have a look at the t
|
||||
| Client Credentials | yes |
|
||||
| Device Authorization | under consideration |
|
||||
| Implicit | yes |
|
||||
| JSON Web Token (JWT) Profile | partially |
|
||||
| JSON Web Token (JWT) Profile | yes |
|
||||
| Refresh Token | work in progress |
|
||||
| Resource Owner Password Credentials | no |
|
||||
| Security Assertion Markup Language (SAML) 2.0 Profile | no |
|
||||
@ -197,7 +425,7 @@ 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
|
||||
3. Generate a JWT with the structure below and sign it with the downloaded key
|
||||
4. Send the JWT Base64 encoded to ZITADEL's token endpoint
|
||||
5. Use the received access token
|
||||
|
||||
@ -243,29 +471,23 @@ JWT
|
||||
}
|
||||
```
|
||||
|
||||
> To identify your key, it is necessary that you provide a JWT with a `kid` header claim representing your keyId from the Key JSON:
|
||||
> ```json
|
||||
> {
|
||||
> "alg": "RS256",
|
||||
> "kid": "81693565968772648"
|
||||
> }
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
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
|
||||
```
|
||||
See [JWT Profile Grant on Token Endpoint](architecture#token_endpoint) for usage.
|
||||
|
||||
##### Using JWTs for Client Authentication
|
||||
|
||||
> Not yet supported
|
||||
See how to build a [JWT for client authentication](architecture/#JWT_with_Private_Key) from the downloaded key.
|
||||
|
||||
Find out how to use it on the [token endpoint](architecture#token_endpoint) or the [introspection endpoint](architecture#introspection_endpoint).
|
||||
|
||||
#### Token Exchange
|
||||
|
||||
|
@ -1,78 +0,0 @@
|
||||
4.66 kB service-worker-index.html
|
||||
10.5 kB index.html
|
||||
1.15 kB icons/favicon.ico
|
||||
481 B manifest.json
|
||||
3.17 kB prism.css
|
||||
11.6 kB default-skin/default-skin.css
|
||||
14.8 kB client/client-48a0d285.css
|
||||
3.88 kB client/index-5d76bab7.css
|
||||
4.14 kB photoswipe.css
|
||||
33.9 kB client/client.ea30bda8.js
|
||||
559 B client/inject_styles.5607aec6.js
|
||||
18.1 kB client/index.6f1d050b.js
|
||||
5.54 kB start.json
|
||||
967 B quickstarts.json
|
||||
6.45 kB logos/zitadel-logo-light.svg
|
||||
8.3 kB logos/zitadel-logo-solo-darkdesign.svg
|
||||
18 kB start/index.html
|
||||
14.9 kB img/develop2.png
|
||||
10.1 kB img/projects2.png
|
||||
11.1 kB img/personal2.png
|
||||
7.96 kB quickstarts/index.html
|
||||
15.2 kB use/index.html
|
||||
22.8 kB apis/index.html
|
||||
73.1 kB img/accounts_org_register.png
|
||||
10.3 kB client/[slug]-3cb415b8.css
|
||||
1.52 kB client/index-4d174bf5.css
|
||||
20.7 kB client/[slug].aebb20dc.js
|
||||
4.16 kB client/index.c2043c63.js
|
||||
114 kB architecture/index.html
|
||||
207 kB img/accounts_password.png
|
||||
199 kB img/accounts_page.png
|
||||
899 B tech/angular.svg
|
||||
1.79 kB tech/dart.svg
|
||||
2.29 kB tech/golang.svg
|
||||
200 kB img/accounts_otp_verify.png
|
||||
21.3 kB img/zitadel_software_architecture.png
|
||||
10.4 kB img/zitadel_cluster_architecture.png
|
||||
184 kB administrate/index.html
|
||||
39 kB angular/index.html
|
||||
38.9 kB dart/index.html
|
||||
38.8 kB go/index.html
|
||||
7.37 kB img/zitadel_multicluster_architecture.png
|
||||
31 kB img/console_user_entry.png
|
||||
83.5 kB img/console_admin_entry.png
|
||||
167 kB img/console_admin_system.png
|
||||
129 kB img/console_org_domain_default.png
|
||||
126 kB img/console_org_domain_add.png
|
||||
142 kB img/console_org_domain_added.png
|
||||
126 kB img/console_user_personal_information.png
|
||||
135 kB img/console_org_domain_verify.png
|
||||
52.8 kB img/console_user_personal_info.png
|
||||
15 kB img/console_projects_empty.png
|
||||
40.2 kB img/console_projects_my_first_project.png
|
||||
40.7 kB img/console_org_domain_verified.png
|
||||
178 kB img/console_org_manage_roles_2.png
|
||||
129 kB img/console_org_manage_roles_1.png
|
||||
38.1 kB img/console_org_domain_verify_dns.png
|
||||
112 kB img/console_project_manage_roles_1.png
|
||||
19.5 kB img/console_clients_my_first_spa_wizard_1.png
|
||||
21.6 kB img/console_clients_my_first_spa_wizard_4.png
|
||||
22.3 kB img/console_clients_my_first_spa_wizard_3.png
|
||||
28.3 kB img/console_clients_my_first_spa_config.png
|
||||
27.1 kB img/console_user_list_search.png
|
||||
159 kB img/console_project_manage_roles_2.png
|
||||
25.2 kB img/console_user_list.png
|
||||
16.3 kB img/console_clients_my_first_spa_wizard_2.png
|
||||
38.8 kB img/console_authz_add_1.png
|
||||
77.2 kB administrate.json
|
||||
26.6 kB img/console_authz_overview.png
|
||||
186 kB img/console_user_manage_roles_1.png
|
||||
47.9 kB img/console_user_manage_roles_2.png
|
||||
110 kB img/console_user_create_done.png
|
||||
36.1 kB img/console_authz_add_2.png
|
||||
34.1 kB img/console_authz_add_3.png
|
||||
29.6 kB img/console_user_create_form.png
|
||||
6.53 kB apis.json
|
||||
142 kB img/console_iam_admin_failed.png
|
||||
167 kB img/console_iam_admin_views.png
|
@ -0,0 +1,218 @@
|
||||
---
|
||||
title: ZITADEL Service Users
|
||||
tags: beginner, developer, product manager
|
||||
readingtime: 10min
|
||||
---
|
||||
|
||||
<table class="table-wrapper">
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>Learn the basics about ZITADEL Service Users, how to set them up and authorize with ZITADEL.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Learning Outcomes</td>
|
||||
<td>
|
||||
In this module you will:
|
||||
<ul>
|
||||
<li>Learn about Service Users</li>
|
||||
<li>Create a Service User in ZITADEL Console</li>
|
||||
<li>Authorize a Service User with JWT signed with your private key</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Prerequisites</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>Knowledge of <a href="/oauth-recommended-flows#Our_recommended_authorization_flows">Recommended Authorization Flows</a></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Human vs. Machine
|
||||
|
||||
ZITADEL supports human an machine users. We call human users simply "Users" and machine users "Service Users".
|
||||
|
||||
With Service Users you would typically secure backend services. For example in ZITADEL you would require an authenticated Service User to access the Management API. The main difference between human and machine users is the type of credentials that can be used for authentication: Human users typically logon via an login prompt, but Machine users require a non-interactive logon process.
|
||||
|
||||
### Exercise: Create a Service User
|
||||
|
||||
1. Navigate to Service Users
|
||||
2. Click on **New**
|
||||
3. Enter a user name and a display name
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_serviceusers_create.gif" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_serviceusers_create.gif" itemprop="thumbnail" alt="console_serviceusers_create" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Create new service user</figcaption>
|
||||
</figure>
|
||||
|
||||
### Authenticating a service user
|
||||
|
||||
In ZITADEL we use the `private_jwt` (**“JWT bearer token with private key”**, [RFC7523](https://tools.ietf.org/html/rfc7523)) authorization grant for this non-interactive authentication.
|
||||
|
||||
You need to follow these steps to authenticate a service user and receive a access token:
|
||||
|
||||
1. Generate a private-public key pair in ZITADEL
|
||||
2. Create a JSON Web Token (JWT) and sign with private key
|
||||
3. With this JWT, request an OAuth token from ZITADEL
|
||||
|
||||
With this token you can make subsequent requests, just like a human user.
|
||||
|
||||
### Exercise: Get an access token
|
||||
|
||||
In this exercise we will authenticate a service user and receive an access_token to
|
||||
|
||||
> **Information:** Are you stuck? Don't hesitate to reach out to us on [Github Discussions](https://github.com/caos/zitadel/discussions) or [contact us](https://zitadel.ch/contact/) privately.
|
||||
|
||||
#### 1. Generate a private-public key pair in ZITADEL
|
||||
|
||||
Select your service user and in the section KEYS click **New**. Enter an expiration date and click **Add**. Make sure to download the json by clicking **Download**.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_serviceusers_new_key.gif" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_serviceusers_new_key.gif" itemprop="thumbnail" alt="console_serviceusers_new_key" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Create private key</figcaption>
|
||||
</figure>
|
||||
|
||||
The downloaded json should look something like outlined below. The value of `key` contains the *private* key for your service account. Please make sure to keep this key securely stored and handle with care. The public key is automatically stored in ZITADEL.
|
||||
|
||||
```json
|
||||
{
|
||||
"type":"serviceaccount",
|
||||
"keyId":"100509901696068329",
|
||||
"key":"-----BEGIN RSA PRIVATE KEY----- [...] -----END RSA PRIVATE KEY-----\n",
|
||||
"userId":"100507859606888466"
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Create a JWT and sign with private key
|
||||
|
||||
You need to create a JWT with the following header and payload and sign it with the RS256 algorithm.
|
||||
|
||||
Header
|
||||
```json
|
||||
{
|
||||
"alg": "RS256",
|
||||
"kid":"100509901696068329"
|
||||
}
|
||||
```
|
||||
Make sure to include `kid` in the header with the value of `keyId` from the downloaded JSON.
|
||||
|
||||
Payload
|
||||
```json
|
||||
{
|
||||
"iss": "100507859606888466",
|
||||
"sub": "100507859606888466",
|
||||
"aud": "https://issuer.zitadel.ch",
|
||||
"iat": [Current UTC timestamp, e.g. 1605179982],
|
||||
"exp": [UTC timestamp, max. 1 hour from iat, e.g. 1605183582]
|
||||
}
|
||||
```
|
||||
|
||||
* `iss` represents the requesting party, i.e. the owner of the private key. In this case the value of `userId` from the downloaded JSON.
|
||||
* `sub` represents the application. Set the value also to the value of `userId`
|
||||
* `aud` must be ZITADEL's issuing domain
|
||||
* `iat` is a unix timestamp of the creation signing time of the JWT, e.g. now
|
||||
* `exp` is the unix timestamp of expiry of this assertion. Must be less than 1 hour from `iat`
|
||||
|
||||
Please refer to [JWT_with_Private_Key](/architecture#JWT_with_Private_Key#JWT_with_Private_Keyvate_Key) in the documentation for further information.
|
||||
|
||||
> **Information:** The `exp` claim is currently not validated, but will be with a future release. Make sure that `exp` is less than 1 hour starting from `iat`.
|
||||
|
||||
If you use Go, you might want to use the [provided tool](https://github.com/caos/zitadel-tools) to generate a JWT from the downloaded json. There are many [libraries](https://jwt.io/#libraries-io) to generate and sign JWT.
|
||||
|
||||
#### 3. With this JWT, request an OAuth token from ZITADEL
|
||||
|
||||
With the encoded JWT from the prior step, you will need to craft a POST request to ZITADEL's token endpoint:
|
||||
|
||||
```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:client-assertion-type:jwt-bearer \
|
||||
--data scope='openid profile email' \
|
||||
--data assertion=eyJ0eXAiOiJKV1QiL...
|
||||
```
|
||||
|
||||
* `grant_type` should be set to `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`
|
||||
* `scope` should contain any [Scopes](/architecture#Scopes) you want to include, but must include `openid`. For this example, please include `profile` and `email`
|
||||
* `assertion` is the encoded value of the JWT that was signed with your private key from the prior step
|
||||
|
||||
You should receive a successful response with `access_token`, `token_type` and time to expiry in seconds as `expires_in`.
|
||||
|
||||
```bash
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"access_token": "MtjHodGy4zxKylDOhg6kW90WeEQs2q...",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 43199
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. Verify that you have a valid access toaken
|
||||
|
||||
For this example let's call the userinfo endpoint to verfiy that our access token works.
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url https://api.zitadel.ch/oauth/v2/userinfo \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--header 'Authorization: Bearer MtjHodGy4zxKylDOhg6kW90WeEQs2q...'
|
||||
```
|
||||
You should receive a response with your service user's information.
|
||||
|
||||
```bash
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "MyServiceUser",
|
||||
"preferred_username": "service_user@acme.zitadel.ch",
|
||||
"updated_at": 1616417938
|
||||
}
|
||||
```
|
||||
|
||||
### Knowledge Check
|
||||
|
||||
* To secure backend APIs you can request an API key via ZITADEL's console
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* The JWT header must contain a property `kid` with the value of the key ID
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* After generating a key for your service user, you must download the public key and sign your JWT with the public key
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Solutions
|
||||
</summary>
|
||||
|
||||
* To secure backend APIs you can request an API key via ZITADEL's console
|
||||
- [ ] yes
|
||||
- [x] no (We use **“JWT bearer token with private key”**, [RFC7523](https://tools.ietf.org/html/rfc7523))
|
||||
* The JWT header must contain a property `kid` with the value of the key ID
|
||||
- [x] yes
|
||||
- [ ] no
|
||||
* After generating a key for your service user, you must download the public key and sign your JWT with the public key
|
||||
- [ ] yes
|
||||
- [x] no (The json file contains the private key. Handle with care.)
|
||||
|
||||
</details>
|
||||
|
||||
### Summary
|
||||
|
||||
* With service users you can secure machine-to-machine communication
|
||||
* Because there is no interactive logon, you need to use a JWT signed with your private key to authorize the user
|
||||
* After successful authorization you can use an access token like for human users
|
||||
|
||||
Where to go from here:
|
||||
* Management API
|
||||
* Securing backend API
|
151
site/docs/oauth-recommended-flows/00-oauth-recommended-flows.md
Normal file
@ -0,0 +1,151 @@
|
||||
---
|
||||
title: Recommended authorization flows
|
||||
tags: beginner, developer
|
||||
readingtime: 15min
|
||||
---
|
||||
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Description | Learn about the different authentication flows and which flow we recommend you should use for your application. |
|
||||
| Learning Outcomes | In this module you will: <ul><li>Learn the basics of federated identities</li><li>Understand the basics of OAuth 2.x client profiles and their importance for authorization flows</li><li>Get a recommended flow for Web, Native, User-Agent, and API</li></ul> |
|
||||
| Prerequisites | Basic knowledge about federated identities. |
|
||||
|
||||
### Introduction
|
||||
|
||||
Before we get into setting up our first application within ZITADEL, we need to go through some basics on how to obtain an authorization with OpenID Connect 1.x and OAuth 2.x.
|
||||
|
||||
ZITADEL does not make assumptions about the application type you are about to integrate. Therefore you must qualify and define an appropriate method for your users to gain authorization to access your application (“authentication flow”). Your choice depends on the application’s ability to maintain the confidentiality of client credentials and the technological capabilities of your application. If you choose a deprecated or unfeasible flow to obtain authorization for your application, your users’ credentials may be compromised.
|
||||
|
||||
We invite you to further explore the different authorization flows in the OAuth 2.x standard. For the start we assume that you have a brand-new application (ie. without legacy requirements) and you found an reliable SDK/Library that does the heavy lifting for you.
|
||||
|
||||
So this module will only go over the basics and explain why we recommend the flow “Authorization Flow with PKCE” as default for most applications. We will also cover the case of machine-to-machine communication, ie. where there is no interactive login. Further we will guide you to further reading viable alternatives, if the default flow is not feasible.
|
||||
|
||||
### Basics of Federated Identity
|
||||
|
||||
Although Federated Identities are not a new concept ([RFC 6749](https://tools.ietf.org/html/rfc6749), “The OAuth 2.0 Authorization Framework” was released in 2012) it is important to highlight the difference between the traditional client-server authentication model and the concept of delegated authorization and authentication.
|
||||
|
||||
The aforementioned RFC provides us with some [problems and limitations](https://tools.ietf.org/html/rfc6749#section-1) of the client-server authentication, where a client requests a protected resource on the server by authenticating with the user’s credentials:
|
||||
* Applications need to store users credentials (eg, password) for future use; compromise of any application results in compromise of the end-users credentials
|
||||
* Servers are required to support password authentication
|
||||
* Without means of limiting scope when providing the user’s credentials, the application gains overly broad access to protected resources
|
||||
* Users cannot revoke access for a single application, but only for all by changing credentials
|
||||
|
||||
So what do we want to achieve with delegated authentication?
|
||||
* Instead of implementing authentication on each server and trusting each server:
|
||||
* Users only **authenticate** with a trusted server (ie. ZITADEL), that validates the user’s identity through a challenge (eg, multiple authentication factors) and issues an **ID token** (OpenID Connect 1.x)
|
||||
* Applications have means of **validating the integrity** of presented access and ID tokens
|
||||
* Instead of sending around the user’s credentials:
|
||||
* Clients may access protected resources with an **access token** that is only valid for specific scope and limited lifetime (OAuth 2.x)
|
||||
* Users have to **authorize** applications to access certain [**scopes**](https://docs.zitadel.ch/architecture#Scopes) (eg, email address or custom roles). Applications can request [**claims**](https://docs.zitadel.ch/architecture#Claims) (key:value pairs, eg email address) for the authorized scopes with the access token or ID token from ZITADEL
|
||||
* Access tokens are bearer tokens, meaning that possession of the token provides access to a resource. But the tokens expire frequently and the application must request a new access token via **refresh token** or the user must reauthenticate
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/consulting_federated_identities_basics.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/consulting_federated_identities_basics.png" itemprop="thumbnail" alt="consulting_federated_identities_basics" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Overview federated identities</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
This is where the so-called “flows” come into play: There are a number of different flows on how to handle the process from authentication, over authorization, getting tokens and requesting additional information about the user.
|
||||
|
||||
Maybe interesting to mention is that we are mostly concerned with choosing the right OAuth 2.x flows (alas “authorization”). OpenID Connect extends the OAuth 2.x flow with useful features like endpoint discovery (where to ask), ID Token (who is the user, when and how did she authenticate), and UserInfo Endpoint (getting additional information about the user).
|
||||
|
||||
### Different client profiles
|
||||
|
||||
As mentioned in the beginning of this module, there are two main determinants for choosing the optimal authorization flow:
|
||||
1. Client’s ability to maintain the confidentiality of client credentials
|
||||
2. Technological limitations
|
||||
|
||||
OAuth 2.x defines two [client types](https://tools.ietf.org/html/rfc6749#section-2.1) based on their ability to maintain the confidentiality of their client credentials:
|
||||
* Confidential: Clients capable of maintaining the confidentiality of their credentials (e.g., client implemented on a secure server with restricted access to the client credentials), or capable of secure client authentication using other means.
|
||||
* Public: Clients incapable of maintaining the confidentiality of their credentials (e.g., clients executing on the device used by the resource owner, such as an installed native application or a web browser-based application), and incapable of secure client authentication via any other means.
|
||||
|
||||
The following table gives you a brief overview of different client profiles.
|
||||
|
||||
<table class="table-wrapper">
|
||||
<tr>
|
||||
<th>Confidentiality of client credentials</th>
|
||||
<th>Client profile</th>
|
||||
<th>Examples of clients</th>
|
||||
<tr>
|
||||
<tr>
|
||||
<td rowspan="2">Public</td>
|
||||
<td>User-Agent</td>
|
||||
<td>Single-page web applications (SPA), generally JavaScript executed in Browser</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Native</td>
|
||||
<td>Native, Mobile, or Desktop applications</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">Confidential</td>
|
||||
<td>Web</td>
|
||||
<td>Server-side web applications such as java, .net, …</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Machine-to-Machine</td>
|
||||
<td>APIs, generally services without direct user-interaction at the authorization server</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Our recommended authorization flows
|
||||
|
||||
We recommend using the flow **“Authorization Code with Proof Key of Code Exchange (PKCE)”** ([RFC7636](https://tools.ietf.org/html/rfc7636)) for **User-Agent**, **Native**, and **Web** clients.
|
||||
|
||||
If you don’t have any technical limitations, you should favor the flow Authorization Code with PKCE over other methods. The PKCE part makes the flow resistant against authorization code interception attack as described well in RFC7636.
|
||||
|
||||
*So what about APIs?*
|
||||
|
||||
We recommend using **“JWT bearer token with private key”** ([RFC7523](https://tools.ietf.org/html/rfc7523)) for Machine-to-Machine clients.
|
||||
|
||||
What this means is that you have to send an JWT token, containing the [standard claims for access tokens](https://docs.zitadel.ch/architecture#Claims) and that is signed with your private key, to the token endpoint to request the access token. We will see how this works in another module about Service Accounts.
|
||||
|
||||
If you don’t have any technical limitations, you should prefer this method over other methods.
|
||||
|
||||
A JWT with a private key can also be used with client profile web to further enhance security.
|
||||
|
||||
In case you need alternative flows and their advantages and drawbacks, there will be a module to outline more methods and our recommended fallback strategy per client profile that are available in ZITADEL.
|
||||
|
||||
### Knowledge Check (3)
|
||||
|
||||
* With federated identities the user sends credentials to the server holding the protected resource
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* ZITADEL will discover your client profile automatically and set the correct flow
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* When working with APIs / machine-to-machine communication its recommended to exchange a JWT that is singed with your private key for an access token
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Solutions
|
||||
</summary>
|
||||
|
||||
* With federated identities the user sends credentials to the server holding the protected resource
|
||||
- [ ] yes
|
||||
- [x] no (Users are authenticated against a centralized IDP, only access tokens are send to the requested resources)
|
||||
* ZITADEL will discover your client profile automatically and set the correct flow
|
||||
- [ ] yes
|
||||
- [x] no (ZITADEL does not make any assumptions about your application’s requirements)
|
||||
* When working with APIs / machine-to-machine communication its recommended to exchange a JWT that is singed with your private key for an access token
|
||||
- [x] yes
|
||||
- [ ] no
|
||||
|
||||
</details>
|
||||
|
||||
### Summary (3)
|
||||
|
||||
* Federated Identities solve key problems and challenges with traditional server-client architecture
|
||||
* Use “Authorization Code with Proof Key of Code Exchange (PKCE)” for User-Agent, Native, and Web clients
|
||||
* “JWT bearer token with private key” for Machine-to-Machine clients
|
||||
* There are alternative flows and fallback strategies supported by ZITADEL, if these flows are technically not possible
|
||||
|
||||
Where to go from here
|
||||
* ZITADEL Applications
|
||||
* ZITADEL Service Accounts
|
||||
* Alternative authentication flows (aka. "The Zoo")
|
@ -1,16 +0,0 @@
|
||||
---
|
||||
title: Overview
|
||||
description: ...
|
||||
---
|
||||
|
||||
> All documentations are under active work and subject to change soon!
|
||||
|
||||
This Integration guide gives you recommendations on how to integrate different Clients with **ZITADEL**
|
||||
|
||||
- Single Page Application
|
||||
- Server Side Application
|
||||
- Mobile App
|
||||
- Native App
|
||||
- Reverse Proxy
|
||||
|
||||
For more details about how **ZITADEL** treats [scopes](architecture#Scopes) and [claims](architecture#Claims) see the [documentations](architecture).
|
@ -1,62 +0,0 @@
|
||||
---
|
||||
title: Single Page Application
|
||||
description: ...
|
||||
---
|
||||
|
||||
### SPA Protocol and Flow recommendation
|
||||
|
||||
If your [client](administrate#Clients) is a single page application (SPA) we recommend that you use [Authorization Code](architecture#Authorization_Code) in combination with [Proof Key for Code Exchange](architecture#Proof_Key_for_Code_Exchange).
|
||||
|
||||
This flow has great support with most modern languages and frameworks and is the recommended default.
|
||||
|
||||
> In the OIDC and OAuth world this **client profile** is called "user-agent-based application"
|
||||
|
||||
### Typescript Example
|
||||
|
||||
#### Typescript Authentication Example
|
||||
|
||||
If you use a framework like Angular, Vue, React, ... you can use this code snippet here to integrate **ZITADEL** into you application
|
||||
|
||||
Library used for this example [https://github.com/IdentityModel/oidc-client-js](https://github.com/IdentityModel/oidc-client-js)
|
||||
|
||||
```ts
|
||||
import { UserManager, WebStorageStateStore, User } from 'oidc-client';
|
||||
|
||||
export default class AuthService {
|
||||
private userManager: UserManager;
|
||||
|
||||
constructor() {
|
||||
const ZITADEL_ISSUER_DOMAIN: string = "https://issuer.zitadel.ch";
|
||||
|
||||
const settings: any = {
|
||||
userStore: new WebStorageStateStore({ store: window.localStorage }),
|
||||
authority: ZITADEL_ISSUER_DOMAIN,
|
||||
client_id: 'YOUR_ZITADEL_CLIENT_ID',
|
||||
redirect_uri: 'http://localhost:44444/callback.html',
|
||||
response_type: 'code',
|
||||
scope: 'openid profile',
|
||||
post_logout_redirect_uri: 'http://localhost:44444/',
|
||||
};
|
||||
|
||||
this.userManager = new UserManager(settings);
|
||||
}
|
||||
|
||||
public getUser(): Promise<User | null> {
|
||||
return this.userManager.getUser();
|
||||
}
|
||||
|
||||
public login(): Promise<void> {
|
||||
return this.userManager.signinRedirect();
|
||||
}
|
||||
|
||||
public logout(): Promise<void> {
|
||||
return this.userManager.signoutRedirect();
|
||||
}
|
||||
|
||||
public getAccessToken(): Promise<string> {
|
||||
return this.userManager.getUser().then((data: any) => {
|
||||
return data.access_token;
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
title: Server Side Application
|
||||
description: ...
|
||||
---
|
||||
|
||||
### SSA Protocol and Flow recommendation
|
||||
|
||||
### ASP.net core example
|
||||
|
||||
> Link here
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
title: Mobile Application
|
||||
description: ...
|
||||
---
|
||||
|
||||
### Mobile App Protocol and Flow recommendation
|
||||
|
||||
### Swift Example
|
||||
|
||||
> Link here
|
||||
|
||||
### Java Example
|
||||
|
||||
> Link here
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
title: Native Application
|
||||
description: ...
|
||||
---
|
||||
|
||||
### Native App Protocol and Flow recommendation
|
||||
|
||||
### Electron Example
|
||||
|
||||
> Link here
|
||||
|
||||
### c# Example
|
||||
|
||||
> Link here
|
@ -1,127 +0,0 @@
|
||||
---
|
||||
title: Proxy / WAF
|
||||
description: ...
|
||||
---
|
||||
|
||||
### Proxy Protocol and Flow recommendation
|
||||
|
||||
### Ambassador Example
|
||||
|
||||
According to [https://www.getambassador.io/docs/latest/](https://www.getambassador.io/docs/latest/) Ambassador is a:
|
||||
|
||||
>The Ambassador Edge Stack is a comprehensive, self-service edge stack and API Gateway for Kubernetes built on Envoy Proxy. The shift to Kubernetes and microservices has profound consequences for the capabilities you need at the edge, as well as how you manage the edge. The Ambassador Edge Stack has been engineered with this world in mind.
|
||||
|
||||
You can use **ZITADEL** for Authentication and Authorization with **Ambassador**.
|
||||
|
||||
> The redirect URI is `https://{AMBASSADOR_URL}/.ambassador/oauth2/redirection-endpoint`
|
||||
|
||||
#### Use Ambassador to Authenticate with ZITADEL
|
||||
|
||||
With this you can use Ambassador to initiate the Authorization Code Flow.
|
||||
|
||||
```yaml
|
||||
apiVersion: getambassador.io/v2
|
||||
kind: Filter
|
||||
metadata:
|
||||
name: zitadel-filter
|
||||
namespace: default
|
||||
spec:
|
||||
OAuth2:
|
||||
authorizationURL: https://accounts.zitadel.ch/oauth/v2/authorize
|
||||
clientID: {ZITADEL_GENERATED_CLIENT_ID}
|
||||
secret: {ZITADEL_GENERATED_CLIENT_SECRET}
|
||||
protectedOrigins:
|
||||
- origin: https://{PROTECTED_URL}
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: getambassador.io/v2
|
||||
kind: FilterPolicy
|
||||
metadata:
|
||||
name: zitadel-policy
|
||||
namespace: default
|
||||
spec:
|
||||
rules:
|
||||
- host: "*"
|
||||
path: /backend/get-quote/
|
||||
filters:
|
||||
- name: zitadel-filter
|
||||
```
|
||||
|
||||
#### Use Ambassador to check JWT Bearer Tokens
|
||||
|
||||
If you would like **Ambassador** to verify a JWT token from the authorization header you can do so by configuring **ZITADEL's** endpoints.
|
||||
|
||||
> Make sure that in your client settings of **ZITADEL** the "AuthToken Options" is **JWT** by default **ZITADEL** will use opaque tokens!
|
||||
|
||||
```yaml
|
||||
apiVersion: getambassador.io/v2
|
||||
kind: Filter
|
||||
metadata:
|
||||
name: zitadel-filter
|
||||
namespace: default
|
||||
spec:
|
||||
JWT:
|
||||
jwksURI: "https://api.zitadel.ch/oauth/v2/keys"
|
||||
validAlgorithms:
|
||||
- "RS256"
|
||||
issuer: "https://issuer.zitadel.ch"
|
||||
requireIssuer: true
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: getambassador.io/v2
|
||||
kind: FilterPolicy
|
||||
metadata:
|
||||
name: zitadel-policy
|
||||
namespace: default
|
||||
spec:
|
||||
rules:
|
||||
- host: "*"
|
||||
path: /backend/get-quote/
|
||||
filters:
|
||||
- name: zitadel-filter
|
||||
```
|
||||
|
||||
> Additional Infos can be found with [Ambassadors Documentation](https://www.getambassador.io/docs/latest/howtos/oauth-oidc-auth/)
|
||||
|
||||
### OAuth2 Proxy Example
|
||||
|
||||
[OAuth2-proxy](https://github.com/oauth2-proxy/oauth2-proxy) is a project which allows services to delegate the authentication flow to a IDP, for example **ZITADEL**
|
||||
|
||||
#### OAuth2 Proxy Authentication Example
|
||||
|
||||
```toml
|
||||
provider = "oidc"
|
||||
user_id_claim = "sub" #uses the subject as ID instead of the email
|
||||
provider_display_name = "ZITADEL"
|
||||
redirect_url = "http://127.0.0.1:4180/oauth2/callback"
|
||||
oidc_issuer_url = "https://issuer.zitadel.ch"
|
||||
upstreams = [
|
||||
"https://example.corp.com"
|
||||
]
|
||||
email_domains = [
|
||||
"*"
|
||||
]
|
||||
client_id = "{ZITADEL_GENERATED_CLIENT_ID}"
|
||||
client_secret = "{ZITADEL_GENERATED_CLIENT_SECRET}"
|
||||
pass_access_token = true
|
||||
cookie_secret = "{SUPPLY_SOME_SECRET_HERE}"
|
||||
skip_provider_button = true
|
||||
cookie_secure = false #localdev only false
|
||||
http_address = "127.0.0.1:4180" #localdev only
|
||||
```
|
||||
|
||||
> This was tested with version `oauth2-proxy v6.1.1 (built with go1.14.2)`
|
||||
|
||||
#### OAuth2 Proxy Authorization Example
|
||||
|
||||
> Not yet supported but with the work of [https://github.com/oauth2-proxy/oauth2-proxy/pull/797](https://github.com/oauth2-proxy/oauth2-proxy/pull/797) it should be possible in the future
|
||||
|
||||
### Cloudflare Access Example
|
||||
|
||||
> TODO
|
||||
|
||||
### NGINX Example
|
||||
|
||||
> TODO
|
@ -1,12 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
description: ...
|
||||
---
|
||||
|
||||
### API Protocol and Flow recommendation
|
||||
|
||||
### Go Example
|
||||
|
||||
### .net core Example
|
||||
|
||||
### node.js Example
|
@ -1,100 +0,0 @@
|
||||
---
|
||||
title: Products
|
||||
description: ...
|
||||
---
|
||||
|
||||
### Grafana Example
|
||||
|
||||
**Grafana** defines itself as "The open-source platform for monitoring and observability."
|
||||
|
||||
The source code is provided on [Grafana's Github Repository](https://github.com/grafana/grafana)
|
||||
|
||||
#### Authenticate Grafana with ZITADEL
|
||||
|
||||
To authenticate **Grafana** with ZITADEL you can use the provided **Generic OAuth** plugin.
|
||||
|
||||
> We do not recommend that you rely on `allowed_domain` as means of authorizing subjects, but instead use **ZITADEL's** RBAC Assertion
|
||||
|
||||
1. Create a new project or use an existing one
|
||||
2. Add OpenID Connect / OAuth 2.0 client to the project (See screenshot for settings)
|
||||
3. Add config to your **Grafana** instance and restart it
|
||||
4. Login to **Grafana**
|
||||
|
||||
```ini
|
||||
[auth.generic_oauth]
|
||||
enabled = true
|
||||
name= ZITADEL
|
||||
client_id = {ZITADEL_GENERATED_CLIENT_ID}
|
||||
client_secret = {ZITADEL_GENERATED_CLIENT_SECRET}
|
||||
scopes = openid profile email
|
||||
auth_url = https://accounts.zitadel.ch/oauth/v2/authorize
|
||||
token_url = https://api.zitadel.ch/oauth/v2/token
|
||||
api_url = https://api.zitadel.ch/oauth/v2/userinfo
|
||||
allow_sign_up = true
|
||||
```
|
||||
|
||||
> Grafanas's redirect is URI https://yourdomain.tld/login/generic_oauth
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/grafana_client_settings.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/grafana_client_settings.png" itemprop="thumbnail" alt="Client Settings for Grafana" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Client Settings for Grafana</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
#### Authorizes Users with Roles in Grafana
|
||||
|
||||
**ZITADEL** provides projects with the option to provide Grafana with the users role.
|
||||
|
||||
1. Create Roles (Admin, Editor, Viewer) in **ZITADEL's** project which contains **Grafana**
|
||||
2. Enable "Assert Roles on Authentication" so that the roles are asserted to the userinfo endpoint
|
||||
3. (Optional) Enable "Check roles on Authentication", this will prevent that someone without any role to login **Grafana** via **ZITADEL**
|
||||
4. Append the config below to your **Grafana** instance and reload
|
||||
5. Authorize the necessary users
|
||||
|
||||
```ini
|
||||
[auth.generic_oauth]
|
||||
...
|
||||
role_attribute_path = keys("urn:zitadel:iam:org:project:roles") | contains(@, 'Admin') && 'Admin' || contains(@, 'Editor') && 'Editor' || 'Viewer'
|
||||
...
|
||||
```
|
||||
|
||||
<div class="zitadel-gallery" itemscope itemtype="http://schema.org/ImageGallery">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/grafana_project_settings.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/grafana_project_settings.png" itemprop="thumbnail" alt="Project Settings for Grafana" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Project Settings for Grafana</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/grafana_zitadel_authorization.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/grafana_zitadel_authorization.png" itemprop="thumbnail" alt="Authorization for Grafana Role in ZITADEL" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Authorization for Grafana Role in ZITADEL</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/grafana_login_button.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/grafana_login_button.png" itemprop="thumbnail" alt="Grafana Login" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Grafana Login</figcaption>
|
||||
</figure>
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/grafana_profile_settings.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/grafana_profile_settings.png" itemprop="thumbnail" alt="Grafana with Editor Role mapped from ZITADEL" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Grafana with Editor Role mapped from ZITADEL</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
> Grafana can not directly use ZITADEL delegation feature but normal RBAC works fine
|
||||
> Additional infos can be found in the [Grafana generic OAuth 2.0 documentation](https://grafana.com/docs/grafana/latest/auth/generic-oauth/)
|
||||
|
||||
### ArgoCD Example
|
||||
|
||||
> TODO
|
||||
|
||||
### Kubernetes Example
|
||||
|
||||
> TODO
|
@ -18,17 +18,16 @@ Then go to your [Console Projects](https://console.zitadel.ch/projects) view and
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
Now you can proceed adding [users](administrate#What_are_users) to your organization as well as integrating your applications. We refer to our administration [documentation](administrate#What_are_clients) as well as our [quickstarts](quickstarts) to do so.
|
||||
Now you can proceed adding users to your organization as well as integrating your applications. We refer to our guides as well as our [quickstarts](quickstarts) to do so.
|
||||
|
||||
#### Verify your domain name (optional)
|
||||
|
||||
If you verify a domain you get the benefit that your organisations users can use this domain as the **preferred logonname**. You find a more detailed explanation on [how ZITADEL handles usernames](administrate#How_ZITADEL_handles_usernames) here.
|
||||
The verification process is documented [here](administrate#Verify_a_domain_name)
|
||||
If you verify a domain you get the benefit that your organisations users can use this domain as the **preferred logonname**.
|
||||
|
||||
#### Elect Managers
|
||||
|
||||
ZITADEL allows you to give other users control over ZITADEL Console itself. This can be restricted to some kind of write and/or read. This can be especially useful for directing administration over several users. You can have managers able to edit project settings and others able to create/add users only.
|
||||
Read the [administration](administrate#ZITADEL_Roles) guide for more information.
|
||||
Read the [guides](guides) for more information.
|
||||
|
||||
> Note: ZITADEL Managers are always located on the right sidepanel of console.
|
||||
|
||||
|
47
site/docs/zitadel-applications/00-zitadel-applications.md
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
title: ZITADEL Applications
|
||||
tags: beginner, developer, product owner
|
||||
readingtime: 10min
|
||||
---
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Description | Learn the basics about applications, roles and authorizations, and how projects allow you to group these together. |
|
||||
| Learning Outcomes | In this module you will: <ul><li>Learn about projects and granted projects</li><li>Create a new project</li><li>Creating simple roles and authorizations</li><li>Create an organization grant for your project</li></ul> |
|
||||
| Prerequisites | <ul><li>ZITADEL organizations</li><li>Role Based Access Management (RBAC)</li></ul> |
|
||||
|
||||
### Knowledge Check (4)
|
||||
|
||||
* ...
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* ...
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* ...
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Solutions
|
||||
</summary>
|
||||
|
||||
* ...
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* ...
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* ...
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
|
||||
</details>
|
||||
|
||||
### Summary (4)
|
||||
|
||||
* ...
|
||||
|
||||
Where to go from here:
|
||||
* ...
|
142
site/docs/zitadel-organizations/00-zitadel-organizations.md
Normal file
@ -0,0 +1,142 @@
|
||||
---
|
||||
title: ZITADEL Organizations
|
||||
tags: beginner, administrator, product owner
|
||||
readingtime: 10min
|
||||
---
|
||||
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Description | Learn how ZITADEL is structured around Organizations and how to create your organization and verify a domain to use with that new organization. |
|
||||
| Learning Outcomes | In this module you will: <ul><li>Learn about organizations</li><li>Create a new organization</li><li>Verify your domain name </li></ul> |
|
||||
|Prerequisites|None|
|
||||
|
||||
### What is an organization?
|
||||
|
||||
ZITADEL is organized around the idea that
|
||||
* Multiple organizations share the same system. In this case multiple organizations share the same service, zitadel.ch
|
||||
* organizations can grant each other rights to self-manage certain aspects of the IAM (eg, roles for access management)
|
||||
* organizations are vessels for users and projects
|
||||
|
||||
<div class="figure-wrapper">
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<img src="img/zitadel_organizations.png" itemprop="thumbnail" alt="Zitadel Organizations" />
|
||||
<figcaption itemprop="caption description">Overview ZITADEL Organizations</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
Organizations in ZITADEL are therefore comparable to tenants of a system or organizational units of a directory based system.
|
||||
|
||||
You can use projects within your organization to manage the security context of closely related components, such as roles, grants and authorizations for multiple clients. You can set up multiple projects within your organization.
|
||||
|
||||
ZITADEL allows you to give other organizations permission to manage certain aspects of a project within your organization on their own. This means you could set up a project with roles that should exist within your service/software, but allow another organization to allocate the roles to users within their own organization. As a service provider, you will find this feature useful, as it allows you to establish a self-service culture for your business customers.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/zitadel_organization_grant.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/zitadel_organization_grant.png" itemprop="thumbnail" alt="Zitadel Organization grant" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization Grant</figcaption>
|
||||
</figure>
|
||||
|
||||
Each organization has its own pool of usernames, which includes human and service users, for its domain (`{username}@{domainname}.{zitadeldomain}`). A username is unique within your organization. You can configure ZITADEL to use your own domain, and simplify user experience (`{loginname}@{yourdomain.tld}`).
|
||||
|
||||
There are several more modules in our documentation to go into more detail regarding organization management, projects, clients, and users. But first let’s create a new organization and verify your domain name.
|
||||
|
||||
### Exercise - Create a new organization
|
||||
|
||||
To register your organization and create a user for ZITADEL, visit zitadel.ch or directly https://accounts.zitadel.ch/register/org and fill in the required information.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_register.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_register.png" itemprop="thumbnail" alt="Register Org" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Register new Organization</figcaption>
|
||||
</figure>
|
||||
|
||||
If you already have an existing login for zitadel.ch, you need to visit the console, then click on your organization’s name in the upper left corner, and then select “New organization”.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_org_select.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_org_select.png" itemprop="thumbnail" alt="console_org_select" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Select Organization</figcaption>
|
||||
</figure>
|
||||
|
||||
### How ZITADEL handles usernames
|
||||
|
||||
As we mentioned before, each organization has its own pool of usernames, which includes human and service.
|
||||
|
||||
This means that, for example a user with the username road.runner, can only exist once in an organization called ACME. ZITADEL will automatically generate a "logonname" for each consisting of `{username}@{domainname}.{zitadeldomain}`, in our example road.runner@acme.zitadel.ch.
|
||||
|
||||
When you verify your domain name, then ZITADEL will generate additional logonames for each user with the verified domain. If our example organization would own the domain acme.ch and verify within the organization ACME, then the resulting logonname in our example would be road.runner@acme.ch in addition to the already generated road.runner@acme.zitadel.ch. The user can now use either logonname to authenticate with your application.
|
||||
|
||||
### Domain verification and primary domain
|
||||
|
||||
Once you have successfully registered your organization, ZITADEL will automatically generate a domain name for your organization (eg, acme.zitadel.ch). Users that you create within your organization will be suffixed with this domain name.
|
||||
|
||||
You can improve the user experience, by suffixing users with a domain name that is in your control. For that you can prove the ownership of your domain, by DNS or HTTP challenge.
|
||||
|
||||
An organization can have multiple domain names, but only one domain can be primary. The primary domain defines which login name ZITADEL displays to the user, and what information gets asserted in access_tokens (`preferred_username`).
|
||||
|
||||
Please note that domain verification also removes the logonname from all users, who might have used this combination in the global organization (ie. users not belonging to a specific organization). Relating to our example with acme.ch: If a user ‘coyote’ exists in the global organization with the logonname coyote@acme.ch, then after verification of acme.ch, this logonname will be replaced with `coyote@{randomvalue.tld}`. ZITADEL will notify users affected by this change.
|
||||
|
||||
|
||||
|
||||
### Exercise - Verify your domain name
|
||||
|
||||
1. Browse to your organization
|
||||
2. Click **Add Domain**
|
||||
3. To start the domain verification click the domain name and a dialog will appear, where you can choose between DNS or HTTP challenge methods.
|
||||
4. For example, create a TXT record with your DNS provider for the used domain and click verify. ZITADEL will then proceed an check your DNS.
|
||||
5. When the verification is successful you have the option to activate the domain by clicking **Set as primary**
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_verify_domain.gif" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_verify_domain.gif" itemprop="thumbnail" alt="console_verify_domain" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Verify Domain</figcaption>
|
||||
</figure>
|
||||
|
||||
> **_Please note:_** Do not delete the verification code, as ZITADEL will re-check the ownership of your domain from time to time
|
||||
|
||||
### Knowledge Check
|
||||
|
||||
* Users exist only within projects or clients
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* User can only login with `{username}@{domainname}.{zitadeldomain}`
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* You can delegate access management self-service to another organization
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Solutions
|
||||
</summary>
|
||||
|
||||
* Users exist only within projects or clients
|
||||
- [ ] yes
|
||||
- [x] no (users exist within organizations)
|
||||
* User can only login with `{username}@{domainname}.{zitadeldomain}`
|
||||
- [ ] yes
|
||||
- [x] no (You can validate your own domain and login with `{loginname}@{yourdomain.tld}`)
|
||||
* You can delegate access management self-service to another organization
|
||||
- [x] yes
|
||||
- [ ] no
|
||||
|
||||
</details>
|
||||
|
||||
### Summary
|
||||
|
||||
* Create your organization and a new user by visiting zitadel.ch
|
||||
* Organizations are the top-most vessel for your IAM objects, such as users or projects
|
||||
* Verify your domain in the Console to improve user experience; remember to not delete the verification code to allow recheck of ownership
|
||||
* You can delegate certain aspects of your IAM to other organizations for self-service
|
||||
|
||||
Where to go from here:
|
||||
* Create a project
|
||||
* Setup Passwordless MFA
|
||||
* Manage ZITADEL Roles
|
||||
* Grant roles to other organizations or users
|
195
site/docs/zitadel-projects/00-zitadel-projects.md
Normal file
@ -0,0 +1,195 @@
|
||||
---
|
||||
title: ZITADEL Projects
|
||||
tags: beginner, administrator, product owner
|
||||
readingtime: 10min
|
||||
---
|
||||
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Description | Learn the basics about applications, roles and authorizations, and how projects allow you to group these together. |
|
||||
| Learning Outcomes | In this module you will: <ul><li>Learn about projects and granted projects</li><li>Create a new project</li><li>Creating simple roles and authorizations</li><li>Create an organization grant for your project</li></ul> |
|
||||
| Prerequisites | <ul><li>ZITADEL organizations</li><li>Role Based Access Management (RBAC)</li></ul> |
|
||||
|
||||
### What is a project?
|
||||
|
||||
The idea of projects is to have a vessel for all components who are closely related to each other. Multiple projects can exist within an organization.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/zitadel_organization_grant.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/zitadel_organization_grant.png" itemprop="thumbnail" alt="Zitadel Organization grant" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization Grant</figcaption>
|
||||
</figure>
|
||||
|
||||
All applications within a project share the same roles, grants, and authorizations:
|
||||
|
||||
* **Applications** is your software that initiates the authorization flow. This could be a web app and a mobile app that share the same roles.
|
||||
* **Roles** are a means of managing user access rights for a project.
|
||||
* **Authorizations** define which users have which roles. Authorizations are also called “user grants”.
|
||||
* **Granted Organizations** can manage selected roles for your project on their own.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_projects_overview.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_projects_overview.png" itemprop="thumbnail" alt="console_projects_overview.png" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization Grant</figcaption>
|
||||
</figure>
|
||||
|
||||
The goal of this module is to give you an overview, but not dive too deep into details around managing access rights and delegating management of roles to third parties. So let’s create a straightforward example project first.
|
||||
|
||||
### Exercise - Create a simple project
|
||||
|
||||
Visit https://console.zitadel.ch/projects or select “Projects” within your organization, then click the button to create a new project.
|
||||
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_projects_empty.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_projects_empty.png" itemprop="thumbnail" alt="console_projects_empty.png" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Empty Project</figcaption>
|
||||
</figure>
|
||||
|
||||
Enter the name “ My first project” and continue.
|
||||
|
||||
Let’s make this more interesting and add some basic roles and authorizations to your project and then confirm the scope of the roles and authorizations.
|
||||
|
||||
Jump to the section ROLES and create two new roles with the following values
|
||||
|
||||
* Key: reader
|
||||
* Display Name: Reader
|
||||
* Group: user
|
||||
|
||||
and
|
||||
|
||||
* Key: editor
|
||||
* Display Name: Editor
|
||||
* Group: user
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_projects_add_new_roles.gif" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_projects_add_new_roles.gif" itemprop="thumbnail" alt="console_projects_add_new_roles" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Add New Roles</figcaption>
|
||||
</figure>
|
||||
|
||||
Now, you can add roles to your own user, or you can create a new user. To create a new user, go to Users and click “New”. Enter the required contact details and save by clicking “Create”.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_users_create_new_user.gif" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_users_create_new_user.gif" itemprop="thumbnail" alt="console_users_create_new_user" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Create new user</figcaption>
|
||||
</figure>
|
||||
|
||||
To grant users certain roles, you need to create authorizations. Go back to the project, and jump to the section AUTHORIZATIONS.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_projects_create_authorization.gif" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_projects_create_authorization.gif" itemprop="thumbnail" alt="console_projects_create_authorization" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Create Authorization</figcaption>
|
||||
</figure>
|
||||
|
||||
You can verify the role grant on the user. Select Users from the navigation menu and click on the user Coyote. Scroll down to the section AUTHORIZATION, there you should be able to verify that the user has the role ‘reader’ for your project ‘My first project’.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_projects_authorization_created.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_projects_authorization_created.png" itemprop="thumbnail" alt="console_projects_authorization_created" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Verify your authorization</figcaption>
|
||||
</figure>
|
||||
|
||||
Now create another project (eg. “My second project”) and verify that there are no roles or authorizations on your second project.
|
||||
|
||||
### What is a granted project?
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/zitadel_organization_grant.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/zitadel_organization_grant.png" itemprop="thumbnail" alt="Zitadel Organization grant" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Organization Grant</figcaption>
|
||||
</figure>
|
||||
|
||||
With ZITADEL you can grant selected roles within your project to an organization. The receiving organization can then create authorizations for their users on their own (self-service).
|
||||
|
||||
An example could be a service provider that offers a SaaS solution that has different permissions for employees working in Sales and Accounting. As soon as a new client purchases the service, the provider could grant the roles ‘sales’ and ‘accounting’ to that organization, allowing them to self-manage how they want to allocate the roles to their users.
|
||||
|
||||
The process of assigning certain roles by default or according to rules can be further automated by utilizing Service Users in the service provider’s business process.
|
||||
|
||||
Obviously, your organization can grant projects and receive projects. When you are granting, then the receiving organization will be displayed in the section GRANTED ORGANIZATIONS of your project.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_projects_granted.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_projects_granted.png" itemprop="thumbnail" alt="console_projects_granted" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Project granted to organization</figcaption>
|
||||
</figure>
|
||||
|
||||
A granted project, on the other hand, belongs to a third party, granting you some rights to manage certain roles of their project. ZITADEL Console shows granted projects in a dedicated navigation menu, to clearly separate from your organization’s projects.
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/console_granted_projects_overview.png" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/console_granted_projects_overview.png" itemprop="thumbnail" alt="console_granted_projects_overview" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Granted Projects Overview</figcaption>
|
||||
</figure>
|
||||
|
||||
Please note that you can also grant selected roles of a project to an individual user, instead of an organization. We will discuss this in more detail in a later section.
|
||||
|
||||
### Exercise - Grant a project
|
||||
|
||||
1. Visit the project that you have created before, then in the section GRANTED ORGANIZATIONS click New.
|
||||
2. Enter the domain ‘acme.zitadel.ch’, search the organization and continue to the next step.
|
||||
3. Select some roles you would like to grant to the organization ACME and confirm.
|
||||
4. You should now see ACME in the section GRANTED ORGANIZATIONS
|
||||
|
||||
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<a href="img/projects_create_org_grant_caos2acme.gif" itemprop="contentUrl" data-size="1920x1080">
|
||||
<img src="img/projects_create_org_grant_caos2acme.gif" itemprop="thumbnail" alt="projects_create_org_grant_caos2acme" />
|
||||
</a>
|
||||
<figcaption itemprop="caption description">Grant a project</figcaption>
|
||||
</figure>
|
||||
|
||||
|
||||
### Knowledge Check (2)
|
||||
|
||||
* You can setup multiple projects within an organization to manage scope
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* Authorizations are define more detailed access rights within your application
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
* Your projects as well as projects granted to your organization are visible within the Tab Projects of your organization
|
||||
- [ ] yes
|
||||
- [ ] no
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
Solutions
|
||||
</summary>
|
||||
|
||||
* You can setup multiple projects within an organization to manage scope
|
||||
- [x] yes
|
||||
- [ ] no
|
||||
* Authorizations are define more detailed access rights within your application
|
||||
- [ ] yes
|
||||
- [x] no (Authorizations link users to certain roles)
|
||||
* Your projects as well as projects granted to your organization are visible within the Tab Projects of your organization
|
||||
- [ ] yes
|
||||
- [x] no (Projects and Granted Projects are shown on different tabs)
|
||||
|
||||
</details>
|
||||
|
||||
### Summary (2)
|
||||
|
||||
* Manage scope of roles, authorizations and applications with projects
|
||||
* Create and assign roles to users of your organization within your project
|
||||
* Use project grants to enable other organizations to self-manage access rights (roles) to your applications
|
||||
|
||||
Where to go from here:
|
||||
* Manage roles for your project
|
||||
* Grant roles to other organizations or users
|
||||
* Service Users
|
||||
* Manage IAM Roles
|
||||
* Setup a SaaS Application with granted projects (Learning Path)
|
12
site/guides/000-zitadel-organizations.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
title: ZITADEL organizations
|
||||
subtitle: Get to know ZITADEL
|
||||
img: logos/zitadel-logo-solo-darkdesign.svg
|
||||
date: 29 January 2021
|
||||
readingtime: 5min
|
||||
route: zitadel-organizations
|
||||
visible: true
|
||||
tags: beginner, developer
|
||||
---
|
||||
|
||||
Learn how **ZITADEL** is structured around Organizations and how to create your organization and verify a domain to use with that new organization.
|
12
site/guides/100-zitadel-projects.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
title: ZITADEL Projects
|
||||
subtitle: Get to know ZITADEL
|
||||
img: logos/zitadel-logo-solo-darkdesign.svg
|
||||
date: 12. March 2021
|
||||
readingtime: 10min
|
||||
route: zitadel-projects
|
||||
visible: true
|
||||
tags: beginner, administrator, product owner
|
||||
---
|
||||
|
||||
Learn the basics about applications, roles and authorizations, and how projects allow you to group these together.
|
12
site/guides/200-oauth-recommended-flows.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
title: OAuth recommended flows
|
||||
subtitle: OAuth
|
||||
img: tech/oauth.svg
|
||||
date: 12. March 2021
|
||||
readingtime: 15min
|
||||
route: oauth-recommended-flows
|
||||
visible: true
|
||||
tags: beginner, developer
|
||||
---
|
||||
|
||||
Learn about the different authentication flows and which flow we recommend you should use for your application.
|
12
site/guides/300-guide-gtnz-service-users.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Service users
|
||||
subtitle: Create service user and authorize them for ZITADEL
|
||||
img: logos/zitadel-logo-solo-darkdesign.svg
|
||||
date: 08. April 2021
|
||||
readingtime: 10min
|
||||
route: guide-gtnz-service-users
|
||||
visible: true
|
||||
tags: beginner, developer, product manager
|
||||
---
|
||||
|
||||
Learn the basics about ZITADEL Service Users, how to set them up and authorize with ZITADEL.
|
10017
site/package-lock.json
generated
@ -18,7 +18,7 @@
|
||||
"compression": "^1.7.4",
|
||||
"golden-fleece": "^1.0.9",
|
||||
"highlight.js": "^10.5.0",
|
||||
"marked": "^1.2.8",
|
||||
"marked": "^2.0.0",
|
||||
"polka": "^0.5.2",
|
||||
"prismjs": "^1.23.0",
|
||||
"sirv": "^1.0.11"
|
||||
@ -35,10 +35,10 @@
|
||||
"@rollup/plugin-node-resolve": "^11.1.1",
|
||||
"@rollup/plugin-replace": "^2.2.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^2.38.4",
|
||||
"rollup-plugin-svelte": "^7.0.0",
|
||||
"rollup": "^2.41.0",
|
||||
"rollup-plugin-svelte": "^7.1.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"sapper": "^0.28.10",
|
||||
"svelte": "^3.32.1"
|
||||
"sapper": "^0.29.1",
|
||||
"svelte": "^3.35.0"
|
||||
}
|
||||
}
|
||||
|
@ -358,7 +358,11 @@
|
||||
padding: 0.3rem 0.8rem 0.3rem;
|
||||
margin: 0 0.2rem;
|
||||
top: -0.1rem;
|
||||
background: var(--back-api);
|
||||
background: #2a2f45;
|
||||
}
|
||||
|
||||
.content :global(p) :global(code) {
|
||||
border: 1px solid #ffffff20;
|
||||
}
|
||||
|
||||
.content :global(pre) :global(code) {
|
||||
@ -408,6 +412,7 @@
|
||||
|
||||
section :global(p) {
|
||||
margin: 1em 0;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
small {
|
||||
|
@ -314,7 +314,7 @@
|
||||
<header class:visible="{visible || open}">
|
||||
<nav>
|
||||
<a
|
||||
rel="prefetch"
|
||||
sapper:prefetch
|
||||
href="."
|
||||
class="home"
|
||||
title="{title}"
|
||||
|
@ -11,8 +11,8 @@
|
||||
<li><a href={external}><slot></slot></a></li>
|
||||
{:else}
|
||||
{#if prefetch}
|
||||
<li class:active="{`${$current}` === segment || active }"><a rel="prefetch" sapper:prefetch href={segment}><i class="bars las la-bars"></i><slot></slot></a></li>
|
||||
<li class:active="{`${$current}` === segment || active }"><a sapper:prefetch href={segment}><i class="bars las la-bars"></i><slot></slot></a></li>
|
||||
{:else}
|
||||
<li class:active="{`${$current}` === segment || active }"><a rel="prefetch" href={segment}><i class="bars las la-bars"></i><slot></slot></a></li>
|
||||
<li class:active="{`${$current}` === segment || active }"><a sapper:prefetch href={segment}><i class="bars las la-bars"></i><slot></slot></a></li>
|
||||
{/if}
|
||||
{/if}
|
@ -19,8 +19,7 @@
|
||||
<Nav title="Zitadel docs" {segment} {page} logo="logos/zitadel-logo-light.svg">
|
||||
<NavItem segment="start" prefetch>Get started</NavItem>
|
||||
<NavItem segment="quickstarts">Quickstarts</NavItem>
|
||||
<!-- <NavItem segment="guides">Guides</NavItem> -->
|
||||
<NavItem segment="administrate" prefetch>Administrate</NavItem>
|
||||
<NavItem segment="guides" prefetch>Guides</NavItem>
|
||||
<NavItem segment="apis" prefetch>APIs</NavItem>
|
||||
<NavItem segment="architecture" prefetch>Architecture</NavItem>
|
||||
<NavItem segment="use" prefetch>Manual</NavItem>
|
||||
|
59
site/src/routes/guides/_guides.js
Normal file
@ -0,0 +1,59 @@
|
||||
import fs from 'fs';
|
||||
import marked from 'marked';
|
||||
import path from 'path';
|
||||
|
||||
import { SLUG_PRESERVE_UNICODE } from '../../../config';
|
||||
import { highlight } from '../../utils/highlight';
|
||||
import { extract_frontmatter, link_renderer } from '../../utils/markdown.js';
|
||||
import { makeSlugProcessor } from '../../utils/slug';
|
||||
|
||||
const makeSlug = makeSlugProcessor(SLUG_PRESERVE_UNICODE);
|
||||
|
||||
export default function get_guides() {
|
||||
return fs
|
||||
.readdirSync('guides')
|
||||
.map(file => {
|
||||
if (path.extname(file) !== '.md') return;
|
||||
|
||||
const match = /^([0-9]+)-(.+)\.md$/.exec(file);
|
||||
if (!match) throw new Error(`Invalid filename '${file}'`);
|
||||
|
||||
const [, order, slug] = match;
|
||||
|
||||
const markdown = fs.readFileSync(`guides/${file}`, 'utf-8');
|
||||
|
||||
const { content, metadata } = extract_frontmatter(markdown);
|
||||
|
||||
const renderer = new marked.Renderer();
|
||||
|
||||
renderer.link = link_renderer;
|
||||
|
||||
renderer.code = highlight;
|
||||
|
||||
renderer.heading = (text, level, rawtext) => {
|
||||
const fragment = makeSlug(rawtext);
|
||||
|
||||
return `
|
||||
<h${level}>
|
||||
<span id="${fragment}" class="offset-anchor"></span>
|
||||
<a href="guides#${fragment}" class="anchor" aria-hidden="true"></a>
|
||||
${text}
|
||||
</h${level}>`;
|
||||
};
|
||||
|
||||
const answer = marked(
|
||||
content.replace(/^\t+/gm, match => match.split('\t').join(' ')),
|
||||
{ renderer }
|
||||
);
|
||||
|
||||
const fragment = makeSlug(slug);
|
||||
|
||||
return {
|
||||
fragment,
|
||||
order,
|
||||
answer,
|
||||
metadata
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.order - b.order);
|
||||
}
|
25
site/src/routes/guides/index.json.js
Normal file
@ -0,0 +1,25 @@
|
||||
import send from '@polka/send';
|
||||
|
||||
import get_guides from './_guides.js';
|
||||
|
||||
let json;
|
||||
|
||||
export function get(req, res) {
|
||||
if (!json || process.env.NODE_ENV !== 'production') {
|
||||
const qss = get_guides()
|
||||
.map(qs => {
|
||||
return {
|
||||
fragment: qs.fragment,
|
||||
answer: qs.answer,
|
||||
metadata: qs.metadata
|
||||
};
|
||||
});
|
||||
|
||||
json = JSON.stringify(qss);
|
||||
}
|
||||
|
||||
send(res, 200, json, {
|
||||
'Content-Type': 'application/json',
|
||||
'Cache-Control': `max-age=${5 * 60 * 1e3}` // 5 minutes
|
||||
});
|
||||
}
|
166
site/src/routes/guides/index.svelte
Normal file
@ -0,0 +1,166 @@
|
||||
<script context="module">
|
||||
export async function preload() {
|
||||
const qss = await this.fetch(`guides.json`).then(r => r.json());
|
||||
return { qss };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
const description = "Guides ZITADEL";
|
||||
export let qss;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>ZITADEL Guides</title>
|
||||
|
||||
<meta name="twitter:title" content="Guides ZITADEL">
|
||||
<meta name="twitter:description" content={description}>
|
||||
<meta name="Description" content={description}>
|
||||
</svelte:head>
|
||||
|
||||
<div class='guides stretch'>
|
||||
<h1>Guides ZITADEL</h1>
|
||||
{#each qss as qs}
|
||||
{#if qs.metadata.visible == 'true'}
|
||||
<article class='guide'>
|
||||
<div>
|
||||
<p class="sub">{qs.metadata.subtitle}</p>
|
||||
<h2>
|
||||
<span id={qs.fragment} class="offset-anchor"></span>
|
||||
<a class="anchor" sapper:prefetch href='guides#{qs.fragment}' title='{qs.title}'><i class="las la-link"></i></a>
|
||||
{qs.metadata.title}
|
||||
</h2>
|
||||
<p>{@html qs.answer}</p>
|
||||
<a class="link" href="{qs.fragment}" sapper:prefetch>Read Guide <i class="las la-arrow-right"></i></a>
|
||||
<p class="info">{qs.metadata.date} • {qs.metadata.readingtime}</p>
|
||||
</div>
|
||||
<img src={qs.metadata.img} alt="article img" />
|
||||
</article>
|
||||
{/if}
|
||||
{/each}
|
||||
<p class="disclaimer">See also our Github page <a href="https://github.com/caos/zitadel" rel="external">ZITADEL </a> for questions regarding the sourcecode.</p></div>
|
||||
|
||||
<style>
|
||||
.guides {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: 1em;
|
||||
min-height: calc(100vh - var(--nav-h));
|
||||
padding: var(--top-offset) var(--side-nav) 6rem var(--side-nav);
|
||||
max-width: var(--main-width);
|
||||
margin: 0 auto 0 auto;
|
||||
}
|
||||
|
||||
h2 {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
color: white;
|
||||
max-width: 18em;
|
||||
font-size: var(--h3);
|
||||
font-weight: 400;
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.guide {
|
||||
margin: 3.2rem 0 1rem 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.guide .anchor {
|
||||
position: absolute;
|
||||
display: block;
|
||||
background-size: 30px 30px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
left: -1.3em;
|
||||
opacity: 0;
|
||||
color: white;
|
||||
transition: opacity 0.2s;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
h2:hover .anchor {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.guide img {
|
||||
max-width: 150px;
|
||||
max-height: 150px;
|
||||
object-fit: contain;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.guide .sub {
|
||||
font-size: 12px;
|
||||
font-size: bold;
|
||||
text-transform: uppercase;
|
||||
color: var(--second);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.guide .info {
|
||||
font-size: 12px;
|
||||
font-size: bold;
|
||||
text-transform: uppercase;
|
||||
color: var(--dark-text);
|
||||
margin: 1rem 0 0 0;
|
||||
}
|
||||
|
||||
.guide .link,
|
||||
.guide .link i{
|
||||
color: var(--prime);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.guide:first-child {
|
||||
margin: 0 0 2rem 0;
|
||||
padding: 0 0 4rem 0;
|
||||
border-bottom: var(--border-w) solid #6767785b; /* based on --second */
|
||||
}
|
||||
.guide:first-child h2 {
|
||||
font-size: 4rem;
|
||||
font-weight: 400;
|
||||
color: var(--second);
|
||||
}
|
||||
|
||||
.guide p {
|
||||
font-size: var(--h5);
|
||||
max-width: 30em;
|
||||
color: var(--dark-text);
|
||||
}
|
||||
:global(.guides .guide ul) {
|
||||
margin-left: 3.2rem;
|
||||
}
|
||||
.guides :global(.anchor) {
|
||||
top: calc((var(--h3) - 24px) / 2);
|
||||
}
|
||||
|
||||
.guide:last-child {
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.guide {
|
||||
flex-direction: column-reverse;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.guide img {
|
||||
max-height: 180px;
|
||||
max-width: 180px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.guides :global(.anchor) {
|
||||
transform: scale(0.6);
|
||||
opacity: 1;
|
||||
left: -1.0em;
|
||||
}
|
||||
}
|
||||
|
||||
.disclaimer {
|
||||
margin-top: 100px;
|
||||
}
|
||||
</style>
|
@ -38,11 +38,8 @@
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.doc-container .doc .text{
|
||||
top: 180px;
|
||||
}
|
||||
|
||||
.doc-container .doc .text p{
|
||||
max-width: 500px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
@ -56,6 +53,7 @@
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
margin: .5rem 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.doc-container .doc .text .logo-cloud {
|
||||
@ -135,7 +133,6 @@
|
||||
display: flex;
|
||||
margin: 1rem;
|
||||
flex: 1 0 auto;
|
||||
max-height: 350px;
|
||||
transition: box-shadow .2 ease;
|
||||
}
|
||||
|
||||
@ -206,22 +203,28 @@
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="angular">Single Page Applications (Angular)</a>
|
||||
<a class="link" href="go">Serverside rendered Applications</a>
|
||||
<a class="link" href="flutter">Native Applications (Flutter)</a>
|
||||
<a class="link" href="oauth2-proxy">OAuth2 Proxy</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
<div class="text">
|
||||
<h4>Administration</h4>
|
||||
<p>Learn how to manage your data and role associations in ZITADEL</p>
|
||||
<a href="administrate">Learn more<i class="las la-arrow-right"></i></a>
|
||||
<h4>Guides</h4>
|
||||
<p>Read our guides on how to manage your data and role associations in ZITADEL and on what we recommend.</p>
|
||||
<div class="logo-cloud">
|
||||
<img src="logos/zitadel-logo-solo-darkdesign.svg" alt="zitadel" />
|
||||
<img src="tech/oauth.svg" alt="oauth" />
|
||||
</div>
|
||||
|
||||
<a href="guides">Learn more<i class="las la-arrow-right"></i></a>
|
||||
|
||||
<p class="section">In this section</p>
|
||||
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="administrate#Organizations">Manage Organisations</a>
|
||||
<a class="link" href="administrate#Projects">Manage Projects</a>
|
||||
<a class="link" href="zitadel-organizations">ZITADEL Organizations</a>
|
||||
<a class="link" href="zitadel-projects">ZITADEL Projects</a>
|
||||
<a class="link" href="oauth-recommended-flows">Recommended OAuth Flows</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Quickstarts ZITADEL</title>
|
||||
<title>ZITADEL Quickstarts</title>
|
||||
|
||||
<meta name="twitter:title" content="Quickstarts ZITADEL">
|
||||
<meta name="twitter:description" content={description}>
|
||||
@ -140,7 +140,19 @@
|
||||
.quickstart:last-child {
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.quickstart {
|
||||
flex-direction: column-reverse;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.quickstart img {
|
||||
max-height: 180px;
|
||||
max-width: 180px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.quickstarts :global(.anchor) {
|
||||
transform: scale(0.6);
|
||||
opacity: 1;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { files, shell, timestamp } from '@sapper/service-worker';
|
||||
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
const ASSETS = `cache${timestamp}`;
|
||||
|
||||
// `shell` is an array of all the files generated by the bundler,
|
||||
|
@ -600,3 +600,6 @@ input[type="checkbox"]:checked::after {
|
||||
width: 150px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: var(--linemax);}
|
BIN
site/static/img/angular/app-create-light.png
Normal file
After Width: | Height: | Size: 175 KiB |
BIN
site/static/img/angular/app-screen.png
Normal file
After Width: | Height: | Size: 107 KiB |
BIN
site/static/img/console_granted_projects_overview.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
site/static/img/console_org_register.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
site/static/img/console_org_select.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
site/static/img/console_projects_add_new_roles.gif
Normal file
After Width: | Height: | Size: 5.8 MiB |
BIN
site/static/img/console_projects_authorization_created.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
site/static/img/console_projects_create_authorization.gif
Normal file
After Width: | Height: | Size: 9.7 MiB |
BIN
site/static/img/console_projects_granted.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
site/static/img/console_projects_overview.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
site/static/img/console_serviceusers_create.gif
Normal file
After Width: | Height: | Size: 2.6 MiB |
BIN
site/static/img/console_serviceusers_new_key.gif
Normal file
After Width: | Height: | Size: 7.9 MiB |
BIN
site/static/img/console_users_create_new_user.gif
Normal file
After Width: | Height: | Size: 9.6 MiB |
BIN
site/static/img/console_verify_domain.gif
Normal file
After Width: | Height: | Size: 17 MiB |
BIN
site/static/img/consulting_federated_identities_basics.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
site/static/img/projects_create_org_grant_caos2acme.gif
Normal file
After Width: | Height: | Size: 7.5 MiB |
BIN
site/static/img/zitadel_organization_grant.png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
site/static/img/zitadel_organizations.png
Normal file
After Width: | Height: | Size: 86 KiB |
61
site/static/tech/oauth.svg
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" x="0px" y="0px" width="598.48541" height="599.83948" viewBox="0 0 598.486 671.089" enable-background="new 0 0 598.486 671.089">
|
||||
<g transform="translate(0,35.625)">
|
||||
<path fill="#fff" d="M 277.7249,0.87048682 C 410.2899,-8.3215132 498.1879,56.550487 548.4459,135.58949 C 573.6459,175.21949 598.3709,235.40949 598.4849,297.25249 C 598.6069,364.44649 576.8389,422.63549 548.4459,465.33049 C 519.2639,509.21349 481.5199,545.45849 434.2559,569.25749 C 355.2499,609.04049 244.8359,610.12849 172.5149,571.82349 C 91.972897,529.16549 30.046897,468.27849 7.0028967,362.68749 C -2.2191033,320.43149 -3.2791033,265.83249 9.5688967,218.98749 C 12.583897,207.99849 18.062897,196.43349 22.399897,185.62849 C 43.241897,133.70449 78.716897,88.552487 122.4769,57.323487 C 140.0609,44.775487 161.3929,32.295487 180.2139,23.964487 C 203.6319,13.599487 243.0599,3.2734868 277.7249,0.87048682 z" />
|
||||
<path fill="#000" d="M 529.1839,304.72449 C 529.1839,430.01249 427.6179,531.57149 302.3319,531.57149 C 177.0459,531.57149 75.481897,430.01249 75.481897,304.72449 C 75.481897,179.43949 177.0459,77.872487 302.3319,77.872487 C 427.6169,77.872487 529.1839,179.43949 529.1839,304.72449 z" />
|
||||
<path fill="#000" d="M 277.7249,0.87048682 C 410.2899,-8.3215132 498.1879,56.550487 548.4459,135.58949 C 573.6459,175.21949 598.3709,235.40949 598.4849,297.25249 C 598.6069,364.44649 576.8389,422.63549 548.4459,465.33049 C 519.2639,509.21349 481.5199,545.45849 434.2559,569.25749 C 355.2499,609.04049 244.8359,610.12849 172.5149,571.82349 C 91.972897,529.16549 30.046897,468.27849 7.0028967,362.68749 C -2.2191033,320.43149 -3.2791033,265.83249 9.5688967,218.98749 C 12.583897,207.99849 18.062897,196.43349 22.399897,185.62849 C 43.241897,133.70449 78.716897,88.552487 122.4769,57.323487 C 140.0609,44.775487 161.3929,32.295487 180.2139,23.964487 C 203.6319,13.599487 243.0599,3.2734868 277.7249,0.87048682 z M 232.8179,22.682487 C 183.5789,35.448487 147.4759,58.319487 116.0619,82.985487 C 70.762897,118.55349 41.884897,168.18849 24.965897,227.96849 C 6.1428967,294.47649 18.233897,374.95849 44.211897,425.55649 C 71.150897,478.02849 107.3219,518.75949 158.4019,547.44549 C 208.0969,575.35349 277.9929,593.27349 350.8589,579.52149 C 415.5989,567.30349 464.7679,539.10049 504.8239,497.40649 C 558.4159,441.62149 601.4889,338.87249 572.8259,230.53449 C 565.1639,201.57949 555.1469,171.40149 539.4659,145.85349 C 530.9939,132.05149 518.5619,118.47349 506.1069,104.79649 C 459.1009,53.175487 383.1279,8.6924868 285.4229,14.983487 C 266.8289,16.180487 250.4879,18.100487 232.8179,22.682487 z" />
|
||||
<g style="fill:none;stroke:#fff;stroke-width:2" id="hashpattern">
|
||||
<g>
|
||||
<line y2="314.658" x2="578.188" y1="576.79" x1="316.05"/>
|
||||
<line y2="292.754" x2="556.415" y1="556.03" x1="293.134"/>
|
||||
<line y2="270.851" x2="534.643" y1="535.273" x1="270.217"/>
|
||||
<line y2="248.948" x2="512.87" y1="514.513" x1="247.3"/>
|
||||
<line y2="227.044" x2="491.098" y1="493.754" x1="224.384"/>
|
||||
<line y2="205.141" x2="469.324" y1="473" x1="201.467"/>
|
||||
<line y2="183.238" x2="447.552" y1="452.236" x1="178.55"/>
|
||||
<line y2="161.334" x2="425.778" y1="431.477" x1="155.633"/>
|
||||
<line y2="139.431" x2="404" y1="410.718" x1="132.716"/>
|
||||
<line y2="117.528" x2="382.233" y1="389.958" x1="109.8"/>
|
||||
<line y2="95.625" x2="360.46" y1="369.2" x1="86.883"/>
|
||||
<line y2="73.721" x2="338.688" y1="348.441" x1="63.966"/>
|
||||
<line y2="51.818" x2="316.915" y1="327.681" x1="41.049"/>
|
||||
<line y2="29.915" x2="295.142" y1="306.922" x1="18.132"/>
|
||||
</g>
|
||||
<g>
|
||||
<line y2="576.96" x2="285.419" y1="309.572" x1="18.043" />
|
||||
<line y2="555.488" x2="307.622" y1="287.579" x1="39.726" />
|
||||
<line y2="534.014" x2="329.825" y1="265.586" x1="61.409" />
|
||||
<line y2="512.542" x2="352.029" y1="243.593" x1="83.092" />
|
||||
<line y2="491.068" x2="374.231" y1="221.6" x1="104.774"/>
|
||||
<line y2="469.595" x2="396.436" y1="199.607" x1="126.457"/>
|
||||
<line y2="448.122" x2="418.639" y1="177.614" x1="148.14" />
|
||||
<line y2="426.648" x2="440.842" y1="155.621" x1="169.822"/>
|
||||
<line y2="405.175" x2="463.046" y1="133.628" x1="191.505"/>
|
||||
<line y2="383.7" x2="485.248" y1="111.635" x1="213.188"/>
|
||||
<line y2="362.229" x2="507.452" y1="89.642" x1="234.871"/>
|
||||
<line y2="340.755" x2="529.655" y1="67.649" x1="256.553"/>
|
||||
<line y2="319.283" x2="551.858" y1="45.657" x1="278.236"/>
|
||||
<line y2="297.809" x2="574.062" y1="23.664" x1="299.92" />
|
||||
</g>
|
||||
</g>
|
||||
<path d="M 490.7099,106.07949 C 467.1169,82.486487 438.1109,61.226487 403.4629,48.342487 C 367.5489,34.987487 326.9229,23.730487 279.0079,27.813487 C 202.6819,34.319487 149.0919,68.564487 108.3629,108.64549 C 79.834897,136.71849 58.375897,171.11949 44.210897,211.28849 C 23.412897,270.26949 24.674897,339.88649 48.059897,399.89549 C 68.006897,451.08249 100.6549,492.36849 146.8539,524.35049 C 190.2849,554.41749 252.6189,577.73649 322.6299,571.82349 C 407.9019,564.62149 470.2939,520.87349 511.2369,470.46349 C 521.7129,457.56749 532.1289,442.99049 538.1799,425.55749 C 544.1089,412.99649 547.0109,404.45749 549.7279,399.89649 C 561.0999,374.41449 567.1249,347.52849 568.9729,317.78249 C 574.6579,226.29049 539.4559,154.82649 490.7099,106.07949 z M 465.5789,384.82749 C 465.4159,385.17549 465.2699,385.49949 465.0999,385.85849 C 460.8699,397.96349 453.5829,408.08549 446.2589,417.04149 C 417.6249,452.04549 373.9959,482.42349 314.3639,487.42549 C 265.4029,491.52949 221.8119,475.33849 191.4409,454.46049 C 165.0489,436.31749 144.9869,413.85949 130.9189,386.86949 C 130.0609,385.24549 121.8909,366.42249 121.8669,365.59449 C 110.7219,331.02549 109.7549,275.43949 121.1939,242.08249 C 128.8279,219.81949 141.5509,195.73149 158.4019,176.64749 C 181.6679,150.29649 204.9509,133.41149 241.7999,121.47649 C 258.6249,116.02649 273.6869,110.47949 294.4039,109.92949 C 344.9239,108.58449 396.3689,131.26749 423.9909,156.11849 C 449.3749,178.95549 478.3049,223.44049 485.5779,265.17649 C 493.0629,308.13349 485.0749,350.07449 465.5789,384.82749 z" />
|
||||
<path stroke="#000" stroke-width="6" fill="#fff" d="M 377.768,426.033 C 365.328,426.033 354.411,418.155 350.601,406.429 L 336.745,364.211 L 267.43,364.211 L 254.556,406.044 C 250.67,417.998 239.67,426 227.166,426 C 224.164,426 221.182,425.525 218.303,424.591 C 203.357,420.104 194.872,404.017 199.451,388.751 L 257.957,203.428 C 261.756,191.639 272.94,183.416 285.157,183.416 L 316.267,183.416 C 328.553,183.416 339.736,191.499 343.461,203.073 L 404.99,388.327 C 409.91,403.473 401.763,419.732 386.839,424.59 C 383.888,425.548 380.837,426.033 377.768,426.033 L 377.768,426.033 z" />
|
||||
<g id="OAUTH" fill="#fff">
|
||||
<g>
|
||||
<path d="M 148.001,124.354 L 147.928,124.255 C 140.632,114.256 142.773,100.268 153.518,92.426 C 164.263,84.585 178.066,86.786 185.362,96.784 L 185.435,96.883 C 192.731,106.882 190.59,120.871 179.845,128.712 C 169.1,136.553 155.297,134.353 148.001,124.354 z M 175.658,104.171 L 175.585,104.072 C 171.919,99.048 165.093,97.32 159.771,101.204 C 154.498,105.052 154.088,111.907 157.754,116.932 L 157.827,117.031 C 161.494,122.055 168.319,123.783 173.592,119.935 C 178.915,116.051 179.325,109.196 175.658,104.171 z" />
|
||||
<path d="M 218.344,58.817 L 229.309,55.299 L 260.048,91.033 L 247.851,94.946 L 242.509,88.576 L 226.676,93.656 L 226.096,101.927 L 214.134,105.765 L 218.344,58.817 z M 236.384,80.775 L 228.066,70.573 L 227.177,83.729 L 236.384,80.775 z" />
|
||||
<path d="M 279.795,69.567 L 279.891,45.364 L 292.023,45.412 L 291.928,69.369 C 291.903,75.589 295.032,78.557 299.836,78.577 C 304.64,78.596 307.792,75.776 307.815,69.741 L 307.912,45.477 L 320.044,45.525 L 319.949,69.42 C 319.894,83.338 311.926,89.404 299.67,89.355 C 287.415,89.305 279.742,83.054 279.795,69.567 z" />
|
||||
<path d="M 363.859,65.338 L 351.491,61.563 L 354.547,51.55 L 390.71,62.587 L 387.654,72.6 L 375.286,68.826 L 365.759,100.042 L 354.333,96.555 L 363.859,65.338 z" />
|
||||
<path d="M 423.012,76.559 L 432.958,83.178 L 424.02,96.61 L 436.786,105.106 L 445.725,91.673 L 455.671,98.292 L 431.788,134.181 L 421.841,127.562 L 430.917,113.924 L 418.15,105.428 L 409.075,119.066 L 399.129,112.447 L 423.012,76.559 z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M 458.146,468.883 L 458.222,468.98 C 465.896,478.693 464.29,492.755 453.852,501.001 C 443.414,509.247 429.536,507.575 421.862,497.862 L 421.786,497.765 C 414.112,488.051 415.719,473.99 426.156,465.744 C 436.594,457.499 450.472,459.17 458.146,468.883 z M 431.277,490.11 L 431.353,490.207 C 435.209,495.088 442.096,496.554 447.267,492.469 C 452.389,488.422 452.538,481.556 448.681,476.675 L 448.605,476.578 C 444.75,471.697 437.862,470.231 432.74,474.278 C 427.569,478.363 427.421,485.229 431.277,490.11 z"/>
|
||||
<path d="M 390.707,537.182 L 379.907,541.179 L 347.625,506.833 L 359.638,502.386 L 365.256,508.516 L 380.85,502.744 L 381.065,494.456 L 392.847,490.095 L 390.707,537.182 z M 371.718,516.04 L 380.477,525.865 L 380.786,512.683 L 371.718,516.04 z"/>
|
||||
<path d="M 328.888,528.985 L 329.955,553.164 L 317.835,553.699 L 316.778,529.766 C 316.504,523.552 313.236,520.738 308.437,520.95 C 303.638,521.162 300.625,524.131 300.891,530.16 L 301.961,554.4 L 289.841,554.935 L 288.787,531.064 C 288.173,517.16 295.841,510.718 308.084,510.178 C 320.328,509.637 328.293,515.511 328.888,528.985 z"/>
|
||||
<path d="M 244.671,536.891 L 257.158,540.262 L 254.429,550.37 L 217.918,540.515 L 220.647,530.406 L 233.134,533.777 L 241.641,502.261 L 253.177,505.375 L 244.671,536.891 z"/>
|
||||
<path d="M 185.65,528.108 L 175.401,521.966 L 183.696,508.125 L 170.543,500.241 L 162.248,514.082 L 152,507.94 L 174.164,470.961 L 184.412,477.104 L 175.99,491.156 L 189.144,499.04 L 197.566,484.988 L 207.814,491.131 L 185.65,528.108 z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.6 KiB |