How to use the omniauth gem to set up oauth access to the Power BI API - ruby-on-rails

We have a Ruby on Rails application and we use the Omniauth gem to set up OAuth access for our users to several APIs. The Microsoft Graph API is one of these. Now we want to add the Microsoft Power BI API.
We usually use a Omniauth "plugin" gem specific to the API. These gems facilitate the process specific for that API by calling specific API methods and using specific attributes in the data provided but the process is the same for all these API's. For Power BI no such plugin gem is available.
The generic process that Omniauth uses to create OAuth access (create an access token) for a user is
request the access token from the API and
request information of the user (using that access token)
create a user specific record containing an identifier for that person (uid), general information of the user (email/name) and the access token
The problem we run into occurs because the Power BI API does not seem to have a method to retrieve user information. This method is available on the Microsoft Graph API (https://graph.microsoft.com/v1.0/me) so we tried using that. This leads to the following two problems:
You need to specify a scope on the API requests and that scope has to also be defined on the app on the Microsoft Azure Portal (AAD). The key and secret of that app is also used on the request to the API. It is possible to add a scope for the Graph API and PowerBI API on the app. However, when combining the scopes of these API's when calling the PowerBI API leads to exceptions
After getting an access token from the Power BI API using a scope that is limited to the Power BI API it is not possible to request user information from the Graph API with that access token
So we see no possibility to finish the Omniauth process to create user specific records with all the data that is needed to do subsequent Oauth authorised API calls for those users.
How can we
either get user identifying information from the Power BI API,
or get the required information from the Graph API using the access token granted by the Power BI API
or is there another way that we can get the Omniauth approach to work for the Power BI API?

I have no experience with either the Microsoft Graph API or the Microsoft Power BI API, so these are general thoughts on how to solve this using OAuth.
How can you get user identifying information from the Power BI API?
You can't. As you said, it doesn't exist: "the Power BI API does not seem to have a method to retrieve user information"
How can we get the required information from the Graph API using the access token granted by the Power BI API
Again, you can't. This is a dead end as the the PowerBI API will not accept a token with the combined scopes.
Is there another way that we can get the Omniauth approach to work for the Power BI API?
Since you can't combine the scopes, I think you will need to request two access tokens, one for each API. So, the thing to be solved here is how do you execute two OAuth sequences in the context of one request? Writing a custom OmniAuth strategy is one approach, but then you lose all the value in the "plugin" gem. I would try to still use the "plugin" gem, but in your callbacks controller, execute a redirect to the second OmniAuth route to step through the OAuth sequence for the Power BI API. You'd need to find an OmniAuth OAuth2 gem that's generic enough to use for the Power BI API (this could use the skip_info option since an info endpoint doesn't exist). You'd also need to persist the OmniAuth hash from the Graph API authentication in a different location, so it's not overwritten when you authenticate to the Power BI API.

Related

Securing Api Calls without OAuth2 client credentials flow in a SPA application

I've got a SPA application which gives statistics and information to anonymous users. It is a react spa app and will consume backend REST Web API(.net core). These data are not specific to users, therefore the information is freely available and no user authentication is required. However, I don't want my Backend Api layer to be exposed to the internet (i.e not use by anonymous applications such as postman, rest clients, etc). I'm familiar with the Client credential flow (OAuth) but I can't use it for this application because there is no concept for user login in this application.
What would be my best options that limit access to my API layer to anonymous applications (i.e postman, etc), or is it not possible at all?
You can't use client credentials flow for your SPA. Anyone would be able to download your SPA, extract the client id and secret and use it to call your API.
If you do not want to authenticate your users, there's no good way to protect your API. Move your SPA to a traditional web application hosted on a server to protect it using client credentials flow.
It's not possible to make an API accessible to a public client (your SPA) without also making it accessible to users making API calls from Postman or custom code. It's possible to do the reverse, only because of the limitations that browsers put in place.
Depending on what you're trying to achieve, you could use something like reCAPTCHA to validate that the users of your API are humans, not scripts. That along with human-scale rate limiting would probably filter out most of non-app users.

Is it safe to use username-password flow for Graph Api and Does this flow comes under Oauth implementation

