Skip to content

Improve authentication mechanism for subscription events#580

Merged
rartych merged 8 commits intocamaraproject:mainfrom
m-nahum:issue-461
Feb 13, 2026
Merged

Improve authentication mechanism for subscription events#580
rartych merged 8 commits intocamaraproject:mainfrom
m-nahum:issue-461

Conversation

@m-nahum
Copy link
Contributor

@m-nahum m-nahum commented Jan 23, 2026

What type of PR is this?

  • enhancement/feature

What this PR does / why we need it:

This PR proposes to improve the authentication mechanism for subscription events.

It proposes two sink credential types to cater for clients with different authentication and authorization capabilities :

  • Clients that don't have authorization server capabilities can use simple access tokens that expire with the subscription.
  • Clients that have authorization server capabilities can use full access token capabilities. The authentication information needed to acquire the access token is pre-shared between the parties. A new access token can be acquired if it expires, decoupling the duration of the subscription from the expiration of the token.

This PR also proposes to remove from the spec two sink credential types that are not required anymore.

Which issue(s) this PR fixes:

Fixes #461

Does this PR introduce a breaking change?

  • Yes
  • No

-REFRESHTOKEN credential type is removed. It was not allowed in the current version of the spec.

Special notes for reviewers:

Changelog input

 - Introduction of new credential type PRIVATE_KEY_JWT, which requires pre-shared authentication information between the parties (token endpoint, client ID and JWKS URI). 
 - Removed REFRESHTOKEN credential type, which is not supported
 

Additional documentation

This section can be blank.

docs

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Jan 23, 2026

CLA Signed

The committers listed above are authorized under a signed CLA.

@rartych
Copy link
Contributor

rartych commented Jan 24, 2026

@m-nahum The procedure for EasyCLA signing is explained in https://github.com/camaraproject/EasyCLA repo.
Please check the status of Corporate CLA within your organization and follow the process.

@rartych
Copy link
Contributor

rartych commented Jan 26, 2026

@m-nahum Thank you for the input.
I think all the legacy requirements related to ACCESSTOKEN flow should stay in place with mostly the additions related to PRIVATE_KEY_JWT flow.
Possible extensions:

@PedroDiez
Copy link
Contributor

Thanks for the input @m-nahum.

@jpengar and myself have been reviewed it.

