Example: Spotify login to display listening data
Source:vignettes/example-spotify.Rmd
example-spotify.RmdOverview
This app shows a user’s top tracks after they authorize access to Spotify. Spotify handles sign-in and returns an access token, a credential your app can use to ask its API for data. The app never needs the user’s Spotify password.
Scopes name the permissions to request. Here
user-top-read allows reading listening preferences; other
data needs different permissions. For the shared login setup, see Usage.
Spotify app registration
- Create an app in the Spotify developer dashboard.
- Register
http://127.0.0.1:8100as its redirect URI. Spotify accepts a loopback IP address for local HTTP development, but notlocalhost. See Spotify’s redirect URI rules. - Store the credentials as
SPOTIFY_OAUTH_CLIENT_IDandSPOTIFY_OAUTH_CLIENT_SECRETin your R environment. See the environment setup example for.Renvironsyntax. - Check your app’s development-mode access rules. Development apps require the owner to have Spotify Premium, and test users need to be on the app’s allowlist.
Shiny app example
Save this as app.R, run it, and open
http://127.0.0.1:8100 in a regular browser. After
connecting Spotify, click Load top tracks.
library(shiny)
library(shinyOAuth)
client <- oauth_client(
provider = oauth_provider_spotify(),
client_id = Sys.getenv("SPOTIFY_OAUTH_CLIENT_ID"),
client_secret = Sys.getenv("SPOTIFY_OAUTH_CLIENT_SECRET"),
redirect_uri = "http://127.0.0.1:8100",
scopes = c("user-read-private", "user-top-read"),
resource_bases = c(spotify = "https://api.spotify.com/v1")
)
ui <- oauth_ui(fluidPage(
h2("My top tracks"),
actionButton("load", "Load top tracks"),
tableOutput("tracks")
), id = "auth", client = client)
server <- function(input, output, session) {
auth <- oauth_module_server("auth", client)
tracks <- reactiveVal(NULL)
observe({
connection <- auth[["connection"]]()
result <- isolate(tracks())
if (is.null(connection) ||
!connection[["has_scopes"]]("user-top-read") ||
(!is.null(result) &&
!identical(result[["authorization"]], connection[["id"]]))) {
tracks(NULL)
}
})
observeEvent(input[["load"]], {
connection <- req(auth[["connection"]]())
req(connection[["has_scopes"]]("user-top-read"))
data <- tryCatch({
response <- connection[["request"]](
"spotify", "me/top/tracks",
query = list(limit = 10, time_range = "short_term"),
required_scopes = "user-top-read",
refresh = TRUE
)
httr2::resp_check_status(response)
body <- httr2::resp_body_json(response, simplifyVector = FALSE)
vapply(body[["items"]], function(track) track[["name"]], character(1))
}, error = function(e) NULL)
tracks(list(authorization = connection[["id"]], data = data))
})
output[["tracks"]] <- renderTable({
connection <- req(auth[["connection"]]())
req(connection[["has_scopes"]]("user-top-read"))
result <- tracks()
req(identical(result[["authorization"]], connection[["id"]]))
values <- result[["data"]]
validate(need(!is.null(values), "Could not load tracks. Try again later."))
validate(need(length(values) > 0, "No listening data to show yet."))
data.frame(Track = values)
})
}
runApp(shinyApp(ui, server), port = 8100, launch.browser = FALSE)API requests and scopes
The request asks for up to ten tracks from the short-term range,
using the user-top-read permission. The module obtains and
stores the access token; the connection checks the operation’s scope and
approved API address, refreshing the token if needed before the request.
observeEvent() loads the data when the button is clicked,
and renderTable() displays it for the current login. The
observer clears cached tracks on logout, a new login, or loss of
permission to read them.
Other Spotify endpoints require their corresponding scopes. Empty results can be normal for accounts without listening history; API errors can indicate missing permissions, app access restrictions, or request limits.
Full dashboard example
A larger example is installed with the package. It adds profile information, currently playing music, top artists, and recent tracks, with a bslib layout. It uses the same authentication setup as the example above.
install.packages(c("bslib", "ggplot2", "DT", "purrr", "dplyr"))
dashboard_file <- system.file(
"examples", "spotify-dashboard.R", package = "shinyOAuth", mustWork = TRUE
)
file.show(dashboard_file) # Read or copy the complete source.
source(dashboard_file) # Run after setting your Spotify credentials.The installed dashboard validates Spotify link and image URLs and escapes text in its HTML output.