Skip to content

feat: added support for optional audience param #423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

mconflitti-pbc
Copy link
Contributor

Intent

Adds optional audience parameter to our oauth creds helpers. Unclear how to handle connect versions constraint since that relies on the oauth feature being there but this is an added param not a new function.

Need to address parity the python sdk through additional integration and association helpers as a follow up.

Approach

Add optional param

Checklist

  • Does this change update NEWS.md (referencing the connected issue if necessary)?
  • Does this change need documentation? Have you run devtools::document()?

Copy link
Collaborator

@nealrichardson nealrichardson left a comment

Choose a reason for hiding this comment

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

We can chat about testing when you're back if you like. I think the approach will be to just assert that we're making the expected POST requests.

) {
validate_R6_class(connect, "Connect")
url <- v1_url("oauth", "integrations", "credentials")
body <- list(
grant_type = "urn:ietf:params:oauth:grant-type:token-exchange",
subject_token_type = "urn:posit:connect:user-session-token",
subject_token = user_session_token,
requested_token_type = requested_token_type
requested_token_type = requested_token_type,
audience = audience,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
audience = audience,
audience = audience

@@ -745,7 +754,8 @@ get_oauth_content_credentials <- function(
grant_type = "urn:ietf:params:oauth:grant-type:token-exchange",
subject_token_type = "urn:posit:connect:content-session-token",
subject_token = content_session_token,
requested_token_type = requested_token_type
requested_token_type = requested_token_type,
audience = audience,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
audience = audience,
audience = audience

error_if_less_than(connect$version, "2025.03.0")
response <- get_oauth_credentials(
connect,
user_session_token,
requested_token_type = "urn:ietf:params:aws:token-type:credentials"
requested_token_type = "urn:ietf:params:aws:token-type:credentials",
audience = audience,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
audience = audience,
audience = audience

@@ -1017,7 +1021,8 @@ connect <- function(
visitor_creds <- get_oauth_credentials(
con,
user_session_token = token,
requested_token_type = "urn:posit:connect:api-key"
requested_token_type = "urn:posit:connect:api-key",
audience = audience,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
audience = audience,
audience = audience

@@ -745,7 +754,8 @@ get_oauth_content_credentials <- function(
grant_type = "urn:ietf:params:oauth:grant-type:token-exchange",
subject_token_type = "urn:posit:connect:content-session-token",
subject_token = content_session_token,
requested_token_type = requested_token_type
requested_token_type = requested_token_type,
audience = audience,
)
connect$POST(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Two questions:

  • Should we check that the connect server version is new enough if !is.null(audience)? I'm guessing that if you want to specify audience and you're on Connect older than the upcoming release, you won't get back what you're asking for.
  • Does the POST handler on the server ignore unknown body fields? Like, if you were to include audience in the payload for an older Connect.

Assuming that the answers are "yes" and "no", respectively, I think we handle this like this here, instead of adding it in the body definition above:

if (!is.null(audience)) {
  if (connect$version < something) {
    stop(helpful message that this is not supported)
  }
  body$audience <- audience
}

Note that the tests in tests/testthat/ don't test against real Connect servers, so they won't give us any assurance about how older versions of Connect respond if you include this parameter. There is an integration test suite that runs against a range of Connect versions but IDK how feasible it would be to set them up with integrations to test this.

Copy link
Collaborator

@toph-allen toph-allen left a comment

Choose a reason for hiding this comment

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

Feedback in two major categories:

  • Thoughts on the workflow generating a publisher-scoped client object, which depend upon how the audience parameter interacts with requested-token-type (which I'm not 100% sure about).
  • Comments on documentation / how we communicate the parameter.

I realize now in your Slack comment about the testing framework — the easiest way to bootstrap those responses you need is to capture them from a Connect server. Happy to pair on that if you want. When you capture them from a server, appropriately-named .json files are created.

Comment on lines +965 to +967
#' @param audience Optional. The audience field used for credential exchange.
#' This must be a valid integration GUID. When provided in conjunction with the
#' token field, it will use the Connect API integation based on the specified GUID.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, thinking this through now, I feel like this change makes the process of creating a visitor-scoped client a lot more fiddly. I don't think we should hold up the PR over that, but I might advocate for making the default behavior be smarter.

[Edit — Perhaps I'm misunderstanding how the field works. Perhaps when it's NULL the requested_token_type field still works as before! If that's the case, ignore at least some of this comment. 🙂]

I think a much better user experience would be to be smart about automatically selecting a Connect API integration's has been associated with the current piece of content — that has been how our users telling the content what integrations to use. We should probably (1) find our current content item, (2) get integrations associated with it, (3) if there is a Connect API integration associated with it, use that automatically. Use this GUID if provided.

Perhaps it's worth merging this PR as-is but doing the above in a follow-on PR (maybe when we add native functions to do the lookup) before a connectapi release? Because if we don't add some kind of automated behavior, this'll be a pretty significant breaking change for anyone using visitor-scoped clients.

I think we should explain it differently, and maybe even name it differently — audience is a pretty jargony term that I only figured out the meaning of fairly recently. Maybe integration_guid?

Suggested change
#' @param audience Optional. The audience field used for credential exchange.
#' This must be a valid integration GUID. When provided in conjunction with the
#' token field, it will use the Connect API integation based on the specified GUID.
#' @param integration_guid Optional. The GUID of a Connect API integration associated with this piece of content.

Comment on lines +646 to +648
#' @param audience Optional. The audience field used for credential exchange.
#' This must be a valid integration GUID. When provided, the specified requested
#' token type will be ignored.
Copy link
Collaborator

Choose a reason for hiding this comment

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

"The audience field used for credential exchange" is a little tautological with the parameter name. Perhaps better combine that and the second sentence, something like: "The GUID of an integration associated with this piece of content." (I'm assuming that it has to be the GUID of an integration that is associated with this content, right? Not any on the server.)

It's optional — what happens when it's not provided?

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.

3 participants