@startuml component

actor developer as "Developer"
actor enduser as enduser
participant cluster as "cluster"
participant jwker as "jwker"
participant naiserator as "naiserator"
participant application as "application"
participant tokendings as "tokendings"
participant anotherapplication as "anotherapplication"
participant idprovider as "idprovider"

==Deploy application==
developer -> cluster: apply ´application´ resource
cluster <- naiserator: read application resource
cluster <- naiserator: apply jwker resource
note left: containing accessPolicies and unique secret name
jwker -> cluster: read jwker resource
jwker -> cluster: read existing jwker secret
jwker -> jwker: Create new jwks
jwker -> tokendings: update
note right: jwks/key-id/accessPolicy json
jwker -> cluster: create secret
note left: jwks with private jwk
jwker -> cluster: delete old application secret
cluster -> application: inject secret

==Call another application==
enduser -> application: fetch resource
application -> enduser: redirect to id-provider
enduser -> idprovider: authenticate user
idprovider -> enduser: user-jwt
enduser -> application: user-jwt
application -> tokendings: present client-jwt, signed with jwk
note right: client-jwt: {sub:app-id(clustername.namespace.appname), audience:tokendings}
application -> tokendings: client-assertion: client-jwt, subject-token: user-jwt
tokendings <- bucket: jwks matching sub:app-id in jwt
tokendings -> tokendings: validate jwt using jwks
tokendings <- bucket: fetch accessPolicy matching sub:app-id in jwt
tokendings -> tokendings: evaluate accessPolicies
tokendings -> idprovider: fetch jwks (public keys)
tokendings -> tokendings: validate subject:token
tokendings -> application: return valid token
application -> anotherapplication: present token

==validate token==
anotherapplication -> tokendings: fetch public keys
note right: public keys from tokendings
anotherapplication -> anotherapplication: validate token from application
anotherapplication -> application: response
