R Shiny - WebSEAL authentication for R Shiny Server Open Source - shiny

It is my understanding that the open source version of Shiny Server does not support authentication.
We have an environment that uses the WebSEAL proxy service for authenticating user and channelling their access through to web applications.
We wish to expose a Shinyapp to authenticated users with the content served up being dependent on user group membership. WebSEAL is able to set the iv_user and iv_group variables in the HTTP Headers to pass onto the shinyapp via the junction, but the Open Source Shiny Server seems to be unable to access them (I.E. via the session$clientData object).
I’m wondering if anyone has worked out a way for an Open Source Shiny Server app to access the HTTP Headers to determine the user and groups.

If you just want to access HTTP headers, the UI can be a function that accepts a single argument for a request object that implements the Rook specification.
library(shiny)
ui <- function(request) {
print(as.list(request))
# get HTTP headers like request$HTTP_HEADER_NAME (all caps)
fluidPage(
tags$pre(
paste(capture.output(as.list(request)), collapse = "\n")
)
)
}
server <- function(input, output) {
}
shinyApp(ui, server)
One way to serve different pages depending on an HTTP header could be like this -
unauthorizedPage <- function() {
"Unauthorized"
}
memberPage <- function() {
fluidPage(
"Member page"
)
}
ui <- function(request) {
# serve memberPage() if request contains header `iv_group: member`
# otherwise serve unauthorizedPage()
if (!identical(request$HTTP_IV_GROUP, "member"))
return(unauthorizedPage())
memberPage()
}
server <- function(input, output) {
}
shinyApp(ui, server)

Related

Why my angular HTTP request can't GET on local Django server?

I made an Angular application able use an online api to get a json and do stuff.
But, although the json is the same, if I try to change only the url of the json by setting a local url of a server written in django, angular would seem not to connect anymore ...
My question is, why if with an online cloud server works, with a local one wouldn't?
I tried making this server "on cloud" opening the router's port, also setting up a ddns, and using postman or a browser it seems to work, but when i try to connect with angular it still doesn't get the data...
I am sure 100% that the server answer, with the right json data, because django prints on console that he received a HTTP GET request :
http://i.imgur.com/TIQnIcR.png
I remind you that the HTTP angular request worked with another api, but i will still show up some code :
export class ProdottoService {
private prodotti: Array<ProdottoModel>;
constructor(private httpClient: HttpClient) {
this.prodotti = new Array<ProdottoModel>();
var url:string = "https://gist.githubusercontent.com/saniyusuf/406b843afdfb9c6a86e25753fe2761f4/raw/523c324c7fcc36efab8224f9ebb7556c09b69a14/Film.JSON";
var local_url:string = "http://127.0.0.1:8000/films/?format=json";
httpClient.get(local_url)
.subscribe((films : Array<Object> ) => {
films.forEach((film => {
this.prodotti.push(new ProdottoModel(film));
}));
}
);
}
getProdotti(): Array<ProdottoModel> {
return this.prodotti;
}
}
Result using external api :
http://i.imgur.com/MT7xD9c.png
Thanks in advace for any help :3
-- EDIT -- IS A CORS ISSUE
In django settings.py file :
CORS_ORIGIN_WHITELIST = (
'localhost:8000',
'127.0.0.1:4200'
)
INSTALLED_APPS = (
...
'corsheaders',
...
)
MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
But i don't know if there's a way to set-up CORS settings in Angular
Based on feedback, this is a CORS issue. Your Django server is getting the requests and responding because localhost is an implicitly trusted domain in Django's dev environment, but it isn't configured properly to set the cross origin header, so the browser is not allowing your app to see the response because the server hasn't authorized the domain explicitly.
The problem here is that you've set CORS white list like this:
CORS_ORIGIN_WHITELIST = ( 'localhost:8000', '127.0.0.1:4200' )
it needs to be like this:
CORS_ORIGIN_WHITELIST = ( 'localhost:4200' )
angular runs on localhost, not 127.0.0.1, even though that's what localhost is an alias for, your browser still differentiates them for CORS. Also, you do not need to whitelist the domain your serving off of, that's not crossing any origin as it's the same origin.
In your screenshot, it looks like the response is type "document..." something. The simplest fix, with only the code here, is to convert the string to JSON.
JSON.parse(films)
This is the wrong answer, because it's being set to that because of the CORS issue in the other answers.

How to embed an Apache Superset dashboard in a webpage?

