PowerBI Secure Access Blob Storage - security

I have created a PowerBI report with embedded videos using the HTML customer visual. The videos are hosted on an Azure Blob Storage so I have generated a SAS token that I have added to the video URL in my data.
However, I would look to increase the security of Blob Storage and find a better solution to avoid having a SAS token out there for everyone to use and with limited control over.
For example, would it be possible to access a token provider that would generate an access token on the fly if a set of credentials is correct? This way, I would be able to control the access to the videos.
I looked into Shared Access Signature but was not able to implement it from PowerBi. Any other ideas are welcome!

I tried to reproduce the same in my environment and got the results like below:
To avoid a SAS token accessible to everyone, try generating the access token by specifying user's IP address or IP Range who are allowed to access:
If the user's IP address is not in the range, the user will get the below error while accessing the SAS URL:
Would it be possible to access a token provider that would generate an access token on the fly if a set of credentials is correct.
You can make use of Authorization-Code Flow to generate the access token which will ask for the Users interaction while generating the token.
Make use of the below Parameters to generate the access token:
GET https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:*****
grant_type:authorization_code
scope:scope
redirect_uri:redirect_uri
code:code
A sign-in screen will appear to validate the Users credentials:
Access token got generated successfully like below:

Related

Azure Active Directory add custom data to Oauth2 token

I'm using the auth endpoint https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token programmatically (Nodejs) for getting back a token that will be used against my API. I have everything properly configured to send the request using a "Client secret" I setup on the Azure Portal - App registration service.
This issues a valid token that I can later check with the help of the Passport azure AD npm library. However I've been looking for a way of somehow adding more metadata to that token (i.e. a custom user name) so that when it gets validated and parsed by my server upon future requests I can extract this information.
When issuing tokens using a frontend application library (like msal) I have access to some of the user's information on the token (like its oid and email address). I'd like to be able to "extend" the token generated by the client secret to also contain a couple custom fields, which I can use after validating and parsing it.
Hopefully that's clear enough. I'm lost on how to achieve this. Thanks
It is a common requirement for APIs to authorize based on claims stored in the business data, eg roles or other custom data.
OPTION 1
Ideally the authorization server can reach out at the time of token issuance to an API or database to include the custom claims. This is not always supported though.
OPTION 2
Another option is for the API to process the incoming access token into a ClaimsPrincipal and to include custom values at that point. For an example see this code of mine.
PRIVACY
When adding more claims, you should also be careful about revealing sensitive data in JWTs returned to internet clients. Eg if you include names and emails, they are easily readable, and this can sometimes be a security concern.

Obtain SharePoint specific access token for a non-user application

I am working on a PHP web app that needs to make HTTP requests to the Sharepoint API with Sites.Selected permission to a specific SharePoint site. It is NOT viable for me to provide a user sign-in experience so I need to treat it as a non-user/daemon application.
I've read the docs and looked at many different forums for the solution but as of yet I've been unsuccessfull in obtaining a SPO specific access token, although I think I'm close.
I am using this StackOverflow answer as a guide: https://stackoverflow.com/a/63386756/19038862
This is what I've done:
Registered an Azure App: (Image of my Azure App Overview)
Created a client secret in the App dashboard: (Image of the client secret page)
Successfully sent a request to https://login.microsoftonline.com/{{app_tenant_id}}/oauth2/v2.0/token using the client secret in Postman: (Image of Postman request)
The request made in step 3 returns an access token (I assume a MS Graph access token?), but it DOES NOT return a refresh token, which is what the afforementioned StackOverflow answer suggests you need to "swap" for an SPO specific access token.
How do I obtain this refresh token so that I can swap it for a SPO access token? Or what better way is there to get my hands on a SPO specific access token from a non-user app?
I wrote this gist to guide you into getting Sites.Selected access to the desired site:
https://gist.github.com/ruanswanepoel/14fd1c97972cabf9ca3d6c0d9c5fc542
This guide shows you how to configure this as Application permissions, and via the Graph API.
I've found going through the Graph API is the best way to go.
Also strangely it's not possible to get delegated Sites.Selected permissions. You must set it up as an Application permission.
In the guide is described that you have to get a delegated auth token from graph but you are getting an application auth token. The token response of this flow does not contain a refresh_token. See here.
But you already wrote that you are not able to provide a user sign-in experience. One workaround would be to once manually get the access_token and refresh_token of a user with the delegated flow and then periodically get a new access_token with the refresh_token on your server. You could store these values in your database and update them when you fetch a new one.
First, the daemon-based client credential flow does not return a refresh token for you. You also can't redeem the refresh token of the graph API for an access token for SPO, which are two completely different API resources.
To get an access token for SPO you just need to set scope to: https://{tenant-name}.sharepoint.com/.default.