The following comments reflect Telefónica’s initial review and feedback on the content of this Pull Request:

  • The PRIVATE_KEY_JWT flow should be included and properly described in the documentation introduced by this PR. As a baseline, you may reuse the flow described in Issue #461.
    As discussed in previous meetings, the description should use terminology aligned with CAMARA definitions (e.g., API Consumer, API Provider, etc.). The ICM flow diagrams can be used as a reference(e.g. ICM JWT Bearer flow)

  • Please align the wording throughout the PR to consistently use API Consumer and API Provider. A specific inline comment has been added for this.

  • The clarification note added regarding the new PRIVATE_KEY_JWT credential applies to both implicit and explicit subscription models. This should be explicitly stated to avoid ambiguity:

    Note: To use credentialType with value PRIVATE_KEY_JWT, the client and server shall share the authentication information required to request an access token. This includes a client ID, a token endpoint, and a JWK set.

  • The ACCESSTOKEN sinkCredentialType model must be preserved for backward compatibility. While some documentation sections may require review, the model itself should not be changed. Part of the text removed in this PR should be restored, as it still applies to the existing ACCESSTOKEN credential use case, which remains unchanged.

  • The new PRIVATE_KEY_JWT sinkCredentialType should also be defined as a bearer token. There are two possible approaches:

    • Implicitly assume this, but clearly document it to avoid misunderstandings.
    • Explicitly define it in the object schema (e.g., via an accessTokenType attribute) under the new credential type, for example:
    type: object
    properties:
      accessTokenType:
        description: REQUIRED. The type of the access token. See OAuth 2.0 (https://tools.ietf.org/html/rfc6749#section-7.1).
        type: string
        enum:
          - bearer
    required:
      - accessTokenType 

@m-nahum
Copy link
Contributor Author

m-nahum commented Jan 30, 2026

@PedroDiez and @jpengar, thank you for your comments.

Regarding:

  • The new PRIVATE_KEY_JWT sinkCredentialType should also be defined as a bearer token. There are two possible approaches:

    • Implicitly assume this, but clearly document it to avoid misunderstandings.
    • Explicitly define it in the object schema (e.g., via an accessTokenType attribute) under the new credential type, for example:
    type: object
    properties:
      accessTokenType:
        description: REQUIRED. The type of the access token. See OAuth 2.0 (https://tools.ietf.org/html/rfc6749#section-7.1).
        type: string
        enum:
          - bearer
    required:
      - accessTokenType 

The token type will be included in the token response when the API Provider requests an access token from the API Consumer authorization server. There is no reason to limit the token type to Bearer in this specification.

@PedroDiez
Copy link
Contributor

@PedroDiez and @jpengar, thank you for your comments.

Regarding:

  • The new PRIVATE_KEY_JWT sinkCredentialType should also be defined as a bearer token. There are two possible approaches:

    • Implicitly assume this, but clearly document it to avoid misunderstandings.
    • Explicitly define it in the object schema (e.g., via an accessTokenType attribute) under the new credential type, for example:
    type: object
    properties:
      accessTokenType:
        description: REQUIRED. The type of the access token. See OAuth 2.0 (https://tools.ietf.org/html/rfc6749#section-7.1).
        type: string
        enum:
          - bearer
    required:
      - accessTokenType 

The token type will be included in the token response when the API Provider requests an access token from the API Consumer authorization server. There is no reason to limit the token type to Bearer in this specification.

Hi @m-nahum,

The point is that we want to keep both securitization approacahes in terms of behavior, so guaranteeing backwards compatibility. It was discussed in the past the use of "bearer" token. No matter to not explicitly indicate in subscription phase, but indicate that tokens issued are "bearer" token type.


opt Using ACCESSTOKEN sink credential type
opt Subscription
appbe ->> cspres: POST /subscription<br>Body: {<br>sink: <API Consumer>/notification,<br>sinkCredential:{ credentialType: ACCESSTOKEN,<br>accessToken:<Access Token>,<br>accessTokenExpireUtc:<access token expire time>,<br>accessTokenType: bearer },<br>...}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
appbe ->> cspres: POST /subscription<br>Body: {<br>sink: <API Consumer>/notification,<br>sinkCredential:{ credentialType: ACCESSTOKEN,<br>accessToken:<Access Token>,<br>accessTokenExpireUtc:<access token expire time>,<br>accessTokenType: bearer },<br>...}
appbe ->> cspres: POST /subscriptions<br>Body: {<br>sink: <API Consumer>/sink,<br>sinkCredential:{ credentialType: ACCESSTOKEN,<br>accessToken:<Access Token>,<br>accessTokenExpireUtc:<access token expire time>,<br>accessTokenType: bearer },<br>...}

@rartych
Copy link
Contributor

rartych commented Feb 3, 2026

The definition of plain credentials in subscription template looks awkward:

PLAIN: "#/components/schemas/PlainCredential"
...
PlainCredential:
...

but it is intended for protocols with plain security (and is inherited from original CloudEvents subscription template).
Currently other protocols are not used, and this credential type is also excluded, but it is kept for future (and present in subscription APIs).
I think we should not remove it within this PR.
It can be separate issue to decide if such cleanup is needed.

Co-authored-by: Rafal Artych <121048129+rartych@users.noreply.github.com>
}
}
```
Note: To use `credentialType` with value `PRIVATE_KEY_JWT`, the API Consumer and API Provider shall share
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this part it would be better below the above table for editorial aligment with Explicit Susbcription (after line 79)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with Pedro

opt Using PRIVATE_KEY_JWT sink credential type
note over appclient,cspclient: Onboarding: <br> API Consumer shares <Token Endpoint> and <Client ID><br>API Provider shares <JWKS URI>
opt Subscription
appclient ->> cspres: POST /subscription<br>Body: {<br>sink: <API Consumer 2>/notification,<br>sinkCredential:{ credentialType: PRIVATE_KEY_JWT },<br>...}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar changes as for ACCESSTOKEN flow:

Suggested change
appclient ->> cspres: POST /subscription<br>Body: {<br>sink: <API Consumer 2>/notification,<br>sinkCredential:{ credentialType: PRIVATE_KEY_JWT },<br>...}
appclient ->> cspres: POST /subscriptions<br>Body: {<br>sink: <API Consumer 2>/sink,<br>sinkCredential:{ credentialType: PRIVATE_KEY_JWT },<br>...}

end

opt Notification
cspclient ->> appres: POST /notification<br>Authorization: Bearer <Access Token><br>Body: { ... }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cspclient ->> appres: POST /notification<br>Authorization: Bearer <Access Token><br>Body: { ... }
cspclient ->> appres: POST /sink<br>Authorization: Bearer <Access Token><br>Body: { ... }

@rartych
Copy link
Contributor

rartych commented Feb 4, 2026

Due to document structure we have twice the following stance:

... the API Consumer and API Provider shall share authentication information needed to request an access token. This includes a client ID, a token endpoint and a JWK set.

For security experts it is obvious what client ID and JWK set mean here, but I guess we can add some references or explanation for general public, for example:

The client ID uniquely identifies the application ([RFC 6749, Section 2.2](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.2)), while the JWK Set ((JSON Web Key Set)) contains the cryptographic keys used for authentication ([RFC 7517](https://www.rfc-editor.org/rfc/rfc7517.html))

@m-nahum
Copy link
Contributor Author

m-nahum commented Feb 4, 2026

The definition of plain credentials in subscription template looks awkward:

PLAIN: "#/components/schemas/PlainCredential"
...
PlainCredential:
...

but it is intended for protocols with plain security (and is inherited from original CloudEvents subscription template). Currently other protocols are not used, and this credential type is also excluded, but it is kept for future (and present in subscription APIs). I think we should not remove it within this PR. It can be separate issue to decide if such cleanup is needed.

@rartych
Following the same logic, should I put back the REFRESHTOKEN credential definition as well ?

@rartych
Copy link
Contributor

rartych commented Feb 4, 2026

Following the same logic, should I put back the REFRESHTOKEN credential definition as well ?

My understanding is that we concluded that using REFRESHTOKEN is not feasible in CAMARA event notification, hence using pre-shared information as alternative solution is proposed.
We can decide in the future about further cleanup in the template or enabling protocols using plain credentials.

Copy link
Contributor

@patrice-conil patrice-conil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after the modifications requested by Pedro and Rafal are implemented.

}
}
```
Note: To use `credentialType` with value `PRIVATE_KEY_JWT`, the API Consumer and API Provider shall share
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with Pedro

@m-nahum
Copy link
Contributor Author

m-nahum commented Feb 5, 2026

@rartych, @PedroDiez , @patrice-conil

Due to document structure we have twice the following stance:

... the API Consumer and API Provider shall share authentication information needed to request an access token. This includes a client ID, a token endpoint and a JWK set.

For security experts it is obvious what client ID and JWK set mean here, but I guess we can add some references or explanation for general public, for example:

The client ID uniquely identifies the application ([RFC 6749, Section 2.2](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.2)), while the JWK Set ((JSON Web Key Set)) contains the cryptographic keys used for authentication ([RFC 7517](https://www.rfc-editor.org/rfc/rfc7517.html))

To avoid having the note in 2 places and add the additional references, I propose to add a section to the Security section that explains the pre-requisites for using PRIVATE_KEY_JWT

Copy link
Contributor

@PedroDiez PedroDiez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Editorial comment.

LGTM at functional level

Co-authored-by: Pedro Díez García <pedro.diezgarcia@telefonica.com>
rartych
rartych previously approved these changes Feb 11, 2026
Copy link
Contributor

@rartych rartych left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Clarified description of ACCESS_TOKEN_EXPIRED reason.

Aligned with CAMARA API Design Guide
Copy link
Contributor

@PedroDiez PedroDiez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor point aligned in a commit

Copy link
Contributor

@PedroDiez PedroDiez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@rartych rartych left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reapproved.

Copy link
Contributor

@patrice-conil patrice-conil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

token refresh not possible on Event subscriptions

4 participants