Skip to main content
Applications in Zitadel represent client applications that authenticate users or access APIs. This guide covers creating, configuring, and managing different types of applications.

Prerequisites

  • Zitadel Ruby SDK installed and configured
  • A project created in your organization
  • Required permissions: project.app.read, project.app.write, project.app.delete

Application Types

Zitadel supports three types of applications:
  • OIDC Applications: OAuth2/OpenID Connect applications (web apps, mobile apps, SPAs)
  • API Applications: Machine-to-machine authentication
  • SAML Applications: SAML 2.0 service providers

Creating Applications

Create an OIDC Web Application

OIDC web applications use the authorization code flow with client credentials.
require 'zitadel-client'

client = Zitadel::Client::Zitadel.with_access_token(
  "https://example.zitadel.cloud",
  "your_access_token"
)

request = Zitadel::Client::ApplicationServiceCreateApplicationRequest.new(
  project_id: "your_project_id",
  name: "My Web Application",
  oidc_config: {
    redirect_uris: [
      "https://myapp.com/callback",
      "https://myapp.com/auth/callback"
    ],
    response_types: [
      "OIDC_RESPONSE_TYPE_CODE"
    ],
    grant_types: [
      "OIDC_GRANT_TYPE_AUTHORIZATION_CODE",
      "OIDC_GRANT_TYPE_REFRESH_TOKEN"
    ],
    app_type: "OIDC_APP_TYPE_WEB",
    auth_method_type: "OIDC_AUTH_METHOD_TYPE_BASIC",
    post_logout_redirect_uris: [
      "https://myapp.com/logout"
    ],
    dev_mode: false,
    access_token_type: "OIDC_TOKEN_TYPE_BEARER",
    access_token_role_assertion: true,
    id_token_role_assertion: true,
    id_token_userinfo_assertion: true
  }
)

begin
  response = client.applications.create_application(request)
  puts "Application created!"
  puts "  Client ID: #{response.client_id}"
  puts "  Client Secret: #{response.client_secret}"
  puts "  Application ID: #{response.app_id}"
rescue Zitadel::Client::ApiError => e
  puts "Error: #{e.message}"
end
Store the client secret securely. It cannot be retrieved again after creation. You can only generate a new one.

Create an OIDC Single Page Application (SPA)

SPAs use PKCE (Proof Key for Code Exchange) instead of client secrets.
request = Zitadel::Client::ApplicationServiceCreateApplicationRequest.new(
  project_id: "your_project_id",
  name: "My SPA",
  oidc_config: {
    redirect_uris: ["http://localhost:4200/auth/callback"],
    response_types: ["OIDC_RESPONSE_TYPE_CODE"],
    grant_types: [
      "OIDC_GRANT_TYPE_AUTHORIZATION_CODE",
      "OIDC_GRANT_TYPE_REFRESH_TOKEN"
    ],
    app_type: "OIDC_APP_TYPE_USER_AGENT",
    auth_method_type: "OIDC_AUTH_METHOD_TYPE_NONE",
    post_logout_redirect_uris: ["http://localhost:4200"],
    dev_mode: true, # Enable for development
    access_token_type: "OIDC_TOKEN_TYPE_BEARER"
  }
)

response = client.applications.create_application(request)
puts "SPA created with Client ID: #{response.client_id}"
SPAs use OIDC_AUTH_METHOD_TYPE_NONE since they cannot securely store client secrets. PKCE is required for security.

Create a Native/Mobile Application

request = Zitadel::Client::ApplicationServiceCreateApplicationRequest.new(
  project_id: "your_project_id",
  name: "My Mobile App",
  oidc_config: {
    redirect_uris: [
      "myapp://callback",
      "http://localhost:8080/callback" # For development
    ],
    response_types: ["OIDC_RESPONSE_TYPE_CODE"],
    grant_types: [
      "OIDC_GRANT_TYPE_AUTHORIZATION_CODE",
      "OIDC_GRANT_TYPE_REFRESH_TOKEN"
    ],
    app_type: "OIDC_APP_TYPE_NATIVE",
    auth_method_type: "OIDC_AUTH_METHOD_TYPE_NONE",
    post_logout_redirect_uris: ["myapp://logout"],
    dev_mode: false,
    access_token_type: "OIDC_TOKEN_TYPE_BEARER"
  }
)

response = client.applications.create_application(request)
puts "Mobile app created: #{response.client_id}"

Create an API Application

API applications are used for machine-to-machine authentication.
request = Zitadel::Client::ApplicationServiceCreateApplicationRequest.new(
  project_id: "your_project_id",
  name: "Backend API",
  api_config: {
    auth_method_type: "API_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT"
  }
)

response = client.applications.create_application(request)
puts "API application created: #{response.app_id}"

Managing Application Credentials

Generate a New Client Secret

For OIDC applications that use client secrets:
request = Zitadel::Client::ApplicationServiceGenerateClientSecretRequest.new(
  project_id: "your_project_id",
  app_id: "application_id_here"
)

response = client.applications.generate_client_secret(request)
puts "New Client Secret: #{response.client_secret}"
Generating a new secret invalidates the previous one. Update all clients using the old secret.

Create an Application Key

For API applications using JWT authentication:
request = Zitadel::Client::ApplicationServiceCreateApplicationKeyRequest.new(
  project_id: "your_project_id",
  app_id: "api_app_id",
  type: "KEY_TYPE_JSON",
  expiration_date: (Time.now + 365 * 24 * 60 * 60).to_s # 1 year
)

response = client.applications.create_application_key(request)
puts "Key ID: #{response.key_id}"
puts "Key Details (JSON):"
puts response.key_details
Store the key details securely. This contains the private key needed for JWT authentication.

List Application Keys

request = Zitadel::Client::ApplicationServiceListApplicationKeysRequest.new(
  project_id: "your_project_id",
  app_id: "api_app_id"
)

response = client.applications.list_application_keys(request)

response.result.each do |key|
  puts "Key ID: #{key.id}"
  puts "  Created: #{key.details.creation_date}"
  puts "  Expires: #{key.expiration_date}"
end

Delete an Application Key

request = Zitadel::Client::ApplicationServiceDeleteApplicationKeyRequest.new(
  project_id: "your_project_id",
  app_id: "api_app_id",
  key_id: "key_id_to_delete"
)

response = client.applications.delete_application_key(request)
puts "Key deleted"

Retrieving Applications

Get Application by ID

request = Zitadel::Client::ApplicationServiceGetApplicationRequest.new(
  project_id: "your_project_id",
  app_id: "application_id"
)

response = client.applications.get_application(request)

if response.app.oidc_config
  puts "OIDC Application: #{response.app.name}"
  puts "  Client ID: #{response.app.oidc_config.client_id}"
  puts "  Redirect URIs: #{response.app.oidc_config.redirect_uris.join(', ')}"
elsif response.app.api_config
  puts "API Application: #{response.app.name}"
end

List All Applications in a Project

request = Zitadel::Client::ApplicationServiceListApplicationsRequest.new(
  project_id: "your_project_id",
  queries: [],
  sorting_column: "FIELD_NAME_CREATION_DATE",
  asc: false
)

response = client.applications.list_applications(request)

response.result.each do |app|
  puts "Application: #{app.name}"
  puts "  ID: #{app.id}"
  puts "  State: #{app.state}"
  puts "  Type: #{app.oidc_config ? 'OIDC' : app.api_config ? 'API' : 'SAML'}"
end

Search Applications by Name

request = Zitadel::Client::ApplicationServiceListApplicationsRequest.new(
  project_id: "your_project_id",
  queries: [
    {
      name_query: {
        name: "mobile",
        method: "TEXT_QUERY_METHOD_CONTAINS"
      }
    }
  ]
)

response = client.applications.list_applications(request)
puts "Found #{response.result.length} applications"

Updating Applications

Update OIDC Application Configuration

request = Zitadel::Client::ApplicationServiceUpdateApplicationRequest.new(
  project_id: "your_project_id",
  app_id: "application_id",
  name: "Updated App Name",
  oidc_config: {
    redirect_uris: [
      "https://myapp.com/callback",
      "https://staging.myapp.com/callback"
    ],
    post_logout_redirect_uris: [
      "https://myapp.com"
    ],
    access_token_type: "OIDC_TOKEN_TYPE_JWT",
    access_token_role_assertion: true
  }
)

