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
Use appropriate application types
Choose the correct app type based on your client:
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
Secure credential storage
Never log or commit client secrets or private keys. Use environment variables or secret management systems.
Always use HTTPS for redirect URIs in production. Use http://localhost only for development.
Only add redirect URIs that your application actually uses to prevent security issues.
Rotate credentials regularly
Periodically generate new client secrets and application keys, especially for production applications.
Set access_token_role_assertion and id_token_role_assertion to include user roles in tokens.
Next Steps