Skip to content

Instantly share code, notes, and snippets.

@jnolis
Last active August 7, 2021 19:30
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jnolis/49d328f58e6bb0074442d032f4e79c7f to your computer and use it in GitHub Desktop.
Save jnolis/49d328f58e6bb0074442d032f4e79c7f to your computer and use it in GitHub Desktop.
Do 3-legged Twitter authentication for rtweet (lite version)
# _____ __ __
# |__ / / /__ ____ _____ ____ ____/ /
# /_ <______/ / _ \/ __ `/ __ `/ _ \/ __ /
# ___/ /_____/ / __/ /_/ / /_/ / __/ /_/ /
# /____/ /_/\___/\__, /\__, /\___/\__,_/
# /____//____/
# RTWEET + 3-LEGGED-AUTH DEMO (LITE)
# This code demonstrates how to do 3-legged authentication for Twitter
# using the {rtweet} package. Based heavily on code from Michael Kearney.
# This is the 'lite' version which requires the user to reauthenticate every time
# they refresh the page. The full version is in a separate gist
# To run this you need:
# 1. An app set up in the twitter developer portal (and http://127.0.0.1 set as a callback URL)
# 2. A config.yml file set up with the API keys like so:
# default:
# consumer_key: "xxx"
# consumer_secret: "xxx"
# access_token: "xxx"
# access_secret: "xxx"
# then to actually run it, use the command: `shiny::runApp(port=80L, launch.browser=FALSE)` and navigate to
# the url http://127.0.0.1 in your browser. It's important that you use port 80 and your desktop browser instead
# of the RStudio one for the app to work.
library(shiny)
library(httr)
library(rtweet)
library(jsonlite)
# this loads the consumer/access keys from a yaml file using the config package.
# You can load them however you want!
keys <- read_json("config.json")
# this is a modification of Michael's code to make the signature for authenticating twitter
# API requests. It's pulled from tokens.R in the rtweet package
oauth_sig <- function(url, method,
token = NULL,
token_secret = NULL,
private_key = NULL, ...) {
httr::oauth_header(httr::oauth_signature(url, method, app, token,
token_secret, private_key, other_params = list(...)))
}
# This function creates a URL for users to click to authenticate.
# You should use it to show a URL when users haven't authenticated yet.
# the callback_url HAS to be in the app configuration on the developer portal,
# and it needs to have the right http/https protocol.
# for testing in RSTudio I found it best to user 127.0.0.1 and have shiny use port 80
get_authorization_url <- function(app, callback_url, permission=NULL){
private_key <- NULL
response <- httr::POST("https://api.twitter.com/oauth/request_token",
oauth_sig("https://api.twitter.com/oauth/request_token",
"POST", private_key = NULL, oauth_callback = callback_url))
httr::stop_for_status(response)
params <- httr::content(response, type = "application/x-www-form-urlencoded")
authorize_url <- httr::modify_url("https://api.twitter.com/oauth/authenticate",
query = list(oauth_token = params$oauth_token, permission = permission))
authorize_url
}
# Once a user authenticates them, Twitter will pass them back to the callback
# url in the authentication one, with the results of the authentication in the query
# of the callback url. This function takes the information from the query
# and does the final conversion to get it into the useful format
get_access_token <- function(app, oauth_token, oauth_verifier){
url <- paste0("https://api.twitter.com/oauth/access_token?oauth_token=",
oauth_token,"&oauth_verifier=",oauth_verifier)
response <- httr::POST(url,
oauth_sig(url,
"POST",
private_key = NULL))
if(response$status_code == 200L){
results <- content(response,type="application/x-www-form-urlencoded", encoding="UTF-8")
results[["screen_name"]] <- NULL # since storing that might be creepy
results[["user_id"]] <- NULL # since storing that might be creepy
results
} else {
NULL
}
}
# The app we'll be using. I didn't give it a name since it doesn't seem to matter
app <- oauth_app(
app = "",
key = keys$consumer_key,
secret = keys$consumer_secret
)
ui <- fluidPage(
verticalLayout(
uiOutput("main") # this will either show a link to authenticate or some tweets
)
)
server <- function(input, output, session) {
# this will be NULL if the user hasn't logged in yet, otherwise
# it will have the valid twitter token for user
access_token <- reactive({
# is the user is coming in from having just authenticated?
# if yes save the tokens, if not then no keys to user
access_token <- NULL
query <- getQueryString(session)
if(!is.null(query)
&& !is.null(query$oauth_token)
&& !is.null(query$oauth_verifier)){
access_token <- get_access_token(app, query$oauth_token, query$oauth_verifier)
}
# turn the information from the file into a valid token object
if(!is.null(access_token)){
create_token(app="",
keys$consumer_key,
keys$consumer_secret,
access_token = access_token$oauth_token,
access_secret = access_token$oauth_token_secret)
}
})
# either show the authentication URL or a few tweets
output$main <- renderUI({
if(is.null(access_token())){
url <- get_authorization_url(app, callback_url = "http://127.0.0.1")
a(href = url, "Click here to authorize this app")
} else {
do.call(div,lapply(get_my_timeline(token = access_token())$text[1:3], p))
}
})
}
# make sure you use port 80 or whatever you put in the twitter developer portal
# in RStudio if you hit "Run App" it ignore the port, so watch out!
shinyApp(ui = ui, server = server, options=list(port=80L))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment