Azure / Microsoft365R

R SDK for interacting with Microsoft 365 APIs
Other
318 stars 45 forks source link

Trying to access sharepoint site from shinyapps.io with authentication through Azure Active Directory #71

Closed LeoTimmermans closed 3 years ago

LeoTimmermans commented 3 years ago

I am trying to develop a shiny app (which is hosted on shinyapps.io). The data resides on a company sharepoint site. To authenticate users I am following allong the Authenticating from Shiny vignette. This works when I use resource <- "https://graph.microsoft.com" instead of resource <- "https://management.azure.com". I get a token, but am at a loss how to use this to connect to the sharepoint site (to retrieve the data (rds-files) from there).

Is this possible? If so, how?

hongooi73 commented 3 years ago

Yes, you can do this, although it's not very well documented.

Put something like this in your server.R (or maybe ui.R, I'm not that familiar with how Shiny works):

token <- AzureAuth::get_azure_token(...) # your existing code here

# must load Microsoft365R to ensure class methods are updated
library("Microsoft365R")

gr <- AzureGraph::create_azure_login(token=token)
site <- gr$get_sharepoint_site("site name")
LeoTimmermans commented 3 years ago

Thanks for the response. I think I am getting closer but not there yet.

create_azure_login gives an error: AzureGraph::create_azure_login(token=token) Error: 'create_azure_login' is not an exported object from 'namespace:AzureGraph'

I guess it needs to be: gr <- AzureGraph::create_graph_login(token=token)

When I use this I get following error: AzureR data directory does not exist; login credentials not saved. Warning: Error in process_response: Forbidden (HTTP 403). Failed to complete operation. Message: Forbidden (HTTP 403). Failed to complete operation. Message: Access denied.

shinyapps.io does not have persistant data storage. Also the folder structure is different from a windows machine. So a folder for caching a token does not exist for shiny apps hosted on shinyapps.io (or in another instance of shiny server). The root for shiny apps on shinyapps.io is: /srv/connect/apps/

The error message occurs at the step: site <- gr$get_sharepoint_site("site name"). This still gives me following info: image

However the shiny app fails when I try to get data or info from the sharepoint site. For instance: drives <- site$list_drives(), items <- site$list_items() or drive <- sp_site$get_drive()

This means I still do not have access to the data on the sharepoint site.

hongooi73 commented 3 years ago

Ok, in that case, try

library("Microsoft365R")

gr <- AzureGraph::ms_graph$new(token=token)
site <- gr$get_sharepoint_site("site name")

I'll look into fixing AzureGraph and AzureRMR to not assume the presence of a caching directory.

hongooi73 commented 3 years ago

However the shiny app fails when I try to get data or info from the sharepoint site.

If you managed to obtain the site object, that means Microsoft365R is working. If you can't list the drives, there must be an issue with the permissions you've set on your app registration. Are you using the app reg from Microsoft365R, or something else?

hongooi73 commented 3 years ago

Actually, AzureGraph/Microsoft365R should work fine without a caching dir. Your 403 error is because your authentication setup isn't working properly.

LeoTimmermans commented 3 years ago

Should I be looking into https://github.com/Azure/Microsoft365R/blob/master/inst/app_registration.md? I'm not familiar with app registrations. Is this done in Azure Active Directory or on sharepoint?

hongooi73 commented 3 years ago

App registrations are an AAD thing, not Sharepoint. Basically you need to tell Azure about your Shiny app: what permissions it needs, who is allowed to use it (anyone with a Microsoft account, or only people in your org), any secure credentials required, etc.

If this is the first time you're dealing with app regs, start here: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-overview

There are vignettes scattered across AzureAuth, AzureGraph and Microsoft365R that also have relevant information: https://cran.r-project.org/web/packages/AzureAuth/vignettes/scenarios.html https://cran.r-project.org/web/packages/AzureGraph/vignettes/auth.html https://cran.r-project.org/web/packages/Microsoft365R/vignettes/auth.html

Creating a new app registration usually involves going to the Azure portal or using the CLI. As a first point of contact, you should talk to a sysadmin in your org. If you're still having problems, shoot me an email.

LeoTimmermans commented 3 years ago

Ok. Thanks. I'm going to look into this with IT next week and will let you know.

LeoTimmermans commented 3 years ago

No luck so far. IT is looking into this. When trying locally, I get following: image

I would say that is not a problem in the app registration, or is it?

hongooi73 commented 3 years ago

You need to supply the ID of your app registration in the create_graph_login() call. If you don't do this, it will use a default app ID which doesn't have the required permissions to read Sharepoint sites and drives.

If you use Microsoft365R, by default it will supply its own app ID which has these permissions. However, this ID won't work for a Shinyapps.io app; you'll have to create your own. See the links posted above; in addition, AzureAuth has a Shiny vignette that you should also read.

hongooi73 commented 3 years ago

The overall process is like this:

LeoTimmermans commented 3 years ago

When I try using c("https://graph.microsoft.com/.default", "openid", "offline_access") I am getting errors. There are different types of errors with differing code:

# in ui.R -- see AzureAuth Shiny vignette
auth_uri <- build_authorization_uri(c("https://graph.microsoft.com/.default", "openid", "offline_access"),
    tenant="yourtenant", app="yourappid", redirect_uri="https://your.shiny.site")
redir_js <- sprintf("location.replace(\"%s\");", auth_uri)
tags$script(HTML(redir_js))

# in server.R
opts <- parseQueryString(isolate(session$clientData$url_search))
token <- get_azure_token(c("https://graph.microsoft.com/.default", "openid", "offline_access"),
    tenant="yourtenant", app="yourappid", authorize_args=list(redirect_uri="https://your.shiny.site"),
    auth_type="authorization_code",
    authcode=opts$code)

gr <- AzureGraph::ms_graph$new(token=token)
site <- gr$get_sharepoint_site(site_url = "yoursharepointsiteurl")
drv <- site$get_drive()

Gives following error:

Warning: Error in get_azure_token: unused argument (authcode = opts$code)
Error in get_azure_token(c("https://graph.microsoft.com/.default", "openid",  : 
unused argument (authcode = opts$code)

That might be because the app registration uses a secret. So I change the get_azure_token to:

token <- get_azure_token(resource         = c("https://graph.microsoft.com/.default", "openid", "offline_access"),
                           tenant         = "yourtenant",
                           app            = "yourappid",
                           auth_type      = "authorization_code",
                           authorize_args = list(redirect_uri="https://your.shiny.site"),
                           use_cache      = FALSE,
                           auth_code      = opts$code,
                           password       = "yoursecret")

The error changes to:

Error : Resource for Azure Active Directory v1.0 token must be a single string

When I change the get_azure_token to:

token <- get_azure_token(resource         = c("https://graph.microsoft.com/.default"),
                           tenant         = "yourtenant",
                           app            = "yourappid",
                           auth_type      = "authorization_code",
                           authorize_args = list(redirect_uri="https://your.shiny.site"),
                           use_cache      = FALSE,
                           auth_code      = opts$code,
                           password       = "yoursecret")

I get following error:

Warning: Error in process_response: Unauthorized (HTTP 401). Failed to complete operation. Message:
Access token validation failure. Invalid audience.
Error in process_response(res, match.arg(http_status_handler), simplify) : 
Unauthorized (HTTP 401).

I am guessing this is caused by the build_authorization_uri. So I changed that:

auth_uri <- build_authorization_uri(c("https://graph.microsoft.com/.default"),
                                        tenant="yourtenant", app="yourappid", authorize_args=list(redirect_uri="https://your.shiny.site"),

But then I cannot complete the login. Part of the url I seeing says: invalid_resource. So I leave the .default out. Which makes it the code I was already using. This is:

# in ui.R -- see AzureAuth Shiny vignette
auth_uri <- build_authorization_uri("https://graph.microsoft.com/",
    tenant="yourtenant", app="yourappid", redirect_uri="https://your.shiny.site")
redir_js <- sprintf("location.replace(\"%s\");", auth_uri)
tags$script(HTML(redir_js))

# in server.R
opts <- parseQueryString(isolate(session$clientData$url_search))
token <-token <- get_azure_token(resource         = "https://graph.microsoft.com/",
                           tenant         = "yourtenant",
                           app            = "yourappid",
                           auth_type      = "authorization_code",
                           authorize_args = list(redirect_uri="https://your.shiny.site"),
                           use_cache      = FALSE,
                           auth_code      = opts$code,
                           password       = "yoursecret")

gr <- AzureGraph::ms_graph$new(token=token)
site <- gr$get_sharepoint_site(site_url = "yoursharepointsiteurl")
drv <- site$get_drive()

Which takes me back to the error I was already getting:

Warning: Error in process_response: Forbidden (HTTP 403). Failed to complete operation. Message:
Error in process_response(res, match.arg(http_status_handler), simplify) : 
Access denied.

All this makes me think that the step:

hongooi73 commented 3 years ago

Regardless, this isn't the place for debugging random user code, and there doesn't seem to be any problem with Microsoft365R here. You may want to ask on Stackoverflow or the RStudio community forums for help. If you're still unable to make progress, as mentioned before, send me an email.

hongooi73 commented 3 years ago

Draft vignette here: https://github.com/Azure/Microsoft365R/blob/shiny-auth/vignettes/shiny.Rmd