Daemon application gets an App-only access token with no Roles - microsoft-graph-api

I have a JavaScript app that requires a user to login and hit a button then it runs a report, posts data to Excel, and sends an email. I want to automate this so a user does not have to log in and push a button.
I started with this project code: https://github.com/microsoftgraph/nodejs-apponlytoken-rest-sample
I followed the instructions and am able to get an access token but then my api call fails with 401 unauthorized. As a test, I am trying to send an email as myself and I have the Application type Mail.Send permission granted by the company admin.
I have spent many hours reading docs and blogs but have not found a solution. This document summarizes best what I am troubleshooting: https://blogs.technet.microsoft.com/sharepointdevelopersupport/2018/03/15/troubleshooting-assistance-with-microsoft-graph-api-development/.
The token I get back does not have any Roles in it as seen when I decode it with JWT. This is the only discrepancy I have found so far.
Any advise would be greatly appreciated. How can I ensure that my token has Roles defined or what else can I try? How is it that I can get a token successfully but can't use it for anything?
Thank you!

I am not a Node expert, so helping you out with a few pointers that might help.
Microsoft Graph has two types of permissions, Delegated and Application. So some things to know of and check..
Delegated permissions require a user to be present, they would show up in the scp claim in the access token. These are obtained by web applications using the implicit_grant flow, Authorization code grant or on-behalf-of flow (usually).
Application Permissions, require an admin to consent and will be provided to you in the roles claim in the access token. This requires, the app to obtain an access token via the client credentials grant. Note that, these are also present when the user is assigned a role as explained in this sample, but this scenario might not be applicable for in your case.
Does you app has the grant provided as you expect? You can check these via the Graph Explorer using the following two rest calls. There would be a OAuth2PermissionGrant entry with the expected role in it.
https://graph.microsoft.com/beta/OAuth2PermissionGrants
https://graph.microsoft.com/beta/kalyankrishna.net/OAuth2PermissionGrants
It'd help more if you can explain the flow that you have been using to obtain the access token. For example, the implicit_grant_flow does not work with application permissions.

In my case, the problem had to do with the endpoint and my tenant. I had been using the common tenant make api calls for tokens because that is what was listed in AzureAD for my app. I found that for the Application client permissions I must use my specific tenant id like 'https://login.microsoftonline.com/tenant_id/oauth2/token' when getting tokens with the proper roles.

Related

How to authorize logged in users using Google Auth JWT? (Picture)

I currently have a backend running on AWS Lambda and I'm using DynamoDB as a database. In Dynamo, there is a list of users and each user has specific permissions as to what routes they have access to through the API. There is no issue here.
I have not built the front end yet, but I will be logging in users using Google Auth, more specifically with the react-google-login component.
My question is: Once a user is logged in to the site, should I trust the JWT from Google (after verifying its legitimacy
here with the Google API) which returns the user information (Name, Email), lookup the user item inside of Dynamo to retrieve their permissions, and then serve their request?
This seems like the logical thing to do but I was looking for some confirmation. My one worry is that someone could use a supervisors name & email to authorize a request but if the lambda must accept a JWT created by Google as entry, I believe this problem is solved correct?
I have API Keys as well for every user for some external functionality, but I have that covered since it's just a Dynamo call away. My only concern is with the front end requests to Lambda since I do not want to roll my own auth/jwt.
Here is what I was envisioning.
Thank you!
Normally you should use access tokens for that purpose. The ID token should be meant only to authenticate the user, and the access token should be used to authorize access.
The best scenario would be to have a separate Authorization Server which could issue access tokens, and there are some open source solutions out there which you can use.
If you really don't want to setup your own AS then you could follow the scenario you outlined - the part with verifying JWT from Google and checking permissions in the DynamoDB is what the Authorization Server would normally do to issue an access token.
Just remember to thoroughly validate the incoming JWT - not only the signature with Google, but also check if that is a token created for your client / audience, etc. Otherwise someone could take a Google ID token JWT from their client and gain access to your API. This article lists best security practices when working with JWTs.
Also remember that ID tokens might have short expiration times and there are no means of automatically refreshing them (like you can do it with a refresh token in case of an access token), so you might end up having to reauthenticate quite often.

