Office365 Exchange REST API errors, endpoints and permissions issues - outlook

I am trying to understand the API's that #Microsoft provides. Its just so messy. My goal is to use the Exchange API to edit settings.
So, I have an APP, Access tokens and subscriptions.
When trying to login to https://outlook.office365.com/ I get the following error:
Your subscription is no longer active. Please contact your admin to activate your subscription.
X-ClientId: 05A0A74F610C432EA1AD48C77829580B
request-id 3088673c-f523-4e26-824f-1d0f7cb0a219
X-OWA-Error Microsoft.Exchange.Data.Storage.TenantAccessBlockedException
X-OWA-Version 15.20.2451.30
X-FEServer HE1PR05CA0360
X-BEServer HE1P190MB0508
Date:18/11/2019 09:11:34
But as you can see, I have a subscription:
What I understand is that I have to login to outlook.office365.com before using the API.
Update
Ok, so I can now login to https://outlook.office365.com/mail/inbox. It took a while............. But;
1) I can request: https://outlook.office365.com/api/beta/users/********************************/. It will return the specified user.
2) I can NOT https://outlook.office365.com/api/beta/users/********************************/mailfolders. I tells me 'access denied'. While my app has all Exchange, Office365 permissions. But delegate and application permissions.

The "Grant admin consent for your tenant" feature seems to have been updated yesterday.
However, something is wrong with the new "Grant admin consent for your tenant" feature based on my test.
If you use it to grant admin consent, it will probably not take effect on the back end although admin consent has been successfully completed on Azure Portal.
Currently you could grant admin consent through a URL request.
https://login.microsoftonline.com/{your tenant}/oauth2/authorize?client_id={app id of your Azure AD app}&response_type=code&redirect_uri={redirect uri of your Azure AD app}&nonce=1234&resource=https://outlook.office365.com/&prompt=admin_consent
Please note that you need to create a new Azure AD App currently because if you have used admin consent on Azure Portal, granting admin consent through a URL request will not take effect.

Related

How user can install app from the team app store without admin approval

How user can add the app in MS Teams, without Admin approval?
So, my question is what policy needs to be added or removed to get rid of the below message:
I am the admin of the tenant and I want my users to install this app if they wish to do so.
If you're a global admin, you can review, and grant consent to apps that request permissions on behalf of all users in your organization.
To grant org-wide consent to an app, follow the steps which mentioned in following document:
https://learn.microsoft.com/en-us/microsoftteams/app-permissions-admin-center#grant-org-wide-admin-consent-to-an-app

Sending automated emails using Gmail API with Java and Oauth authentication

I have a web app which sends emails (gmail) in name of my users
When a user registers, she supplies gmail account and password. Also she has to enable access for Less Secure Apps (I recommend to create a new account for this)
Then I can open a gmail session
session = Session.getInstance(props, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user.getEmail(), user.getPassword());
}
});
and send emails on her behalf.
Unfortunately this is going to stop working next 30th May, when Google will allow only OAUTH2 access
I have followed Java Quickstart for Gmail API and I have code up and running for sending emails with OAUTH2: enable gmail api, create an application on google cloud platform, grant send permission, oauth2 client id credential created...
The problem I have is I can't see a way to automatize this task because when creating an authorized credential, a consent screen displays on browser and you have to select the account to be granted manually (maybe because my app in google cloud platform is still pending to be reviewed)
Is there a way to infer the gmail account you want to access from the credentials file (client_secret.json)? Is there a way to automatize this?
No, or yes. It depends.
The whole point of OAuth2 is to improve security by working with authorization tokens rather than asking for user credentials. To do this the user has to consent to the app's access request, and thus the OAuth consent screen cannot be bypassed. This is
explained in Google's documentation. It's not related to your app's review status but rather it's the way OAuth works.
You can still work in a similar way, though . Instead of asking for username and password upon the user's registration you can redirect them to the OAuth consent screen so they can authorize your app. Make sure that your app is requesting offline access type and then you can retrieve an access_token and a refresh_token. These will essentially work as your credentials and you can use the refresh token to generate new access tokens when needed without having the user go through the consent screen each time.
The refresh token doesn't have a "natural" expiration so you can keep using it indefinitely, but there are a few scenarios where it will become invalid, such as it not being used for six months, the user changing passwords (if using Gmail scopes), the user manually revoking access, etc. In these cases you will need to direct them to the consent screen again to reauthorize your app.
In this sense, your app can still work automatically without user input except the initial setup, which you already had to deal with when they supplied you with their credentials. The refresh token expiration can even be compared to what you had to do when the users changed their passwords in your current workflow.
One exception to this are service accounts. If you and your users are part of a Google Workspace domain you can delegate domain-wide access to it, then the service account will be able to access user data without any manual input. Of course, this is because as the domain administrator you pretty much own all the accounts under it. But if you're working with a publicly available application you will have to deal with the limitations I mentioned above.
Sources:
Google's auth overview
Using OAuth 2.0 to access Google APIs
OAuth 2.0 for web applications
The OAuth consent screen

