MS Graph endpoint validation with R
Problem
Your Posit Connect administrator has informed you that the Microsoft Graph OAuth integration has been configured and can now be added to content. When asked what endpoints are accessible via the integration the Connect administrator is not sure, as the Microsoft Entra administator set up the application on the Microsoft side.
Solution
In order to verify the endpoints available to the integration you create a basic Shiny application that takes in an endpoint and queries it on submit, returning the results to the user on success and displaying an error otherwise.
app.R
library(shiny)
library(httr2)
library(bslib)
library(connectapi)
<- page_sidebar(
ui title = "Microsoft Graph Endpoint Requester",
sidebar = sidebar(
title = "Endpoint to request",
textInput("endpoint", "MS Graph Endpoint", placeholder = "/me/manager", value = Sys.getenv("GRAPH_ENDPOINT")),
actionButton("submit", "Submit")
),layout_columns(
card(
card_header("Results"),
verbatimTextOutput("results")
)
)
)
<- function(input, output, session) {
server
# check if running on Posit Connect
if (Sys.getenv("RSTUDIO_PRODUCT") == "CONNECT") {
# initialize Connect API client
<- connect()
client # read the user-session-token header
<- session$request$HTTP_POSIT_CONNECT_USER_SESSION_TOKEN
user_session_token # grab the OAuth Integration access token using the session token
<- get_oauth_credentials(client, user_session_token)
credentials <- credentials$access_token
token else {
} # grab the access token from the MSGRAPH_TOKEN env var if running locally
<- Sys.getenv("MSGRAPH_TOKEN")
token
}
# only request when the submit button is selected
observeEvent(input$submit, {
# do not allow an empty value for the graph endpoint
req(input$endpoint)
# form the requested endpoint
<- paste0("https://graph.microsoft.com/v1.0", input$endpoint)
path # request the endpoint
<- httr2::request(path) |>
resp ::req_headers("Accept" = "application/json;odata.metadata=full;odata.streaming=true") |>
httr2::req_auth_bearer_token(token) |>
httr2# to avoid HTTP response error codes being surfaced as R errors
::req_error(is_error = ~FALSE) |>
httr2::req_perform()
httr2# check the HTTP response code
<- httr2::resp_status(resp)
http_code if (http_code == 200) {
# format response body now that we have the HTTP status code
<- httr2::resp_body_json(resp)
resp # output the response
$results <- renderText({
output# paste to avoid "cannot be handled by cat()" error
paste0(resp, sep = "\n")
})}# output the unexpected HTTP code
if (http_code != 200) {
$results <- renderText({
output<- paste0("Received non-200 HTTP response code: ", http_code)
error
error
})}
})
}
shinyApp(ui, server)
Running the app locally
Terminal
Sys.setenv(CONNECT_SERVER = "<connect-host>")
Sys.setenv(CONNECT_API_KEY = "<connect-api-key>")
# MSGRAPH_TOKEN is only required when running the example locally
Sys.setenv(MSGRAPH_TOKEN = "<msgraph-token>")
::runApp() shiny