How to ensure that only authenticated users can read blobs in azure storage?

I'm trying to build some kind of instagram clone for me and my friends only. I'm using react in the frontend and node in the backend.
I'm also using azure to store the files my users upload. I've already manage to get Shared access signature (SAS), but I don't know if there's a more appropriate way to do this. Is generating a new SAS every time i want to show a post overkill? Is there a way to get a token so I can give an authenticated user read access to a container of blobs? So i dont have to make a sas for every blob.
At the moment, given a blob URL with valid sas token (not experired) in it, you can access the blob even in a browser with no login in my site.
Edit: To illustrate what I want to do here it is an example:
When you send some picture in a DM in twitter, you can try to get the URL of the picture. If you try to access that URL with incognito mode, you can't access that file. I can't find any resource on how to do something like that.

Microsoft Graph API: how to get access token without browser

I would like to upload a given file to Sharepoint. I'm using the Microsoft Graph API.
The documentation follows this workflow:
1. If no token, redirect the user to the Microsoft signin page.
2. The user is then redirected to the application, with an access token
3. Use access token to have an authorization bearer
4. Do what you gotta do...
My problem is the sign-in part. I don't want my users to be redirected to the Microsoft signin page. I want my application to connect and get the access token in the background (with cURL or whatever).
How can I do that? Why is the "open in browser" necessary?
I tried to replicate the sign-in process, but all I get back is the HTML response from the signin page.
Thanks in advance.
Your application act as a single-tenant service or daemon app.
The documentation about this scenario is here : https://developer.microsoft.com/en-us/graph/docs/authorization/app_only
The application must be registered in the AzureAD directory corresponding to the Office365 tenant
A first request is made by passing the application unique identifier and secret key as registered in the directory. This request returns an access token
The access token can now be used in the Authorization header of the following request to the Microsoft Graph API.
This method (of using Client ID and Secret) works well but there are other ways which may be better suited for similar scenarios.
The one major thing which is missing in access token generated this way is a user, meaning the token only contains the identity of the OAuth application (client) which called it but is not associated with any user for the request.
This could have a couple of implications:
Since the token is not associated with a specific user you will not know who performed the operation. In your example, you would not know who uploaded the file (and other similar information may be missing).
Access token without users will not work at all for some methods. For those, you need a delegated token.
Creating a delegated token requires some effort, if you are interested you can find the details in my article:
Getting Access Token for Microsoft Graph Using OAuth REST API

'[AUTHENTICATIONFAILED] Invalid credentials (Failure)' error for gmail.readonly, gmail.modify etc. scopes

I am getting the error mentioned in the title for gmail.readonly, gmail.modify and all other scopes except for full account access scope (https://mail.google.com/). Here is what I am trying to do.
I have a django-allauth setup to get offline access tokens (OAUTH2 bearer token and refresh tokens). I am using this token to fetch emails using python's imaplib. It works when I specify full account access scope but doesn't work for gmail.readonly scope. And I don't need the full access as I just want to fetch the emails using imaplib.
Reference Link
Problem solved ! For me it was just that google waiting for the confirmation on my phone that it's really me who try to connect to my account

Resources