How can I read local MS Teams status - api

I am trying to implement a hardware busy light to show my Microsoft Teams presence so that my family to not enter the room I have the office while I am in a meeting. I am looking to implement something similar to:
https://www.eliostruyf.com/diy-building-busy-light-show-microsoft-teams-presence
https://blog.jongallant.com/2014/12/beakn-v0-1-diy-lync-status-light/ (older acticle - similar idea).
The only problem I have with this setup is that I cannot get the MS Teams status.
The best way to go is by using MS Graph Presence API but my problem is that this is a company account and I don't have (and there is no way I could have) and app in the main subscription granted with the required scope: Presence.Read.
So I tried different ideas but none worked in the end:
check local running processes
check if MS Teams exposes any local API
check if there is a CLI available
This seems a simple idea, I mean, I see the status right there now while I am typing this message, I could as well do an app that gets a screenshot of the taskbar and extract the status from the icon, but is that really the only option I have?

I think I found something interesting for you.
Go to
C:\Users\user\AppData\Roaming\Microsoft\Teams
you'll find a file called logs.txt
In this file you see if your current state changed
(current state: Available -> DoNotDisturb)
I would write a script with php or VB (depends on your skills) that read that logs.txt file like every minute and check for the last "current state" line.

What those posts are doing (certainly the first one, I didn't check the 2nd one) is calling the Microsoft Graph, which has a "presence" endpoint to get a user's status. There's actually even a specific "/me" endpoint, to get your own personal preference (less access rights needed). See more about this here: https://learn.microsoft.com/en-us/graph/api/presence-get?view=graph-rest-1.0&tabs=http
In order for this to work, as you've mentioned, you do need to have an Azure AD App registration. However, importantly, this will only require "delegated" permission (i.e. only permission from the single user, you, to access just data for that single user, you). As a result, you can use "delegated" and not "Application" permissions, which means that it does -not- require Admin consent for the tenant.
It -does- require and Azure Add Application though, at the risk of stating the obvious. While you don't have tenant admin rights, you need to see if you have Azure rights, just to create an application (you might have this anyway as a developer in your org). If you don't even have this, you can sign up for an M365 Developer account, and use that tenant. Importantly - the application does't have to be in the same tenant. If it's not, it's just a simple multi-tenant app, like any 3rd party Azure AD-backed application is.

Related

Restrict access of a connected app (Salesforce)

What is the best way to restrict the scope of a connected app to a set of objects? My current solution is to use the Manage user data via APIs scope but that still grants more access than required.
A solution I see frequently is to create a user with a restricted profile and connect with that user but then you lose context of actions made by users in the connected app so this solution doesn't work
Tricky, you typically don't. (consider posting on https://salesforce.stackexchange.com/, there might be a clever way I didn't think of).
You can flip the connected app from "all users can self authorise" to "admin-approved users are preauthorised" and then allow only certain profiles / permission sets to use the app. But the bulk of it is "just" enabling the connection via API and cutting it to say Chatter only or OpenId identifiers. And that's already an improvement compared to SOAP APIs where you don't have scopes and the app can completely impersonate the user, do everything they can do in UI.
Profiles/permission sets/sharing rules are "the" way even in not immediately obvious situations like Lighting Connect Salesforce to Salesforce or Named Credentials access to another org.
If you can't restrict the visibility with profiles and access to all tables user can see is not acceptable...
you could create series of Apex classes exposing certain queries, updates etc and grant profile access to these classes - but without full api access? You could even let them pass any SOQL (evil) but use with sharing, WITH SECURITY_ENFORCED, stripInaccessible + custom restriction on tables before returning results
you could look into https://developer.salesforce.com/docs/atlas.en-us.238.0.apexref.meta/apexref/apex_class_Auth_ConnectedAppPlugin.htm although I suspect it's run only on connect, not on every request. So at best you could deny access if user has right to see some sensitive data, not great
if there are few objects you need to block updates if done via app - Quiddity might be the way to go. Throw error in a trigger if action started from REST context?
give the Transaction Security trailhead a go. If it looks promising (there's way to check "application" and "queried entities" according to this) - might be a solution. You'll likely have to cough up $ though, last time I checked the cool bits of event monitoring & transaction security were hidden behind an extra paid addon (standalone or bundled with platform encryption and Field Audit Track into Salesforce Shield solution)
2 logins? dedicated user for querying stuff but inserts/updates running as your end user?

How to avoid script authorization prompt when G-Suite user is accessing G-Suite trusted app script?

I wrote an app script which provides a web UI for data entry into a team calendar. I published it using G-Suite super admin account and added it as Trusted App under Security/API Permissions. "Trust domain owned apps" is checked under "Internal App Settings".
When a G-Suite user in our organization tries to access the app, he sees
"The developer of ShiftSchedulingApp, admin#_our_organization_.org, needs your permission to access your data on Google."
Those brave enough to click "Review Permissions" are taken to the next message:
"ShiftSchedulingApp wants to access your Google Account. See, edit, share, and permanently delete all the calendars you can access using Google Calendar"
Of course nobody wants to risk losing all the calendars on their Google Account and this is where it ends.
How do I get rid of this misleading message? It's not Google account, it's their organization account on G-Suite. It's not all their calendars, it's the shared team calendar only. It's adding data, not permanently deleting calendars. It's published by their administrator in their G-Suite, not an unknown 3rd party.
I spent days trying to make this message go away but no luck. App must be executed as an accessing user and not as publishing user because their user ID determines what shifts they can fill on a calendar.
I'd appreciate any hints pointing me the right direction.
I experimented with variations of the two-app approach as suggested.
The app which provides the UI needs to read the calendar to display available shifts - so I can't get away from the user authorization prompt.
Another variation I tried was having one app do everything and run as me, and another do nothing but return Session.getActiveUser(). I tried calling the 2nd one from the 1st one on the client side via XMLHttpRequest. It would be ideal for my needs - but I hit CORS error as apps URL is script.google.com but it actually gets redirected to script.googleusercontent.com. There doesn't seem to be a way to set CORS in Google App Script.
Although I was not able to find a way to avoid prompting users for authorization when executing the app as accessing user, it turns out my reasons for doing that were based on a false premise.
I chose to publish app as accessing user because I thought that's the only way to get accessing user Id - which is true for non-G Suite accounts.
However, when app is published by a G Suite account, the app can get accessing user ids within the same G Suite domain even when it's set to execute as publishing user.
Thanks Niek and TheMaster for your help!
If you just need user ID, why do you ask for all those permissions?
Possible Solutions:
2 web-apps- One running as you and another as user accessing (with only profile) permission. The second one will be the actual web interface and POST necessary information to the first one with privileges. OR
Implement your own web-app Google-sign in1
Use the least permissive2 scope3

Developer access and when a token is valid

I apologise if the title is a little confusing, but I was a little stuck with the wording.
I'm currently working on a section of an application to allow users to grant developers access to their data through the application. This comes in a little 'Allow Some great app to access your account with the following permissions'. The application developer adds the required permissions, then when the user goes to authorize the application, these permissions are are displayed. If the user is happy to grant these permissions, the user shall press 'Grant'. This means that the user has agreed to every permission that has been displayed, and therefore this generates an API access token for the relevant application.
The issue now is that it has came to the attention that people may want to remove these permissions at a further date. At the moment, if the user would like to remove permissions, all permissions will be removed or disabled. The reasoning behind this is that if a single permission is removed from the application, the token that they authorized with is technically invalid as it does not have the permissions that were given to it when first creating the token.
Whilst this seems logical, there are also circumstances where the user would want to deny access for the third party application for a single feature (eg. The external application had a bug that was creating bad behaviour in a certain area, but was working fine in another area).
Would anybody be able to throw their two-cents in to this, as I'm having a hard time understanding if its best to allow modifications to a single permission in the event of problems, or to simply have to disable the application.

Single sign-on and user's file (web page content) access

I don't want to store passwords on my server and I don't want to force my end users to create yet another account, that's why I'd like to use single sign-on. I'm looking for a widely accepted solution for the authentication, I think about OpenID and OpenID Connect, the former seems to be more widespread but obsoleted and no longer used by Google, the latter seems to be faster (thanks to JSON?), safer but less widely adopted.
I'd like to share some documents on Internet. I want to control who can view them. I have looked at OwnCloud but it seems to be too much for my needs.
My website contains some photos and some articles, I want to show some of them to everybody, I want to show some of them only to my family and my best friends but not my colleagues, I want to show some of them to all logged users but not everybody and finally, I want to show some of them to … nobody.
I use Apache HTTP Server, I want to be able to manage file access rights for my end users with their own means of authentication. I have looked at mod_auth_oid and mod_auth_oid_file, it handles the authentication with OpenID 2.0, it allows to define a mapping between OpenID and local user ids. Does it mean that I still have to store a password for each local user anywhere on my server?
A graceful server restart is required in order to load new mapping definitions
It's a bit annoying as I don't want to restart the server each time I edit the mapping. It's unclear to me whether it is still true when using mod_auth_oid_ldap. I really need an open source software that I can install on my server and adapt to my needs. I plan to use openid-selector with the Apache modules I mentioned earlier and some JavaScript code to handle gracefully the display of the forbidden content. Am I missing a more obvious solution? I'm not a big fan of Facebook but is this bridge working?

Implementing ActiveDirectory account lockout after n tries in WCF

I am developing a WCF service which can be consumed by mobile applications to authenticate users against the corporate extranet ActiveDirectory. I am using a customized version of this implementation from Microsoft. I need to implement the account lock out logic so that after n retries the account in the ActiveDirectory should get locked-out.
I tried with state-full WCF service to keep track of the failed log-ins. But the client can start over the next session and continue with the attack.
I know that the ActiveDirectory policy can be set to enforce this, but just querying the AD -like the Microsoft solution does to authenticate the user - does not lock out the user.
So, I am looking forward for a solution which will work like when log-in to Windows with incorrect password for n times the account will get locked-out as per the policy set in the AD.
I have not seen your code. So I'm guessing you have similar solution that is implemented in this example, have a look at this link
In above example, please have look at line
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
this entry object would be used for authentication when you make a search call on active directory.
If you are using user/password that you want to authenticate then you need not to worry about locking it by your code. Active directory policy would be enough.
But after reading your comment I guess you have one specific user that you use to search mobile application users to check if they exist in your active directory or not. If this is the case effectively you are never authenticating against mobile users so those users never going to be blocked automatically.
I would be interested to know your answer.
There are basically two ways of doing this:
You continue the directory search method you are using, but track the number of logins for each user in a custom database, and check this database before doing the directory search.
Use the Windows login instead, and rely on AD to lockout the user. For a description of how to do this check: Active Directory (LDAP) - Check account locked out / Password expired
Edit
After seeing marc_s's comment, I am unsure if doing the directory search will lockout or not. It would actually be a serious security hole if you could try an infinate number of times. But you would need an account that is allowed to query AD before you could use it.
The code you linked to had this line
object obj = entry.NativeObject
Which was to force authentication. Have you included this line?