response = client.applications.update_application(request)
puts "Application updated"

Application Lifecycle

Deactivate an Application

request = Zitadel::Client::ApplicationServiceDeactivateApplicationRequest.new(
  project_id: "your_project_id",
  app_id: "application_id"
)

response = client.applications.deactivate_application(request)
puts "Application deactivated"
Deactivated applications cannot be used for authentication until they are reactivated.

Reactivate an Application

request = Zitadel::Client::ApplicationServiceReactivateApplicationRequest.new(
  project_id: "your_project_id",
  app_id: "application_id"
)

response = client.applications.reactivate_application(request)
puts "Application reactivated"

Delete an Application

request = Zitadel::Client::ApplicationServiceDeleteApplicationRequest.new(
  project_id: "your_project_id",
  app_id: "application_id"
)

response = client.applications.delete_application(request)
puts "Application deleted"

Complete Workflow Example

require 'zitadel-client'

client = Zitadel::Client::Zitadel.with_client_credentials(
  "https://example.zitadel.cloud",
  "client_id",
  "client_secret"
)

project_id = "your_project_id"

begin
  # Create a web application
  create_request = Zitadel::Client::ApplicationServiceCreateApplicationRequest.new(
    project_id: project_id,
    name: "Production Web App",
    oidc_config: {
      redirect_uris: ["https://app.example.com/callback"],
      response_types: ["OIDC_RESPONSE_TYPE_CODE"],
      grant_types: [
        "OIDC_GRANT_TYPE_AUTHORIZATION_CODE",
        "OIDC_GRANT_TYPE_REFRESH_TOKEN"
      ],
      app_type: "OIDC_APP_TYPE_WEB",
      auth_method_type: "OIDC_AUTH_METHOD_TYPE_BASIC",
      post_logout_redirect_uris: ["https://app.example.com"],
      access_token_type: "OIDC_TOKEN_TYPE_BEARER"
    }
  )

  create_response = client.applications.create_application(create_request)
  app_id = create_response.app_id
  
  puts "Application created successfully!"
  puts "Client ID: #{create_response.client_id}"
  puts "Client Secret: #{create_response.client_secret}"
  
  # Store credentials securely
  # ENV['APP_CLIENT_ID'] = create_response.client_id
  # ENV['APP_CLIENT_SECRET'] = create_response.client_secret
  
  # Retrieve application details
  get_request = Zitadel::Client::ApplicationServiceGetApplicationRequest.new(
    project_id: project_id,
    app_id: app_id
  )
  
  app_details = client.applications.get_application(get_request)
  puts "\nApplication Details:"
  puts "  Name: #{app_details.app.name}"
  puts "  State: #{app_details.app.state}"
  puts "  Redirect URIs: #{app_details.app.oidc_config.redirect_uris}"
  
rescue Zitadel::Client::ApiError => e
  puts "Error: #{e.message}"
  puts "Code: #{e.code}"
end

Best Practices

1
Use appropriate application types
2
Choose the correct app type based on your client:
3
  • Web apps: Use OIDC_APP_TYPE_WEB with client secrets
  • SPAs: Use OIDC_APP_TYPE_USER_AGENT with PKCE
  • Mobile: Use OIDC_APP_TYPE_NATIVE with PKCE
  • APIs: Use API applications with JWT authentication
  • 4
    Secure credential storage
    5
    Never log or commit client secrets or private keys. Use environment variables or secret management systems.
    6
    Use HTTPS redirect URIs
    7
    Always use HTTPS for redirect URIs in production. Use http://localhost only for development.
    8
    Limit redirect URIs
    9
    Only add redirect URIs that your application actually uses to prevent security issues.
    10
    Rotate credentials regularly
    11
    Periodically generate new client secrets and application keys, especially for production applications.
    12
    Enable role assertions
    13
    Set access_token_role_assertion and id_token_role_assertion to include user roles in tokens.

    Next Steps

    Build docs developers (and LLMs) love