Azure/AzureAuth

Acquiring different token for multiple users in Shiny

Closed this issue · 10 comments

I have a Shiny app which runs in the network and multiple users can access it.
With the help of the instructions, Azure authentication work without any issue.

In order to extract user information, I call another tokenuser <- get_azure_token but it returns same user's information in the app.

library(AzureGraph) 
library(AzureAuth) 
library(AzureRMR)  
library(shiny)

myresource <- 'xxxx'
mytenant <- 'xxxx'
myapp <- 'xxx'
myredirect='http://localhost:2121'
mysecret <- 'xxxx'

ui = function(req) {
    qs <- parseQueryString(req$QUERY_STRING)
    redirect <- NULL
    
    if (is.null(qs$code)) {
        auth_uri <- build_authorization_uri(myresource, mytenant, myapp, redirect_uri=myredirect, version=2)
        redirect <- tags$script(HTML(paste0('window.location.replace(\'', auth_uri, '\');')))
    }
    
 fluidPage(
     tags$head(
         redirect
     ),

    titlePanel('Old Faithful Geyser Data'),
    actionButton('go', 'Go'),
    sidebarLayout(
        sidebarPanel(
            sliderInput('bins','Number of bins:',min = 1,max = 50,value = 30)),
        mainPanel(plotOutput('distPlot'))
    )
    
)}

server <- function(input, output,session) {

    qs <- isolate(parseQueryString(session$clientData$url_search))
    
    if (!is.null(qs$code)) {
        code <- qs$code
        
        token <- get_azure_token(resource = c('https://graph.microsoft.com/.default', 'openid', 'profile', 'email'), 
                                 mytenant, myapp,  password=mysecret,
                                 authorize_args=list(redirect_uri=myredirect),
                                 auth_code=code, version=2, use_cache=FALSE)
        
        
        tokenuser <- get_azure_token(resource='https://graph.microsoft.com/.default',
                                     app=AzureRMR:::.az_cli_app_id,version=2, use_cache = FALSE)
 
        tokenuserinfo<-decode_jwt(tokenuser)$payload
    }
    
    output$userinfo<-renderText(paste(tokenuserinfo$given_name,tokenuserinfo$family_name,tokenuserinfo$email))
    
    output$distPlot <- renderPlot({
        x    <- faithful[, 2]
        bins <- seq(min(x), max(x), length.out = input$bins + 1)
        hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })
}

shinyApp(ui = ui, server = server)

Many thanks in advance

Azure configuration
3
2
1

Try adding the prompt="login" option on the call to get the authorization code: build_authorization_uri(*, prompt="login"). This will force AAD to ask for the user's credentials.

Thank you.
I have added it. Still the issue is same; logged in with user1 and it shows user1's name, logged in with user2 in another machine but it still shows user1's name.

When I execute below line from R it says "Using client_credentials flow", is it normal as I was expecting it to use authorization code?

I was assuming I could get any info about user with the single token only by adding "email" is in the scope or "User.Read" .

 mytoken <- get_azure_token(resource = c("https://graph.microsoft.com/.default", "openid", "profile", "email","offline_access")
                                                 ,tenant= mytenant
                                                 ,app= myapp
                                                 ,password=mysecret,
                                                 authorize_args=list(redirect_uri=myredirect),
                                                 auth_code=code, version=2, use_cache=FALSE)

Using client_credentials flow

If you include the password arg, that will cause get_azure_token to default to client credentials, in which case the password is used as the client secret. I have no idea what the email scope will do in this case, as you don't have a logged-in user.

Still the issue is same; logged in with user1 and it shows user1's name, logged in with user2 in another machine but it still shows user1's name.

Please provide more details on how exactly you "log in with user1" and also with "user2 on another machine". Do you mean that your machine running the Shiny server has 2 separate client sessions on different machines? Or what?

I do not have Shiny server but I have above Shiny app running in a machine in the internal network.
I would like the other users to be able to login to this Shiny app from other machines in same network using this library.

That login part runs perfectly without any issue, i.e other users from other machines can login with their credentials.
However I was not able to grab any information about the user (email or name).
I have checked #17 .

token<-... in my code works without any error and gets users in.

In order to retrieve I inserted below part from my above code. It returns first user's information.
I might be in wrong path.

tokenuser <- get_azure_token(resource='https://graph.microsoft.com/.default',
                                     app=AzureRMR:::.az_cli_app_id,version=2, use_cache = FALSE)

Add auth_type="authorization_code" in the get_azure_token call. Remove the password arg.

With the

token <- get_azure_token(resource = c("https://graph.microsoft.com/.default", "openid", "profile", "email","offline_access")
                                                ,tenant= mytenant
                                                ,app= myapp,
                                 auth_type="authorization_code",
                                                authorize_args=list(redirect_uri=myredirect),
                                                auth_code=code, version=2, use_cache=FALSE)

It returns

Warning: Error in as.character: cannot coerce type 'closure' to vector of type 'character'
  61: curl::curl_escape
  60: FUN
  59: vapply
  58: compose_query
  56: body_config
  54: httr::POST
  53: private$initfunc
  52: <Anonymous>
  50: initialize
  49: AzureTokenAuthCode$new
  48: get_azure_token
  47: server [C:\ESG\ESG_Form/app.R#452]
Error in as.character(url) : 
  cannot coerce type 'closure' to vector of type 'character'

Change your redirect to a mobile & desktop redirect.

Now the situation changed to below;

If I would try to login from the server, it opens another Azure login page in the server and then let's me in.

If I would try to login from another machine (client), it opens the Azure login page in the server, but the user would not be able to see it from client machine.

I think at this point there's nothing wrong with the package. Consider asking on Stackoverflow or the RStudio community forums for tech support.