Secure Logins and Resource Access with ZITADEL and OpenID Connect - Part 1

Dakshitha Ratnayake
Dakshitha Ratnayake

Developer Advocate

  1. 1. Introduction
  2. 2. OAuth2 and OpenID Connect
    1. 2.1 OAuth2
      1. 2.1.1 Main Grant Types
      2. 2.1.2 Deprecated Grant Types
      3. 2.1.3 Other Grant Types
    2. 2.2 OpenID Connect (OIDC)
      1. 2.2.1 Application Types
    3. 2.3 Recommendations
  3. 3. How ZITADEL Authenticates End Users and Authorizes Applications as an OIDC Provider
    1. 3.1 Application Types and OAuth2 Grant Types Supported
    2. 3.2 Choosing an Authentication Flow for an Application
  4. 4. Wrap Up

1. Introduction

ZITADEL allows you to add login to your applications to authenticate your users and authorize your application to access those users’ protected resources on their behalf, with or without explicit consent, depending on the type of application you are building. This post will primarily cover how you can do this on ZITADEL with OpenID Connect (OIDC).

2. OAuth2 and OpenID Connect

First, let’s look at the different grant types introduced in OAuth2, and therefore OIDC, to figure out how to select a grant type for an application based on what kind of app they are.

2.1 OAuth2

OAuth2 is a widely used authorization framework that allows third-party applications to access protected resources on behalf of their owner without requiring the owner to share their username and password with the third-party application. OAuth2 defines several grant types. They specify how you can obtain an access token. In other words, you need to select a grant type based on how you, as the application developer, intend the users of your application to access their protected resources (which reside in a separate resource server) within your application.

In basic terms, when you specify a grant type, you are telling the authorization server something along the lines of:

Dear Authorization Server,

Here is how I, the client application, would like to receive an access token to access my user’s protected resources on their behalf. As a client app registered with you and assigned a unique identifier, I trust you will make it happen.

Thanks,

Client App X

2.1.1 Main Grant Types

The introduction of different grant types in the OAuth2 framework, as well as the extensions that are capable of defining new grant types, was necessary to support a variety of use cases and scenarios where access tokens need to be issued. For example:

  • Authorization Code grant type is used for web server applications that can securely store a client secret. This is the most commonly used grant type for web-based applications. It involves the client application redirecting the user to the authorization server's login page, where the user logs in and grants the client application access. The authorization server then redirects the user back to the client application with an authorization code, which the client application can exchange for an access token.
  • Proof Key for Code Exchange (PKCE) grant type is an extension to the Authorization Code flow that protects against Cross-Site Request Forgery(CSRF) and authorization code injection attacks. The PKCE flow ensures that the authentication process is secure by using a code verifier and a code challenge, which are sent to the authorization server to obtain an access token. PKCE is not a replacement for a client secret, but it is recommended even if the client is using one. PKCE was developed to protect the authorization code flow in mobile apps, but its ability to prevent authorization code injection makes it useful for any type of OAuth client, including web apps that use a client secret.
  • Client Credentials grant type is used for server-to-server communication, where no end user is involved, and the client application is the resource owner.
  • Device Authorization grant type, also known as the Device Code Grant, is used to allow devices with limited input capabilities to obtain an access token. This grant type involves a set of steps that allow a user to authorize a device. Once the user authorizes the device, the device can use the authorization code to obtain an access token.
  • Refresh Token grant type is used to obtain a new access token using a previously obtained refresh token. This grant type is typically used in situations where long-lived access to a resource is required.