In the bot framework OAuth Flow with Teams, what is the correct way to consent to changed permissions?

I've implemented the OAuth flow in a Teams bot similar to the sample, and I'm able to get a user token and make calls against the graph, but I'm running into an issue with changing permissions. Here's what I did:
Created a bot and gave it mail.read
Add the bot for a user and trigger the OAuth dialog. User is prompted for consent, and signed in.
Successfully read mail
In AAD, added the Mail.ReadWrite and Mail.Send permissions to the app
Next time the OAuthPrompt was triggered, token was returned immediately. No prompt for consent.
Got an access denied exception when trying to write or send mail
So the issue is that changing permissions on the app does not automatically trigger the consent flow again in the OAuthPrompt. I also tried these troubleshooting steps:
I manually signed the user out (botAdapter.SignOutUserAsync) and signed back in, but was not prompted for consent again.
Same as above, but signed out of Teams as well. Launched the web client in a new incognito window, and still no prompt for consent.
Uninstalled and re-installed the bot on the user's account. No change.
Tried the above after waiting a few hours, but still no change.
The only way I found to trigger the consent flow again was to have the user go to https://account.activedirectory.windowsazure.com/r#/applications and delete the consent from there. Even then I had to call botAdapter.SignOutUserAsync (since the bot service still returned a token with the old permissions). Once I did that, and triggered the OAuth prompt again, I was able to get the consent flow with the new permissions to trigger.
So my question is, is there a better way to handle this? If a new version of the bot requires new permissions, shouldn't the OAuthPrompt from Microsoft.Bot.Builder.Dialogs and the bot service handle re-prompting for consent?
Short answer
Bot Framework's auth provider for AAD v1 isn't flexible enough to support adding scopes.
You can switch to the AAD v2 provider and specify your new scopes in the OAuth Connection Settings. Then, if you force the user to sign in again (after SignOutUserAsync), you will get a consent screen including the new scopes. To set up the AAD v2 provider, see the Bot Framework docs on adding authentication to a bot, which has steps for both the AAD v1 and AAD v2 providers.
Long answer
The key to this behavior is how the AAD v1 and AAD v2 endpoints handle permissions and consent differently.
The problem with v1
In v1, the permissions (such as Mail.Send) are pre-registered in the AAD app registration. During sign-in, AAD checks if the user has already consented to any scopes for the app.
If yes, AAD skips the consent screen and eventually provides an access token for the scopes that had already been consented.
If no, AAD shows the consent screen for all registered scopes and eventually provides an access token for all of those scopes.
This explains the behavior you're seeing. After you tell Bot Framework to forget the current access token (via SignOutUserAsync) and force the user to login again, AAD sees that the user has consented previously, so it skips the consent screen and gives you a new token with the old scopes.
Then how do you add permissions for users who have already consented, without forcing the user to delete consent for the app? AAD's login endpoint has an optional prompt parameter that you can set to prompt=consent. This will force AAD to show the consent screen as if the user had not previously consented, and it will contain all registered permissions. So if you try to use an access token and get a 403 Forbidden error (or an equivalent exception), you can take the user through the login flow using prompt=consent.
Unfortunately, with Azure Bot Service's AAD v1 provider, you don't have enough control over the login URL to dynamically set the prompt parameter, so there isn't an easy way to achieve this.
Enter v2
But there's hope! The AAD v2 endpoints have a much more flexible way of adding scopes incrementally. In v2, for delegated permissions, the permissions do not have to be pre-registered in the AAD app registration. Instead, you specify the scopes in the scope parameter of the login URL. During sign-in, AAD checks if the user has consented to the scopes you specified in the URL.
If yes, AAD skips the consent screen and eventually provides an access token for the scopes you specified.
If no, AAD shows the consent screen for all the scopes you specified and eventually provides an access token for all of those scopes.
Either way, you end up with an access token containing all the scopes you specified in the URL.
Bot Framework sets the scope parameter using the scopes you specify in the OAuth Connection Settings. So if you add a new scope there, then the next time the user signs in, they will get a consent screen with the new permissions, and you will get an access token with the new scopes. (Note: To re-trigger the sign-in, you will still have to sign the user out using SignOutUserAsync. Otherwise, Bot Framework will continue giving you the access token it already has, instead of performing a new sign-in flow with AAD.)

