Grant Access to a Shared Mailbox From an Application - javascript

Within Office 365 its apparently not possible to assign a security group to a shared mailbox. This means that all users need to manually be added to the shared mailbox, which is a pain.
However, Microsoft Graph appears to offer a way to subscribe to changes to a given group. As a result my thought was to build a simple azure function application that receives a web-hook from Microsoft Graph when someone is added / deleted from a specific group, and promptly adds / removes the user from the list of shared mailboxes.
The problem I'm having is that Microsoft Graph does not appear to have an API call for granting a user access to a shared mailbox; and I haven't been able to find another Microsoft API that will allow it.
The only way I've discovered that can even do this programmaticly is with PowerShell, which requires that I create a user to authenticate rather than granting application access. PowerShell also only has experimental support for Azure Functions right now, and I'm not even sure if Azure Functions supports Exchange Online PowerShell calls or how to install it if needed.
Does anyone know a way to do this with REST calls or JavaScript specifically, or better yet to do it with Microsoft Flow without writing code?
If I don't get any answers on the preferred method soon, I will except a solution on how to do this with an Azure Function or Microsoft Flow and PowerShell.

Instead of an Azure function, you could use Azure automation to create an Azure Runbook that will execute your PowerShell code.
The Runbooks allows you to import modules giving you all the functionality you need to do the Exchange Online PowerShell. It also allows you to store credentials of an Account with the correct level of permissions. (While testing you can use an Exchange Service admin account or a Global admin).
So you could create an Azure AD user, use Exchange RBAC rights to scope it down to only have permissions to what it needs to do for security reasons, then store the creds of that user in the Runbooks credential functionality.
The Runbook can then be executed from a webhook.
A small note, you cannot add a security group, but you can add a mail enabled security group and give it rights. The group can be hidden from the global address list in Exchange and just use some bogus mail address on the .onmicrosoft.com domain of the tenant.
Only thing to note, this method of using groups for permissions does give the user the correct access rights, but, the mailbox will not automatically be added to Outlook.
The reason for this is that Exchange adds an Automapping flag to the object you give access rights on the mailbox. But setting this flag on a group does not recurse and also add the flags on users, so users would need to manually go into Outlook and tell it to open the mailbox.
How to manually test in Office 365
Confirmed to work 03/12/2018
Adding a new mail enabled security group in Office 365.
Creating a new shared mailbox in Office 365.
Adding a user to the mail enabled security group.
Open the OWA logged in with the user you added to the mail enabled security group
Select "Open another Mailbox" and selected my shared mailbox.
This is the easiest way to test if the permissions have carried over. But do mind that in Outlook for desktop, the user manually will need to add the mailbox in the settings page, since the auotmapping flag does not carry over.
Also take note of Exchange Online replication time. At its worst it may take up to 30 minutes for everything to propagate properly, but it usually works within 5 minutes.

Related

Is there a better way to access my Gmail account through nodemailer?

I have been accessing my gmail account through nodemailer for quiet a while now but there two issues with that:
If 'allow less secure apps' feature isnt used for a particular time it automatically gets disbled and emails are no longer sent and i have to enable it again everytime this happens.
Google says on their page that 'allow less secure apps' feature will be unavailable after May 30, 2022.
I want my website to use my gmail account to send emails to the customers. Is there a way i can get my node app registered with google or something so it is not marked as insecure.

Firebase allows creation of users via the JS SDK without being authenticated

I found out that it is possible to create a new user in Firebase using the JS SDK without any user being logged in using the method createUserWithEmailAndPassword. For consumer apps i can image this is a great feature so that a "new customer" can create an account.
However, for the b2b world this ain't such a great feature and in my case we actually wan't to disable this.
Is there any configuration possible in Firebase or GCP that disallows any random person in the world to create an account in my environment?
Thanks!
If you want to disallow the creation of new accounts entirely, then you probably don't want the normal Firebase Auth standard email/password auth at all (which does not have the ability to disable new accounts created by an end user). You probably want to use custom authentication, and control precisely how signups occur with your own backend. You can control everything that happens on your own backend, of course. The downside is that you have to control everything on your backend!
You can't disable account creation but you can make your system only work with account you created with custom claims. You can make a cloud function to add a specific claim to your accounts, then delete that function. Now, with security rules like
allow read, write: if request.auth.token.yourClaim == true;
effectively, any account created without the claim can't do anything in your system. I think this is easier than implementing your own authentication scheme

How to hide Firebase credentials in chrome extension?

I am working on a chrome extension, and using Cloud Firestore. As mentioned in Google's documentation, I have to put the code in the JavaScript file itself, which is easily visible to anyone who can extract the source code. For security purposes, we can allow access to database only through certain domain names or certain apps. But in the case of Google Chrome extension, it is neither being hosted with a domain name nor it can be registered as an app. So, how do I not let anyone mess around with it ?
And my second question is that I have some if statements inside the chrome extension code which relates credentials from Cloud Firestore and shows result according to it. Like this -
if(userrefdoc.getCoins < 1){
console.log("Not enough coins. Buy some more");
}
So, if someone can extract and modify my code, he can easily change the if statements according to his need and gets access to the features, which he is not allowed to use. So, how do I deal with this scenario too ?
It's impossible to hide secrets in code JavaScript code that you ship to customers to run in their browser or device (same for Android, iOS apps). You should assume that a determined hacker will be able to reverse engineer all the shipped code.
The Firebase init parameters are not "credentials". They are just settings that identify your project. There are no secrets in them.
The way to secure your data in Firebase is to use Firebase Authentication along with Firestore security rules. If you can't use Firebase Auth or security rules to to control access to your database to individual users authorized to do so, but you need public client code to read and write it, you should assume that anyone with the name of your project will be able to read and write it.
The only workaround for this involve you setting up your own backend, routing all access through it, and performing your own checks to see if the client should be able to do.