OAuth 2.0 Implicit Grant flow - Read calendar API returns 403

Can anyone help me to figure out solution for the below problem?
Summary:
I am getting 403 for Microsoft Graph Calendar Read API.
Detail
I am using microsoft identity platform with implicit grant flow mechanism to log user from his microsoft account into my application.
I am requesting in scope parameter with these permissions "profile User.Read Calendars.Read Calendars.ReadWrite"
Below things works after successful login.
1) It asks for the permission to grant
2) Microsoft oauth2.0 login.
3) Profile picuture read.
But for some reason when i try to read "calendar" I get 403 for only one account in whole tenant. I have gone through below link for error description, but couldn't find out solution
https://learn.microsoft.com/en-us/graph/errors
can anyone point me, where i need find solution for the above issue? Is it account issue or do I need to modify api request. Below api i am using to read calendar
https://graph.microsoft.com/v1.0/me/calendar/calendarView?startDateTime=${sd}&endDateTime=${ed}
For this problem, first you need to check if the token you got contains the correct permission, you can decode your token in this page. I test request this graph api with implicit grant flow, it works fine and I put my access token to decode we can see it contains the two calendar permissions which we expect.
Here I list some points which you need to pay attention to when you request this graph api:
1. As you mentioned in your question, you request in scope parameter with "Calendars.Read Calendars.ReadWrite" permissions, so did you add these two permissions to your AD application ? If you didn't add them, please add them in your AD application (please add them in "Delegated permissions" but not "Application permissions", I test it if we add them in "Application permissions" it will show 403 error because implicit flow requires "Delegated permissions").
2. After add the two permissions, don't forget grant admin consent for them.

Microsoft Graph API with Azure User Provisioning

What I want to do is quite simple: provision Office 365 and Azure Account from my Web App. And I want it to be available not only for me but for all the IT Departments (from other organizations too) that logs in my App.
From my understanding the steps I have to take are:
Register App on apps.dev.microsoft.com and get ID And Secret.
Enable the Scopes I'm interested in (in my case Directory.ReadWrite.All and User.ReadWrite.All) -- Enabled from both Delegated Permissions and Application Permissions
Gone through the LOGIN PROCESS
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=[My Client]&response_type=code&redirect_uri=[My Account]/Account/Office&response_mode=query&scope=openid%20User.Read%20offline_access%20Directory.ReadWrite.All
Confirm the code I receive back on my Return URL
POST https://login.microsoftonline.com/common/oauth2/v2.0/token?...secret and so on...
Now what I get is an object with Access Token, Renew Token and so on and so forth.
If I use it to get users, it's all working:
https://graph.microsoft.com/v1.0/users
But when I try to perform other operations the token seems invalid.
For instance:
Get Azure subscriptions (the account is admin of several subscription):
https://management.core.windows.net/subscriptions ==> UNAUTHORIZED
What I'm doing wrong? Is the IDEA behind it correct?
I really need to be done at a "global" level without config manual steps on every subscription or putting in some "TenantID" manually.
You've requested a token with scoped for the Microsoft Graph API which is why you can use API endpoints surfaced by https://graph.microsoft.com/.
The call to https://management.core.windows.net/subscriptions is not part of Microsoft Graph API so you're token isn't valid for that resource. That call is into the Service Management REST API. Authenticating for this API is documented here.

Does Google OAuth2.0 support an OAuth-flow for a Resource Owner Password Credential Flow?