send emails from MY gmail account with OAuth2 and nodemailer

I want to send emails from my gmail address through my own server. I'm using nodemailer and using account credentials is flaky, and often times doesn't work and leads to this thread
I've implemented everything on that thread many times, and still it's flaky, and also I know OAuth2 is the way to go.
I have a project with cliendID and clientSecret in google developer console, as you can see:
But how do I get an access token WITHOUT any browser interaction?
I seem to be missing something trivial here ...
I've went through all google tutorials and docs I could find about OAuth2, tokens, and APIs, but all guides go through the browser in one point.
Go to the OAuth Playground, click the cog on the top right, check the Use your own OAuth credentials and insert your clientID and clientSecret.
Then select the Gmail API v1 scopes you want in the list to the left and follow the outlined steps and you will get an access_token and a refresh_token.
Google Oauth2 actually all Oauth2 implementations I am aware of require that a user grant an application access via a web browser.
There is an alternative type called service accounts this is more like oauth1 service accounts are preauthorized. You can grant a service account access to your google drive by sharing folders and files with the service account like you would any other user. Because they are preauthorized there is no browser window pop up with service accounts.
You can only user service accounts with Gmail if you have a Google domains account Gsuite. The admin can go in and grant the service account access to the Gmail account in question. Perform G Suite Domain-Wide Delegation of Authority
If this is a normal user Gmail account you cant use a service account. You will have to use Oauth2 popup the request and save the refresh token so that you can gain access at a later date.

Unauthorised access to Email Settings Google API

I am using both GAM and the Google API PHP client library to integrate with Google for Work.
I am using a service account and I have authorized the Client ID in the Admin console to access the following two scopes:
https://www.googleapis.com/auth/drive
https://apps-apis.google.com/a/feeds/emailsettings/2.0/
I have also enabled the Drive API and Admin SDK in the Developers Console. There is no Email Settings API that I can see.
I have followed this page and granted GAM access to all scopes during testing - which does include the Email Settings scope.
I can successfully use GAM and the PHP client library to access the Google Drive API. However, I always get a 403 - Unauthorised when trying to do any of the Email Settings API functions detailed in https://developers.google.com/admin-sdk/email-settings/
I am fairly confident that I have the authorised the right Client ID in the Admin Console. When I remove the scope https://www.googleapis.com/auth/drive from the Admin Console it blocks my access to Google Drive from both GAM and the PHP client library.
Any suggestions on what to try?
GAM does not use service accounts for email settings API, it uses standard OAuth 2.0 for installed apps. Be sure you used a super administrator to authorize GAM access to the email settings API. If you didn't, run
gam oauth revoke
And then another command like:
gam all users show imap
And this time make sure you are logged in as a super admin.
Jay's post led me to the answer - namely that I should be logged in as a super admin when accessing the Email Settings API.
I therefore created a super admin account and authenticated GAM using that. That gave GAM access.
In order to get the PHP client library working, I had to impersonate the super admin account when I created the OAuth2 token. The code to impersonate the admin account is below:
$credentials = new Google_Auth_AssertionCredentials(
$service_account_email,
$scopes,
$private_key,
'notasecret', // Default P12 password
'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type
$admin_email
);
where
$service_account_email is the email address of the service account created in the Developer's console - not the super admin account.
$scopes is an array of the API URLs that you need to access
$private_key is the contents of the P12 certificate created from the Developer's console.
$admin_email is the email of the super admin account.
Hope this helps someone else.

Resources