We have an on-prem Temporal cluster with the below configuration for Authentication.
authorization:
authorizer: default
claimMapper: default
permissionsClaimName: roles
jwtKeyProvider:
keySourceURIs:
- https://login.microsoftonline.com/{azure_tenant_id}/discovery/v2.0/keys
It looks like Temporal caches the RSA keys returned from "keySourceURIs".
Since we are using Azure AD as IdP, it rotates the keys in the background without our knowledge and our Workflows fail with an Authentication error "PERMISSION_DENIED: Request unauthorized.".
I want to know if there is any way to make Temporal aware of the key rotation.
There is a refresh interval here in their helm chart that reads from the environment variable TEMPORAL_JWT_KEY_REFRESH
.
authorization:
jwtKeyProvider:
keySourceURIs:
{{- if .Env.TEMPORAL_JWT_KEY_SOURCE1 }}
- {{ default .Env.TEMPORAL_JWT_KEY_SOURCE1 "" }}
{{- end }}
{{- if .Env.TEMPORAL_JWT_KEY_SOURCE2 }}
- {{ default .Env.TEMPORAL_JWT_KEY_SOURCE2 "" }}
{{- end }}
refreshInterval: {{ default .Env.TEMPORAL_JWT_KEY_REFRESH "1m" }}
permissionsClaimName: {{ default .Env.TEMPORAL_JWT_PERMISSIONS_CLAIM "permissions" }}
authorizer: {{ default .Env.TEMPORAL_AUTH_AUTHORIZER "" }}
claimMapper: {{ default .Env.TEMPORAL_AUTH_CLAIM_MAPPER "" }}
There is a recent documentation bogpost, that is using it as below
# JWK containing the public keys used to verify access tokens
- "TEMPORAL_JWT_KEY_SOURCE1=https://login.microsoftonline.com/{Tenant ID}/discovery/v2.0/keys"
- "TEMPORAL_JWT_KEY_REFRESH=30m"
While examining the Golang code responsible for managing the configuration:
func (a *defaultTokenKeyProvider) initialize() {
a.rsaKeys = make(map[string]*rsa.PublicKey)
a.ecKeys = make(map[string]*ecdsa.PublicKey)
if a.config.HasSourceURIsConfigured() {
err := a.updateKeys()
if err != nil {
a.logger.Error("error during initial retrieval of token keys: ", tag.Error(err))
}
}
if a.config.RefreshInterval > 0 {
a.stop = make(chan bool)
a.ticker = time.NewTicker(a.config.RefreshInterval)
go a.timerCallback()
}
}
I have concerns about the key no longer being updated. I would recommend opening an issue regarding this matter. Actually I've just opened #5127
But the callback should periodically refresh the key
func (a *defaultTokenKeyProvider) timerCallback() {
for {
select {
case <-a.stop:
return
case <-a.ticker.C:
}
if a.config.HasSourceURIsConfigured() {
err := a.updateKeys()
if err != nil {
a.logger.Error("error while refreshing token keys: ", tag.Error(err))
}
}
}
}
Regarding the question about whether the URI
https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys
will keep working after a key rotation, the answer is supposed to be yes. The purpose of the JWKS endpoint is to provide a set of public keys that can be used to verify the authenticity of tokens. As long as the endpoint continues to provide the current set of keys, Temporal token validation should remain functional, even after key rotation.
So I will close the above issue as soos as it is confirmed to work as expected.