Office365 IMAP Access: User is Authenticated but not Connected

I'm building my own IMAP client using node-imap, and I'm testing it against accounts on office365.
Since it's under development, I tend to hammer on the IMAP server more that I would in production, but not necessarily what I would consider to be too much.
Occasionally, I start getting the IMAP response "BAD User is authenticated but not connected". This comes after the first command after a successful login.
This is not related to password changes as other similar articles indicate, as my passwords are not changing during this time.
When this happens, the account seems to get locked up for a period of time. I seem to be able to jiggle it free by disabling then re-enabling IMAP on the account via the office365 admin panel.
So it looks like there's a circuit breaker of some sort in the IMAP interface on office365. Microsoft documents a limit of 20 concurrent sessions. In my case I am only opening one session at a time, but I am then closing it and re-opening it again soon after (debugging), so if I am running afoul of a limitation, it's not documented anywhere i have read.
Microsoft support has been helpful but unable to help me root cause this.
In order to take this app to production, I need to know what causes this to happen.
Has anyone else had a similar experience with office365?
You may want to take a look at the Outlook REST APIs rather than IMAP. The REST APIs are the recommended development API for Office 365 and are much better suited for app development with features like webhook based notifications, and are constantly evolving with the new features and functionality in the service. They also don't have the session oriented nature that IMAP has that results in the kinds of problems you are hitting.
There is a NodeJS quickstart guide to O365 here: https://dev.outlook.com/RestGettingStarted/Tutorial/node
you need to perform 2 operations on exchange online using powershell
You need to create the service principal
New-ServicePrincipal -AppId {clientid} -ServiceId {enterprise application objectid} -Organization {tenantid}
you need to grant your service principal access to the mailbox,
If the principal does not have the access, you get "user not connected"
Add-MailboxPermission -Identity {email} -User -ServiceId {enterprise application objectid} -AccessRights FullAccess
See "Register service principals in Exchange" at
https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth
If you have already verified that your password is correct (by logging into your mailbox from the web) then the issue might be Exchange server keeping a list of all your active login sessions.
Try signing out from all other locations by clicking "sign out everywhere" on the account security page https://mysignins.microsoft.com/security-info and then retry signing in again.
Office365 will accept connections and successfully authenticate even when the user doesn't have permissions to access the server by IMAP, and this is the exact error it gives in that situation.
To resolve it, go into the Office365 panel, open the user, and ensure that the IMAP permission is checked.

how to make sure only my own website (clientside code) can talk to Firebase backend?

I've read about Firebase and it looks awesome for what I want to do.
I've read about authentication and how based on rules certain logged-in users are authorized to do different stuff. Al good.
However, I'm unsure about another type of security: how do I make sure that only my own site (using client-side javascript) can talk to my firebase-backend? I'm asking because afaik there's no way to prevent anyone from looking up my firebase endpoint from the client-side code (url pointing to my specific firebase backend) and start using that for god knows what.
This is especially worrisome in situations in which I want to open up writes to the anonymous user role. (e.g: some analytics perhaps)
Any help in clearing my mind on this much appreciated.
Update (May 2021): Thanks to the new feature called Firebase App Check, it is now actually possible to limit calls to your backend service to only those requests coming from iOS, Android and Web apps that are registered in your Firebase project.
You'll typically want to combine this with the user authentication based security that Kato describes below, so that you have another shield against abusive users that do use your app.
In my opinion, this isn't so much a question about Firebase's security as a general discussion of the internet architecture as it stands today. Since the web is an open platform, you can't prevent anyone from visiting a URL (including to your Firebase) any more than you can prevent someone from driving past your house in the real world. If you could, a visitor could still lie about the site of origin and there is no way to stop this either.
Secure your data with authentication. Use the Authorized Domains in Forge to prevent CSRF. Put security rules in place to prevent users from doing things they should not. Most data writes you would use a server to prevent can be accomplished with security rules alone.
This is actually one of the finer qualities of Firebase and API services in general. The client is completely isolated and thus easily replaced or extended. As long as you can prove you're allowed in, and follow the rules, where you call in from is unimportant.
Regarding anonymous access, if you could make them visit only from your site, that still won't stop malicious writes (I can open my JavaScript debugger and write as many times as I want while sitting on your site). Instead, place tight security rules on the format, content, and length of data writable by anonymous users, or save yourself some time and find an existing service to handle your analytics for you, like the ubiquitous Google Analytics.
You can, of course, use a server as an intermediary as you would with any data store. This is useful for some advanced kinds of logic that can't be enforced by security rules or trusted to an authenticated user (like advanced game mechanics). But even if you hide Firebase (or any database or service) behind a server to prevent access, the server will still have an API and still face all the same challenges of identifying clients' origins, as long as it's on the web.
Another alternative to anonymous access is to use custom login, which would allow a server to create its own Firebase access tokens (a user wouldn't necessarily have to authenticate for this; the signing of the tokens is completely up to you). This is advantageous because, if the anonymous user misbehaves, the access token can then be revoked (by storing a value in Firebase which is used by the security rules to enforce access).
UPDATE
Firebase now has anonymous authentication built into simple login, no need to use custom login for common use cases here.

Categories