Skip to main content

IAMApplication

Available

Deployed and supported. The fields and commands described here are stable within version v1alpha1.

apiVersioniam.stackngo.io/v1alpha1
kindIAMApplication
Applied bysng apply
Related commandssng template gen IAMApplication, sng kind get IAMApplication, sng kind delete IAMApplication, sng iam app list · describe · credentials, sng tenant policy attach --app

What it is for​

An IAMApplication declares an OAuth2 / OIDC client for one of your applications: its redirect URLs, its flows (authorization_code, refresh_token, client_credentials…), its scopes, and the lifetime of its tokens. The platform creates the application and puts clientId, clientSecret, and issuer into a <nom>-oidc secret in your tenant, ready to be injected into an App. With directory: tenant, your applications' users (tenant directory) sign in at your tenant's issuer (https://auth.dev.stackngo.fr/t/acme), without a password.

Minimal example​

billing-api.yml
apiVersion: iam.stackngo.io/v1alpha1
kind: IAMApplication
metadata:
name: billing-api
spec:
directory: tenant # your applications' users (default: platform)
displayName: Billing API
redirectURLs:
- https://billing-api.acme.dev.stackngo.app/auth/callback
grantTypes: [authorization_code, refresh_token]
scopes: [openid, profile, email]
sng apply billing-api.yml
sng kind get IAMApplication billing-api --json # status.credentials.secretName = billing-api-oidc

There is no equivalent imperative command: sng iam app lists and describes the directory's applications, but does not create them; the console offers an equivalent form.

Complete annotated example​

portal.yml
apiVersion: iam.stackngo.io/v1alpha1
kind: IAMApplication
metadata:
name: portal # object name; the name in the SSO derives from it (sng-…-app-portal)
spec:
displayName: Portail client # shown on the sign-in screen, 256 characters max
homeURL: https://portal-web.acme.dev.stackngo.app # HTTPS, no local or private address
redirectURLs: # 32 max; HTTPS, except http://127.0.0.1 and http://localhost
- https://portal-web.acme.dev.stackngo.app/auth/callback
- http://127.0.0.1:*/callback # native application or CLI (any port)
grantTypes: # 16 max
- authorization_code
- refresh_token
scopes: [openid, profile, email] # 32 max
credentialsSecret:
name: portal-oidc # default: <nom>-oidc
create: true # false: no Secret, credentials in the SSO only
token:
expireInHours: 1 # access token: 1 to 8760 h; 168 if spec.token is omitted
refreshExpireInHours: 720 # refresh token: 168 by default with refresh_token
deletionPolicy: Delete # Block (default), Orphan, or Delete: see "What happens when you delete"

The Secret produced:

KeyContent
clientIdOAuth2 client identifier
clientSecretclient secret
issuerURL of the OIDC issuer (https://auth.dev.stackngo.fr/t/acme for directory: tenant); discovery at <issuer>/.well-known/openid-configuration

Fields​

Cross-field validation rules​

The schema has no CEL rule. sng apply checks the types, lengths, and bounds in the table below (for example token.expireInHours: 0 is rejected, minimum 1). The following rules are checked by the platform after sng apply, when the manifest is applied:

  • redirectURLs: each URL over HTTPS, neither a local address, nor a private address, nor a metadata address; exception for http://127.0.0.1 and http://localhost (native applications and CLIs), including with a wildcard port http://127.0.0.1:*/callback.
  • homeURL: HTTPS, same prohibitions, without the local exception.
  • credentialsSecret.name: DNS name (lowercase, digits, -, .) or empty.
  • token.expireInHours: at least 1 when spec.token is present.
  • token.refreshExpireInHours: 0 is forbidden when grantTypes contains refresh_token.
  • assignableRoles is not supported yet: a non-empty list is refused (assignableRoles: field not supported yet, it would have no effect; remove it). Remove the field, or leave it empty.

An application rejected at this stage stays Ready: False with the reason UnsupportedConfiguration and the rule's message.

IAMApplication​

ChampDescriptionDéfautValidation
apiVersion stringiam.stackngo.io/v1alpha1
kind stringIAMApplication
metadata ObjectMetaSeul metadata.name est à renseigner (nom de la ressource dans votre tenant).
spec IAMApplicationSpec
status IAMApplicationStatus

IAMApplicationSpec​

ChampDescriptionDéfautValidation
displayName stringNom affiché sur l'écran de connexion de l'application (256 caractères au plus).MaxLength: 256
homeURL stringAdresse d'accueil de l'application, en HTTPS. Les adresses locales et privées sont refusées.MaxLength: 2048
redirectURLs string arrayAdresses vers lesquelles l'utilisateur est renvoyé après connexion (32 au plus). HTTPS obligatoire, sauf http://127.0.0.1 et http://localhost pour les applications natives et les CLI.MaxItems: 32
postLogoutRedirectURLs string arrayAdresses de retour admises après une déconnexion (post_logout_redirect_uri d'OIDC
RP-Initiated Logout), mêmes règles que redirectURLs. Backend auth seulement : sans
elles, /end_session refuse la redirection et la session du navigateur reste ouverte.
MaxItems: 32
Optional: {}
grantTypes string arrayFlux OAuth2 autorisés (16 au plus), par exemple authorization_code, refresh_token ou client_credentials.MaxItems: 16
scopes string arrayPérimètres de données que l'application peut demander (32 au plus), par exemple openid, profile, email.MaxItems: 32
assignableRoles string arrayPas encore pris en charge : une liste non vide est refusée. Laissez ce champ vide.MaxItems: 64
credentialsSecret CredentialsSecretSpecOù déposer les identifiants de l'application (clientId, clientSecret, issuer) pour les injecter dans une App.Optional: {}
token TokenPolicyDurées de vie des jetons émis. Facultatif : sans ce bloc, les jetons d'accès
durent 168 heures (7 jours).
Optional: {}
public booleanClient public (CLI, application native) : PKCE obligatoire, aucun secret utilisé,
redirections loopback admises.
Optional: {}
clientID stringIdentifiant OAuth fixé (ex. compilé dans un binaire) au lieu d'un identifiant
généré. Jamais au format UUID.
Pattern: ^[A-Za-z0-9._-]\{8,128\}$
Optional: {}
directory stringUtilisateurs que l'application connecte : platform (défaut, membres de votre tenant sur StackNGO) ou tenant (utilisateurs de vos applications, émetteur propre à votre tenant). Ne change plus après la création : en créer une autre. Incompatible avec le scope urn:stackngo:introspect.platformEnum: [platform tenant]
Optional: {}
deletionPolicy DeletionPolicySort de l'application quand le manifeste est supprimé : Block (défaut), Orphan ou Delete.BlockEnum: [Block Orphan Delete]

IAMApplicationStatus​

ChampDescriptionDéfautValidation
observedGeneration integerDernière version du manifeste (metadata.generation) prise en compte par la plateforme.
provider ProviderStatusIdentité de la ressource dans le service d'authentification.
lastSyncedAt TimeDate de la dernière prise en compte réussie du manifeste.Optional: {}
conditions Condition arrayConditions décrivant l'état actuel de la ressource (Ready…).
credentials CredentialsStatusÉtat du secret des identifiants OIDC, sans les valeurs secrètes.
oauthSecretRef SecretReferenceDeprecated: use status.credentials.secretName.
machineOrigin stringTenant auquel sont rattachées les sessions ouvertes avec les identifiants de
cette application, quand c'est une application machine. Vide sinon.

CredentialsSecretSpec​

CredentialsSecretSpec configure le secret qui reçoit les identifiants OIDC de l'application.

ChampDescriptionDéfautValidation
name stringNom du secret qui reçoit les identifiants (clientId, clientSecret, issuer).
Défaut : <nom-de-l-application>-oidc. Ignoré quand create vaut false.
MaxLength: 253
Pattern: ^(|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)$
Optional: {}
create booleanÀ false, aucun secret n'est créé dans votre tenant : les identifiants ne sont
conservés que par le service d'authentification (cas typique d'une application
machine à machine). Défaut : true.
trueOptional: {}

TokenPolicy​

TokenPolicy fixe la durée de vie des jetons émis pour l'application.

ChampDescriptionDéfautValidation
expireInHours integerDurée de vie du jeton d'accès, en heures. 0 est refusé. Défaut : 168.168Maximum: 8760
Minimum: 1
Optional: {}
refreshExpireInHours integerDurée de vie du jeton de rafraîchissement, en heures. Non renseigné : 168 si
grantTypes contient refresh_token, 0 sinon. La valeur 0 n'est acceptée que sans
le grant refresh_token.
Maximum: 8760
Minimum: 0
Optional: {}

DeletionPolicy​

Type sous-jacent : string

DeletionPolicy indique ce que devient la ressource quand vous supprimez son manifeste : Block bloque la suppression tant que la ressource est encore utilisée, Orphan la conserve, Delete la supprime.

Règles de validation :

  • Enum: [Block Orphan Delete]
ValeurDescription
BlockBloque la suppression tant que la ressource est encore utilisée par une autre.
OrphanSupprime le manifeste mais conserve la ressource créée.
DeleteSupprime la ressource avec le manifeste, sans vérifier son usage.

ProviderStatus​

ProviderStatus identifie la ressource dans le service d'authentification.

ChampDescriptionDéfautValidation
owner stringOrganisation propriétaire de l'objet dans l'annuaire d'identité. Renseigné par la plateforme.
name stringNom de l'objet dans l'annuaire d'identité. Renseigné par la plateforme.
resourceID stringIdentifiant de l'objet dans l'annuaire d'identité. Renseigné par la plateforme.

CredentialsStatus​

CredentialsStatus indique si le secret des identifiants OIDC est prêt, sans en exposer les valeurs.

ChampDescriptionDéfautValidation
secretName stringNom du Secret qui contient les identifiants.
ready booleanVrai quand le Secret d'identifiants est écrit et complet.
lastRotatedAt TimeDate du dernier renouvellement des identifiants.
observedRotationRequest stringDernière demande de renouvellement prise en compte.

SecretReference​

SecretReference désigne un secret de votre tenant.

ChampDescriptionDéfautValidation
name stringNom du secret.MaxLength: 253
MinLength: 1
Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
Fields out of reach from a tenant

Status and conditions​

ConditionTrue when
Readythe application exists in the SSO and matches the manifest
CredentialsReadythe credentials Secret is written (or the credentials are kept in the SSO with create: false)

Useful fields: status.provider.name (name of the application in the SSO, to pass to sng tenant policy attach --app), status.credentials.secretName, status.credentials.lastRotatedAt, status.lastSyncedAt.

ReasonConditionMeaningCorrective action
ReconciledReady=True, CredentialsReady=Trueup to date—
SecretUpdatedCredentialsReady=Truethe credentials were just renewedrestart the applications that read the Secret
WaitingForTenantReady=Falsethe tenant's identity directory is not ready yet (the resource converges by itself)wait; if it persists, contact support
NamespaceNotManagedReady=Falsethe tenant is not activated on the platform side yetcontact support
UnsupportedConfigurationReady=Falsea validation rule is broken (URL, Secret name, token lifetime, assignableRoles set)fix the manifest, sng apply
SecretOwnershipConflictCredentialsReady=Falsea Secret with the same name exists and does not belong to this applicationchange credentialsSecret.name or delete the other Secret
CredentialsMissingCredentialsReady=Falsethe Secret could not be written or is incompletewait for the next attempt; if it persists, contact support
CredentialsUnavailableCredentialsReady=Falsethe application exists in the SSO but its Secret has disappeared, and the client secret cannot be read backdelete and recreate the application with deletionPolicy: Delete, or contact support
InsufficientRBACCredentialsReady=Falseplatform-side incident: the Secret cannot be writtencontact support
ProviderConflictReady=Falsean application with the same name exists in the SSO and does not belong to this objectchoose another metadata.name (see Common errors)
ProviderUnavailable, ScopeUnresolvedReady=Falseregistering a machine application is not possible for nowautomatic retry
DependencyInUseReady=Falsedeletion blocked (deletionPolicy: Block): suppression bloquée : l'application est encore liée à 1 fournisseur d'identitécontact support; or delete with deletionPolicy: Delete

What happens when you apply​

Creation. The application is created in your users' directory under a stable name derived from the manifest (sng-<empreinte>-app-<nom>, visible in status.provider.name), with a clientId and a clientSecret, stored in the <nom>-oidc Secret in your tenant (unless credentialsSecret.create: false).

Update. A new sng apply updates the application in place; clientId and clientSecret do not change. Renaming the manifest (metadata.name) creates another application.

What happens when you delete​

sng kind delete IAMApplication <nom>. The effect depends on deletionPolicy:

deletionPolicyApplication in the directory<nom>-oidc Secret
Block (default)deleted, except while it is in use: linked to an external identity provider (DependencyInUse, with a message that says what)deleted
Orphankeptkept
Deletedeleted, without checking usagedeleted

Once the application is deleted from the directory, your users can no longer sign in to it. A blocked deletion is re-examined every minute and completes on its own as soon as the application is no longer in use.

Recreate under the same name. After a completed deletion (Block or Delete), a new sng apply of the same manifest creates a new application, with a new clientId and a new clientSecret in <nom>-oidc. After an Orphan, the reapplied manifest takes over the application left in the directory.

No directory user is ever deleted along with an application.

Common errors​

SymptomCauseFix
sng apply rejects: metadata : seul name est permis (…)label, annotation or any key other than name in metadataremove it
Ready: False, UnsupportedConfiguration: assignableRoles: field not supported yet…assignableRoles setremove the field
Ready: False, WaitingForTenantthe tenant's directory is not ready yetwait a few minutes; otherwise contact support
sng apply rejects directorydirectory changed after creation, or tenant combined with multiTenant or the urn:stackngo:introspect scopecreate another application
Ready: False, UnsupportedConfiguration: redirectURLs: …redirect URL over http:// to a public host, or a private addressHTTPS, or http://127.0.0.1 for a native application
sng apply rejects token.expireInHoursvalue 0at least 1, or remove spec.token (168 h)
CredentialsReady: False, SecretOwnershipConflicta <nom>-oidc Secret already exists (created by hand, or by another application)credentialsSecret.name: autre-nom
Ready: False, ProviderConflict: une ressource du même nom existe déjà et appartient à un autre objet : choisissez un autre noman application of that name exists in the directory without belonging to your tenant or to a deleted manifestchoose another metadata.name
Deletion that never finishes, DependencyInUseapplication linked to an external identity providercontact support
sng tenant policy attach --app billing-api has no effect--app expects the SSO name, not the manifest nameread status.provider.name (sng kind get IAMApplication billing-api --json) and pass it to --app

See also​