OAuth Integrations Security
This section provides additional details about the Posit Connect OAuth integrations feature, focusing on the security implications of its design and operation.
Credential exchange
The Connect Server API endpoint which provides the OAuth access token to requesting content implements RFC8693. This token exchange service specification lays out strict semantics for interacting with this endpoint and facilitates well-defined interactions that must meet certain security-related criteria to succeed.
Request
Following RFC8693, a valid request to the credential exchange endpoint must include the following parameters:
grant_type
must beurn:eitf:params:oauth:grant-type:token-exchange
.subject_token_type
must be eitherurn:posit:connect:user-session-token
orurn:posit:connect:content-session-token
.subject_token
must be a valid instantiaton of the submittedsubject_token_type
.
The expected subject_token_type
depends on the auth_type
of the OAuth integration being used.
Integration Auth Type | Subject Token Type |
---|---|
Viewer | urn:posit:connect:user-session-token |
Service Account | urn:posit:connect:content-session-token |
Subject Tokens
When a subject_token
is created, Connect signs it using an ephemeral secret. This secret’s life cycle is coupled to the life cycle of the executing content process. This means that the client requesting a credential exchange must have acquired the token from the content item when it was recently executing.
Across all subject tokens accepted by the credentials exchange endpoint, the following design properties hold which help to prevent misuse:
The user requesting the token exchange must have owner permissions on the content item.
The
subject_token
must have been issued by the server that is receiving the credential request.The
subject_token
must have been produced within the past 24 hours.
User Session Token
A urn:posit:connect:user-session-token
is a signed Json Web Token (JWT) with the following claims:
Name | Description |
---|---|
Iss |
Address of the Connect server that issued the subject_token . |
Sub |
GUID identifying the content viewer. |
Job |
Identifies the underlying content process for which the subject token can be used. |
App |
App ID of the accessed content. Connect uses this value to verify that both the authenticated user who is requesting a viewer’s OAuth access token and the content viewer have permission to receive the OAuth access token. |
Iat |
Unix timestamp indicating when the subject_token was issued by the Connect server. |
Exp |
Unix timestamp indicating when the subject_token expires. Connect sets the expiration to be 24 hours from the time the token was issued. |
The design of the urn:posit:connect:user-session-token
maintains the following additional properties which help to prevent misuse:
The viewer must have recently interacted with the content which is requesting their OAuth access token.
The viewer must have permission to view the content item.
Content Session Token
A urn:posit:connect:content-session-token
is a signed Json Web Token (JWT) with the following claims:
Name | Description |
---|---|
Iss |
Address of the Connect server that issued the subject_token . |
Sub |
GUID identifying the content item. Must be internally consistent with the App claim. |
Job |
Identifies the underlying content process for which the subject token can be used. |
App |
App ID of the accessed content. Connect uses this value to verify that the authenticated user who is requesting a service account OAuth access token has permission to receive it. |
Iat |
Unix timestamp indicating when the subject_token was issued by the Connect server. |
Exp |
Unix timestamp indicating when the subject_token expires. Connect sets the expiration to be 24 hours from the time the token was issued. |
Response
The credential exchange only returns an OAuth access token. Sensitive credentials are never returned in the response.
Publisher trust model
When deployed content requests an OAuth access token from an OAuth integration on Connect, by definition, the content receives a credential which provides it with the ability to access private external resources. Viewer OAuth integrations grant content the ability to access resources available to viewers. Service Account OAuth integrations grant content the ability to access resources available to the Service Account.
Once the content receives this credential, Connect cannot control its use. Connect implicitly trusts that publishers’ content will not misuse delegated credentials, either maliciously or unintentionally.
Published content only receives OAuth access tokens, which are short-lived credentials designed to eventually expire.
This trust model, which assumes that publishers will not misuse or abuse system assets, exists elsewhere in Connect. For example, this same implicit trust relationship applies to content that executes using Current User Execution accessing privileged resources. This is not a change in the fundamental trust model between the server and deployed content. Rather, it is an extension of the same underlying trust model with the following additional implications:
Publishers should take care to ensure that OAuth access tokens are not unintentionally leaked through content logs, cached outside of the content process, or otherwise observed external to the executing content.
Administrators should regularly audit user roles to ensure that users with the Publisher role are trusted actors on the server.
Sensitive fields
Setting up an OAuth integration may require configuring sensitive fields, such as an OAuth client secret for integrations which target confidential OAuth clients. Sensitive fields are encrypted-at-rest in the Connect database and are never returned by the Connect Server API.
Publishers must explicitly opt-in to use a particular OAuth integration with their content, either through the Access tab in the Content Settings pane or through the Connect Server API. Content may only request OAuth access tokens for an integration with which it has been explicitly associated. Content never has access to sensitive information about configured OAuth integrations.
Modifying integrations
Connect allows OAuth integration edits to support certain essential maintenance and upkeep operations such as secret rotation. Given that there are certain contexts where edits to OAuth integrations are necessary, an OAuth integration should not be modified to point to an entirely different authentication provider. This ensures that access tokens from active user sessions are not leaked to an unintended authentication provider.
Encryption
Stored credentials
All OAuth credentials stored by Connect are encrypted-at-rest.
Network traffic
When considering the network topology of Connect, and by implication, the relevant network boundaries over which sensitive data might be communicated, it is useful to consider local and off-host execution separately.
To keep the discussion concrete, assume our OAuth integration has the Viewer Auth Type, and that our content process needs to acquire a user session token which will be communicated through an HTTP header. The topology differences for Service Account OAuth integrations and content session tokens are minimal and will be presented at the end of this section.
The following discussion assumes Connect has been configured to use SSL/TLS. It also assumes the third-party protected resource is configured to use SSL/TLS. Communication with third-party resource(s) is out-of-scope for this document.
Local execution
In the network diagram below, a user initiates communication with Connect which targets some interactive content process, either over HTTPS or websockets using SSL (WSS) (1). Connect then proxies this request to the content (2). Finally, the content initiates a credential exchange request on behalf of the user (3) in order to acquire an OAuth access token which can be used to communicate with some third-party protected resource.
When Connect is running in local execution, all communication which crosses a network boundary (1 and 3) is encrypted by TLS. In particular, note that the credential exchange (3) uses the public Connect Server API to securely communicate the OAuth access token to the requesting content.
Off-host execution
The network topology of the off-host execution model on Connect is very similar to local execution. The initiating communication between a user and Connect remains unchanged (1). The token exchange which serves an OAuth access token to executing content still occurs over the TLS-backed Connect Server API (3). However, communication between the Connect server and the interactive content it manages now crosses an intra-cluster network boundary, because communication must pass between Kubernetes pods (2).
Traffic between the Connect server and executing content in Kubernetes (2) is not encrypted.
This network boundary is not encrypted for the following reasons:
Connect assumes that intra-network communication is managed by Kubernetes administrators who have hardened the external boundaries of the cluster against malicious actors.
Best practices dictate that communication within a Kubernetes cluster should be holistically secured by installing a service mesh.
Importantly, OAuth credentials are not communicated directly to executing content across this intra-cluster network boundary. The only relevant data that crosses this network boundary is the signed subject_token
, which content can subsequently use to initiate a credential exchange through the TLS-secured Connect Server API to receive an OAuth access token.
No sensitive information is communicated in the subject_token
. The signing secret used to verify the integrity of the user session token never crosses any network boundaries.
Content Session Token Transmission
Where user session tokens are communicated through an HTTP header to interactive content, represented by step (2) in both the Local and Off-host execution network topology diagrams, content session tokens are transmitted to content through an encrypted environment variable which is made available to the executing content process. This environment variable is always encrypted.
The rest of the network topology remains unchanged.
Viewer OAuth integrations
Prerequisites
Connect must have received a viewer’s OAuth credentials before the credential exchange occurs. This means that:
- The content being accessed by the viewer must have been explicitly associated with an OAuth integration by the content publisher.
- The viewer must have already logged into the OAuth provider and delegated their OAuth credentials to Connect before the credential exchange is initiated.
Restrictions
Viewer OAuth integrations are not supported for content which uses the Anyone - no login required access type. This means that every OAuth token maintained by Connect is linked to a named user on the server.
Proof Key for Code Exchange
Viewer OAuth integrations in Connect use the PKCE (Proof Key for Code Exchange) extension for the authorization code flow by default. PKCE is required in the upcoming OAuth 2.1 specification, and is recommended in all cases to protect against authorization code injection attacks. If necessary, PKCE can be disabled by creating a Custom integration, but this is not recommended.
Viewer identity delegation
When a viewer is directed to log in to a third-party OAuth application by Connect, the viewer’s identity, represented by an OAuth access token, is stored and maintained on the Connect server. Under specific, well-defined circumstances, executing content is able to request this access token from Connect on behalf of the viewer.
In brief, the restrictions around when and how this credential exchange can occur ensure that both the user requesting the credential exchange and the viewer have the correct permissions, and that the viewer has recently interacted with the content which is requesting their OAuth access token. Additional details about the behavior of this credential exchange operation are provided above.
Once the executing content acquires the viewer’s OAuth access token, it can then make authenticated requests to a third-party protected resource using the viewer’s token.
OAuth access tokens are short-lived credentials which expire. Additional details about the security implications of publishers’ control over OAuth credentials are provided above.
Process management
While each client session will use a user subject token which is scoped uniquely to the viewer, multiple clients which connect to the same application may reuse the same underlying Python or R process. Because of this, published application code must be careful to scope sensitive information to the lifecycle of the client session. For example, applications should not store sensitive information in global variables which persist outside of the client session and are instead tied to the lifecycle of the Python or R process.
Connect’s application process management documentation provides additional information about how Connect manages long-running processes to service client connections.
Service Account OAuth integrations
OAuth Token Requests
Service Account OAuth integrations request a fresh OAuth access token from the external provider on every credential exchange. There is no OAuth session stored by Connect which caches the access token. No refresh token is received or stored by Connect.
Publisher Access
There are two considerations which Connect administrators should be aware of when configuring Service Account OAuth integrations.
While Viewer OAuth integrations require a login flow which explicitly acquires consent from the viewer before granting access to protected resources, the OAuth flow used by Service Account integrations has less restrictions. It implicitly acquires an access token using the Connect Server’s identity without requiring additional opt-in.
Every publisher has access to every OAuth integration configured on the Connect Server.
This means that the Connect server’s level of access to protected third-party resources is implicitly granted to every publisher on the Connect server through the use of a Service Account OAuth integration. Connect Administrators should carefully consider the level of access granted to the Service Account identity before granting access to publishers.