We are trying to migrate from EWS to Microsoft graph api as Microsoft will no longer support basic authentication from October. While going through few online examples of Microsoft azure I came across below git location.
https://github.com/Azure-Samples/ms-identity-java-desktop/tree/master/Username-Password-Flow
Is it okay if I migrate our web application to use the above method or am I using the wrong flow in our case
Does the Username-Password flow come under Microsoft Oauth
We recommend that you move to an OAuth flow for your application and not bake user name and passwords in. Its unfortunate that the sample is called this because it is in fact using OAuth. The main user experience problem you will have otherwise is that any user with multi-factor auth on will not work.
We have some getting started tutorials for JAVA here https://developer.microsoft.com/en-us/graph/get-started/java specific to Microsoft Graph that you can use to call Exchange APIs to replace your EWS API calls.

Using SharePoint Rest API

I am trying to read SharePoint lists using the following endpoint (http://url/_api/web/lists) and I am passing the access token, but the response returns Access Denied.
While I use the same access token to call an endpoint from the graph API (https://graph.microsoft.com/v1.0/sites/root/lists) and it works fine.
Should I use a different access token when I work with SharePoint REST APIs? or am I missing something here?
Thanks.
Yes, you should use a different access token since the endpoints are different. The graph api and sharepoint api are different resource, you need to grant the application different permissions.
Note:
SharePoint APIs are available via the Microsoft Graph API. You may
want to consider using Microsoft Graph instead.

Authenticate to external API from a Jira add-on

I am building a Jira add-on that gives provides the user with the status of an object within my own API (not within Jira). My API is protected using OAuth 2.0. What is the best way to authenticate to my API from my Jira add-on?
I like how the Jira + GitHub/Bitbucket integration works. Specifically, the user retrieves API keys from GitHub and puts them in Jira. Jira then uses these keys to authenticate with and then retrieve data from GitHub. At least, this is how I think it works.
How can I achieve this same effect for my Jira add-on?
When you are building a cloud add-on then you can handle authentication without bothering admins (they don't need to copy anything).
To integrate yourself with Jira UI you need to create a webpanel or page, in both cases, Jira will ask your site to render the HTML code and the request will include JWT token. Inside you will have information about which user did the request.
Now, you can authenticate Jira users to your API in several ways:
render a time-limited token to the HTML and use it to authenticate calls to your API. As a downside of this solution, if someone will keep the page open without reloading for long enough (longer than your time limit) the token will become invalid.
provide a resource to retrieve time-limited token (validate JWT signature provided by Jira to be sure request really comes from particular Jira instance) and retrieve the token every time before doing the request (or every N minutes depending on your time limit).
or if you really want to bother admins then create a configuration page and let them save API keys by hand (I assume they will have to retrieve those keys from you somehow, this additional step may discourage many admins), in this configuration page you will include JS code that on submit will save API keys as Application property and later you will have to retrieve this before making requests to your API. With this approach however, admins will not be able to restrict access to your API to a subset of users with Jira permissions (every logged in user can access application properties, in open instances even anonymous users).
If you are unsure how to validate JWT Token you can read this developer guide. Also, you can make your life easier by using one of the provided framework and tools, for example, atlassian-connect-spring-boot will take care of installation handshake, JWT authentication and authentication to Jira REST API from your server.

IdentityServer3 organisation for multiple api

I have a DashboardApi and an EnterpriseApi on my system. May be one more later.
I am new at IdentityServer3 and I wonder solve my problem.
IdentityServer saves client applications that will use an api. So I have 2 or 3 api. Will I create IdentityServer for all api? Because DashboardApi will consume EnterpriseApi. EnterpriseApi will consume another api.
And users will login to Dashboard application. I could not imagine the organisation.
To answer the question: you may have one instance of IdentityServer being your identity provider/authority across different "resource" APIs as long as they all point back to that same authority when it comes to token validation.
Then an access token used for "DashboardApi" can be used by "EnterpriseApi". It is important to proxy the token properly and in my experience it would be advantageous to create different scopes for each API to have better access as to which calls may be used to proxy into the second API through the first (especially if user consent is a concern).

Resources