Hello kind people of the internet.
Does Google OAuth2.0 support an OAuth-flow for a Resource Owner Password Credential Flow?
...and if so, then:
A.) can this type of OAuth flow be tested on the Google OAuth2 Playground?
B.) are there any examples of the "Resource Owner Password Credential Flow" with Google OAuth2.0 and the Google APIs?
Per an OAuth presentation recently in Oslo NDC 2013, this subject flow apparently skips the authorization end point all together and directly talks to the token end point of the OAuth2 server. The request syntax incantation would supposedly look something like this:
grant_type=password&
scope=resource&
user_name=owner&
password=password&
My understanding is the Resource Owner Password Credential Flow is for trusted applications in a back-end enterprise type of situations (where a name-password pair could be securely stored).
This particular OAuth flow would require no end-user consent interaction (no pop-up of a browser to Accept, then get a returned authorization-code, etc). In this subject flow the access & refresh token are directly returned, again: with no end-user interaction (albeit after an entry of a username-password).
Looking through the Google OAuth documentation ( link to Google OAuth2 docs ) there does not seem to be any mention of anything resembling Resource Password Credential Flow, but not sure that necessarily means it is explicitly not supported by Google.
Any help or advice would be much appreciated.
thanks in advance
Dear kind internet person,
it is true that Resource Owner Password Credential Flow is not supported on Google but google suggests you use the Installed Application Flow, which is described in: https://developers.google.com/accounts/docs/OAuth2InstalledApp.
You would need to create an Installed Application in the Google Console (https://code.google.com/apis/console), when you do that you can fetch the client_id and build a GET request with the parameters, which would look like so:
https://accounts.google.com/o/oauth2/auth\?
scope\=<scope>\&
redirect_uri\=urn:ietf:wg:oauth:2.0:oob\&
response_type\=code\&
client_id\=<client_id fetched from google console>
You would construct this URL and navigate to it on your browser, allow access for the app and google would give you what I believe is a code which you can use to get credentials. You can use those credentials to get an access token and refresh it, and this credentials is permanent. There's a good example of that on github. Note that you only need to get those credentials manually once, and then you save those credentials somewhere and keep using them to get/refresh tokens.
Hope this helps!
As far as I know, No. The OAuth 2.0 stuff is for Google accounts, for which Google does authentication.

Google API : How to authenticate without redirection?

We want to use Google Doc API to generate Document (In our own business account) when our end users do some actions on our site.
The problem is that we've tried to implement the OAuth 2.0 protocol, as suggested in the v3.0 protocol documentation. The apiClient::authentication method do a redirection. This is a major problem because our users doesn't know the access to our own business account.... and we don't want to give them access anyway ;)
(In other word, we're not creating an application that allow our users to edit their own data, but to interact with our data, like a database.)
I've read that the point of OAuth 2.0 was to avoid that we manage the credential of our users. I'm personally O.K. with the concept, but in our case, we don't want to get authenticated in the google account of our users ...
So, what would be the best approach to get a valid authentication without any interaction from the end user ?
What you describe is not how 3-legged OAuth was designed to be used.
3-legged OAuth is all about delegated authentication where a user (who knows his password) can grant limited and revokable resource access to application. That application never sees the user's password. There is a bunch of work involved to safely allow the application to impersonate the user.
What you probably want is to use the (2-legged) OAuth flow, where the consumer_id/consumer_secret credentials are embedded in your application. Here your application is not impersonating your end user and there would be no browser redirection involved.
Here's some further info on using 2-legged OAuth in Google Apps:
http://googleappsdeveloper.blogspot.com/2011/07/using-2-legged-oauth-with-google-tasks.html
And this is a good description of 3- vs 2- legged OAuth:
http://cakebaker.42dh.com/2011/01/10/2-legged-vs-3-legged-oauth/
You will need to use a SERVICE ACCOUNT. Basically you are hard coding access to this account into your server application. Then you use sharing to give access to the to account for the content you want. For example you can share a Google Doc or an Analytics profile with the SERVICE ACCOUNT.
Here is a complete example implementation of setting up a service account, logging and and then using it.
Updated 2018-12-12: https://gist.github.com/fulldecent/6728257
Why not get one OAuth authorization for your business account and have all users use that account. Since it sounds like you want everyone accessing the data for one account, the details can be hid from the end user.
The access token would be shared by all users and they would all hit the same account back end without any authorization for each user's own account.

Resources