Skip to content

Instantly share code, notes, and snippets.

@jcheng5
Last active February 3, 2024 17:34
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save jcheng5/44bd750764713b5a1df7d9daf5538aea to your computer and use it in GitHub Desktop.
Save jcheng5/44bd750764713b5a1df7d9daf5538aea to your computer and use it in GitHub Desktop.
Using OAuth2 with Shiny
library(shiny)
# WARNING: This sketch does not make proper use of the "state" parameter.
# Doing so usually involves using cookies, which can be done with the
# Rook package but I have not done that here. If you choose to use this
# approach in production, please check the state parameter properly!
APP_URL <- if (interactive()) {
# This might be useful for local development. If not, just hardcode APP_URL
# to the deployed URL that you'll provide a few lines below.
options(shiny.port = 8100)
"http://localhost:8100/"
} else {
# TODO: Provide the URL that will be used when deployed. This is the URL from
# the browser's/end-user's perspective.
"https://servername/path-to-app"
}
# TODO: Provide an actual client_id, client_secret, and scope here
client_id <- "a_real_client_id"
client_secret <- "a_real_client_secret"
scope <- "photos"
has_auth_code <- function(params) {
# params is a list object containing the parsed URL parameters. Return TRUE if
# based on these parameters, it looks like auth codes are present that we can
# use to get an access token. If not, it means we need to go through the OAuth
# flow.
return(!is.null(params$code))
}
make_authorization_url <- function(req) {
# TODO: Implement for real
#
# The req object is a Rook request. This is just an environment object that
# gives you access to the request URL, HTTP headers, etc. The documentation
# for this object is here:
# https://github.com/jeffreyhorner/Rook#the-environment
#
# Implement this function by returning the URL that we should redirect the
# user to in order to
url_template <- "https://oauth2server.com/auth?client_id=%s&scope=&redirect_uri=%s&response_type=code&state=%s&scope=%s"
redirect_uri <- APP_URL
state <- "something"
sprintf(url_template,
utils::URLencode(client_id, reserved = TRUE, repeated = TRUE),
utils::URLencode(redirect_uri, reserved = TRUE, repeated = TRUE),
utils::URLencode(state, reserved = TRUE, repeated = TRUE),
utils::URLencode(scope, reserved = TRUE, repeated = TRUE)
)
}
ui <- fluidPage(
# Your regular UI goes here, for when everything is properly auth'd
textOutput("code")
)
# A little-known feature of Shiny is that the UI can be a function, not just
# objects. You can use this to dynamically render the UI based on the request.
# We're going to pass this uiFunc, not ui, to shinyApp(). If you're using
# ui.R/server.R style files, that's fine too--just make this function the last
# expression in your ui.R file.
uiFunc <- function(req) {
if (!has_auth_code(parseQueryString(req$QUERY_STRING))) {
authorization_url <- make_authorization_url(req)
# This is silently redirecting the user to oauth. If you prefer, this could
# be a pretty login page with a button-link.
return(tags$script(HTML(sprintf("location.replace(\"%s\");", authorization_url))))
} else {
ui
}
}
server <- function(input, output, session) {
params <- parseQueryString(isolate(session$clientData$url_search))
if (!has_auth_code(params)) {
return()
}
code <- params$code
state <- params$state
session_state <- params$session_state
# etc.
# TODO: Get the access token or whatever. If you do this synchronously here
# then you never have to consider the case of the access token not being
# available.
#access_token <- httr::something(...)
resp <- httr::POST("https://api.oauth2server.com/token",
body = list(
client_id = client_id,
scope = scope,
code = code,
redirect_uri = APP_URL,
grant_type = "authorization_code",
client_secret = client_secret
))
respObj <- jsonlite::fromJSON(rawToChar(resp$content))
str(respObj)
output$code <- renderText({
paste("The code is", code)
})
}
# Note that we're using uiFunc, not ui!
shinyApp(uiFunc, server)
@sourourarbi
Copy link

sourourarbi commented Feb 18, 2018

hello i used this code in my R application but when i run my application i couldn't get the token and my page web is empty ?? can you help me please ??

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