2.1.2 Deprecated Grant Types

  • Implicit grant type (deprecated in OAuth 2.1 draft is used for browser-based applications (such as single-page applications) that cannot keep a client secret confidential. It involves the client application requesting an access token directly from the authorization server by including the access token request in the URL of a redirect URI.
  • Resource Owner Password Credentials (ROPC) grant type (deprecated in OAuth 2.1 draft is used for trusted applications that can securely store user credentials and directly exchange them for an access token (without an intermediary access code). ROPC, however, is often discouraged due to its potential security risks.

2.1.3 Other Grant Types

OAuth also allows for the definition of new extension grant types to support additional clients or to provide a bridge between OAuth and other trust frameworks. One such grant type is the JSON Web Token(JWT) Profile.

  • JSON Web Token(JWT) Profile is an extension grant type that uses a JWT Bearer Token to request an OAuth2 access token as well as for use as client credentials without a direct user-approval step at the authorization server.

2.2 OpenID Connect (OIDC)

OpenID Connect (OIDC), on the other hand, is an extension built on top of OAuth2 that provides additional functionality for authentication and obtaining user identity. The use of this extension is requested by client applications by including the openid scope value in the authorization request. Information about the authentication performed is returned in a JSON Web Token (JWT) called an ID Token. The JWTs include claims, which are statements about an entity (typically, the user), as well as additional metadata. A set of standard claims is defined in the OpenID Connect specification. Name, email, gender, birth date, and so on are among the standard claims. If you want to capture information about a user and there isn't a standard claim that best reflects that information, you can create custom claims and add them to your tokens.

While OIDC uses OAuth2 as the underlying protocol for obtaining access tokens, it adds to the grant types by providing a set of authentication flows to obtain ID tokens and access tokens, depending on the type of client application and the requirements of the use case. These flows include:

  • Authorization Code Flow returns an authorization code to the client application, which can then exchange it for an ID token and an access token directly. This provides the benefit of not exposing any tokens to the user agent and possibly other malicious applications with access to the user agent. The authorization server can also authenticate the client before exchanging the authorization code for an access token. The authorization code flow is suitable for clients that can securely maintain a client secret between themselves and the authorization server.
  • Implicit Flow is mainly used by client applications implemented in a browser using a scripting language. The access token and ID token are returned directly to the client, which may expose them to the end user and applications that have access to the end user's user agent. The authorization server does not perform client authentication.
  • Hybrid Flow is a combination of the Authorization Code and Implicit grant types, and is used to obtain both an authorization code and an access token in a single request. When using the Hybrid Flow, some tokens are returned from the authorization endpoint and others are returned from the token endpoint.

The specification places additional requirements on how the grant types are used for authentication and identity management.

2.2.1 Application Types

Because we are looking at adding authentication to the apps, let’s focus on the different application types mentioned in OpenID Connect. There are three primary application types:

  • Web Applications: These are traditional web applications, such as those built with Java or .NET, that run on a web server and use a browser to interact with the user. Web applications should use the Authorization Code Grant with PKCE to obtain an access token.
  • Single-Page Applications (SPAs): These are web applications that run entirely in the browser, without a back-end server. SPAs should use the Authorization Code Grant with PKCE or the Implicit Grant (if PKCE is not feasible) to obtain an access token.
  • Native Applications: These are applications that are installed and run natively on a device, such as a mobile app or a desktop app. Native applications should use the Authorization Code Grant with PKCE or the Device Authorization Grant(if the device has no display or mechanism for user input and therefore needs another device) to obtain an access token.

2.3 Recommendations

In summary, the Authorization Code Grant with PKCE is considered the most suitable grant type for web apps, native apps, and user agents due to its secure method of authentication, smooth user experience, versatility, and recommendation as a best practice by security experts and industry standards, such as OAuth 2.0 Security Best Current Practice.

While APIs (Application Programming Interfaces) can be considered as a type of application in the broader sense of the term, they are not typically considered as an application type in the context of OpenID Connect. This is because APIs are not user-facing applications, and their primary function is to provide access to data and services for other applications to consume. That being said, APIs can still play an important role in OIDC by acting as an OAuth Resource Server that can be accessed by user-facing applications on behalf of end users. In this context, the API may require an access token. The API can then use the access token to authorize access to protected resources on behalf of the user-facing application. These APIs will have to use a grant type such as the JWT Profile to access the authorization server’s introspection endpoint to validate the token.

There will also be client APIs or systems that need to access other protected APIs/protected resources for their functionality and not for accessing resources on behalf of end users, such as the management API of the authorization server or another API that is not tied to user data. These client APIs or systems can acquire an access token using a grant type, such as Client Credentials Grant, JWT Profile, or another OIDC-compliant authentication flow. Each grant type has its own use case and application type. It's worth noting that the specific grant type used by an application will depend on various factors, such as the level of security required, the type of user experience desired, and the capabilities of the application. The choice of grant type should be made with consideration for the specific requirements of the application and the needs of the users.

From a purely technical standpoint, most OAuth2 grants and OIDC flows that support end-user authentication can be made to work in almost any scenario, but doing so has significant security implications. As a result, it is recommended that you adhere to the recommended flows.

3. How ZITADEL Authenticates End Users and Authorizes Applications as an OIDC Provider

3.1 Application Types and OAuth2 Grant Types Supported

ZITADEL supports the following application types:

  • Web Application
  • Native Application (mobile or desktop apps)
  • User Agent (browser-based apps/single-page applications)
  • API

In these scenarios, users can authenticate through user interaction for the first three options (web, native, and user agent), or without direct interaction for the fourth option (API).

ZITADEL can help with end-user authentication by providing various authentication methods, such as username/password, multi-factor authentication (MFA), passwordless authentication, single sign-on (SSO), and federated identity options. Understanding the different use cases can help in choosing the appropriate authentication method for a particular scenario.

For authorization, ZITADEL supports the following grant types in accordance with the OAuth 2 framework as well as the related specifications like RFC 6749, RFC 8628, RFC 7636, RFC 7523, and OpenID Connect Core.

  • Authorization Code
  • Authorization Code with PKCE
  • Implicit
  • Client Credentials
  • JSON Web Token(JWT) Profile
  • Refresh Token

ZITADEL does not support the following grant types:

  • Resource Owner Password Credentials (as this is not recommended and will be deprecated in OAuth 2.1)
  • Device Authorization Grant (In progress)

3.2 Choosing an Authentication Flow for an Application

Applications and Grant Types Supported in ZITADEL

Figure 1: Applications and grant types supported in ZITADEL

For each of the following application types (where end-user authentication is required), ZITADEL supports the following methods:

Web Application (with dedicated server-side component):

  • Authorization Code (with PKCE) - Recommended
  • Authorization Code
    • Authorization Code (without PKCE)
    • JSON Web Token Profile
    • POST (including the client credentials in the request body) - Not recommended

Native Application (mobile/desktop/smart device application):

  • Authorization Code (with PKCE) - Recommended

User Agent (SPA/browser-based application):

  • Authorization Code (with PKCE) - Recommended
  • Implicit

API:

If you have an API that behaves as an OAuth resource server that can be accessed by user-facing applications and need to validate an access token (either by calling the introspection endpoint or other mechanism such as verifying a private key) in order to grant access to the resource, it is categorized as an API application in ZITADEL. You can use the following methods to register these APIs in ZITADEL:

  • JSON Web Token (JWT) Profile (Recommended)
  • Basic Authentication

Service Users:

If there are client APIs or systems that need to access other protected APIs/protected resources and do not want to access resources on behalf of end users, these APIs or systems must be declared as service users. A service user is not considered an application type in ZITADEL. These client APIs(service users) can obtain an access token by using a grant type, such as Client Credentials Grant, JWT Profile or an OIDC-compliant authentication flow. The following mechanisms are available for service users to obtain an access token:

  • JSON Web Token (JWT) Profile (Recommended)
  • Client Credentials
  • Personal Access Tokens (PAT)

4. Wrap Up

In this post, we discussed the OAuth2/OIDC grant types, authentication workflows, and the various ways in which ZITADEL supports them so that you can secure your application in the most optimal way. In Part 2 of this series, we will walk you through the process of registering a web application with ZITADEL, using the recommended Authorization Code with PKCE approach. Hope this post was informative and useful. Thanks for reading, and we'll see you in Part 2!

Liked it? Share it!