I am trying to implement the Apache superset dashboard in a webpage.
Anyone have any idea how to implement this?
Keep the iframe tag line as you mentioned.
<iframe src="linkToYourDashBoard?standalone=true"></iframe>
and check the superset_config.py file.
HTTP_HEADERS = {'X-Frame-Options': 'SAMEORIGIN'}
Change the line to
HTTP_HEADERS = {'X-Frame-Options': 'ALLOWALL'}
or
HTTP_HEADERS = {}
Don't forget to add superset_config.py file to your python path.
First, you need to update the public roles with these options.
Security/List Roles:
can explore json on Superset,
can dashboard on Superset,
all database access on all_database_access
Second, embed your dashboard in your HTML
<iframe src="localhost:8088/superset/dashboard/5/?standalone=true"></iframe>
Superset Embedded SDK allows you to embed
dashboards from Superset into your own app, using your app's authentication.
superset backend server: update superset_config.py or config.py
FEATURE_FLAGS = {
"EMBEDDED_SUPERSET": True, # requirement
}
"GUEST_ROLE_NAME": "Public", # you might need to edit role permissions when 403 error
"GUEST_TOKEN_JWT_EXP_SECONDS": 300 # 5 minutes, or you could set it longer
your app's backend server
fetch access_token
http://localhost:8088/api/v1/security/login
fetch guest_token
http://localhost:8088/api/v1/security/guest_token/
your app's frontend, for example:
<script src="https://unpkg.com/#superset-ui/embedded-sdk"></script>
<script>
supersetEmbeddedSdk.embedDashboard({
id: 'd3918020-0349-435d-9277-xxxxxx', // given by the Superset embedding UI
supersetDomain: 'http://localhost:9000',
mountPoint: document.getElementById('container'), // any html element that can contain an iframe
fetchGuestToken: () =>
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.xxxxxx.1RExnlLfdDI6P4vG3gB0otLL7XR_3OE2OZ0WhCKyTyE', // guest_token
dashboardUiConfig: {} // dashboard UI config: hideTitle, hideTab, hideChartControls (optional)
})
</script>
Please refer to: Embedding Superset dashboards in your React application
Superset now provides the Superset Embedded SDK, an NPM package for inserting an iframe that will embed your Superset dashboard. I'm using it at the moment and it is relatively straightforward; this is the current implementation example provided in the docs:
import { embedDashboard } from "#superset-ui/embedded-sdk";
embedDashboard({
id: "abc123", // given by the Superset embedding UI
supersetDomain: "https://superset.example.com",
mountPoint: document.getElementById("my-superset-container"), // any html element that can contain an iframe
fetchGuestToken: () => fetchGuestTokenFromBackend(),
dashboardUiConfig: { hideTitle: true }, // dashboard UI config: hideTitle, hideTab, hideChartControls (optional)
});
Obviously the end result could still be achieved by adding the iframe "manually," but using the official abstraction might provide simplicity and future functionality in subsequent versions.

How can I render a list in a shiny application

I've tried the method of showing lists in a shiny app in the following link:
How to print lists of lists of uneven length in Shiny and nothing is displayed so far.
ui <- fluidPage(
verbatimTextOutput("res")
)
server <- function(input, output, session) {
output$res<-renderPrint({
x=list(nam=('d','h','k','m'),num=(3,2,8,9))
a=tapply(x[,1],x[,2],summary)
})}
shinyApp(ui = ui, server = server)

Make all users who have logged into Shiny-Server reload without resigning in

I have a number of individuals who log into a shiny-server application where they all interact. After the app stops, I load another application, they each click ``reload'', and they all interact on the new application.
If someone clicks ``reload'' early, then everyone needs to re sign in. Is there any way to avoid this. I'd like to just regenerate shiny's default reload-page.
I'm not sure how your reaload works as you havent posted any code, however you can force F5 page refresh like so. parts of the code example are taken from here`
library(shiny)
library(shinyjs)
jscode <- "shinyjs.reload = function() { window.location.reload(true); }"
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jscode),
textInput("text", "Text"),
actionButton("reload", "Refresh app")
)
server <- function(input, output, session) {
observeEvent(input$reload, {
js$reload();
})
}
shinyApp(ui = ui, server = server)

How to create an interactive environment within shinyapp

I am using the below query in sever.R and it works fine when run locally. However, when the app is deployed over shinyapps.io or on a web hosting server, I get the following error
Error: Requires an interactive environment
Code deployed over shinyapp:
updateStatus <- function(text, token, link=NULL) {
## text prepocessing
text <- enc2utf8(text)
text <- gsub(" ", "+",text)
## query including text
query <- paste('https://graph.facebook.com/me/feed?message=', text, sep="")
## adding URL
if (!is.null(link)){
query <- paste(query, "&link=", link, sep="")
}
## making query
if (class(token)[1]=="config"){
url.data <- POST(query, config=token)
}
if (class(token)[1]=="Token2.0"){
url.data <- POST(query, config(token=token))
}
if (class(token)[1]=="character"){
url <- paste0(query, "&access_token=", token)
url.data <- POST(url)
}
if (class(token)[1]!="character" & class(token)[1]!="config" & class(token)[1]!="Token2.0") {
stop("Error in access token. See help for details.")
}
## output
if (url.data$status_code==200){
id <- fromJSON(rawToChar(url.data$content))$id
if (is.null(id)){
message("Failed update. OAuth token does not have permission to update status. ",
"See ?fbOAuth for more details.")
}
message("Success! Link to status update: ", paste("http://www.facebook.com/", id, sep=""))
}
if (url.data$status_code==400){
error <- fromJSON(rawToChar(url.data$content))$error$code
message <- fromJSON(rawToChar(url.data$content))$error$message
if (error==2500){
message("Failed update. OAuth token does not have permission to update status. ",
"See ?fbOAuth for more details.")
}
if (error!=2500){
message("Failed update.", message)
}
}
}
observeEvent(input$FBButton,{
Sys.setenv("HTTR_SERVER_PORT" = "1410/")
updateStatus(paste("Analysis by using www.abc.com",sep=""),
token=oauth2.0_token(oauth_endpoints('facebook'),
oauth_app('facebook', 'app', 'key'),
scope = 'ads_management',
type = 'application/x-www-form-urlencoded',
cache = FALSE)$credentials$access_token,
link = "www.rstudio.com")
})