Trying to bulk dismiss all risky signons so my security team can start new.
It should be able to be done using this powershell code:
get-riskyUser -Top 5 -Filter "Riskstate eq 'AtRisk'" -Orderby RiskLastUpdatedDateTime | Invoke-DismissRiskyUser
But I get this error 5 times:
VERBOSE: Performing the operation "Invoke-DismissRiskyUser_Dismiss" on target "Call remote 'RiskyUsersDismiss' operation".
Invoke-DismissRiskyUser_Dismiss: You cannot perform the requested operation.
I did authorize the scope for connect-graph with "IdentityRiskyUser.ReadWrite.All" as well assigned a P2 license to my admin account (which I think is stupid given the feature is a P1 feature)
This cmdlet calls the following API:
https://learn.microsoft.com/en-us/graph/api/riskyusers-dismiss?view=graph-rest-beta&tabs=http
so I dug up postman, got my self a shinny new bearer token based on a freshly minted app registration with the "IdentityRiskyUser.ReadWrite.All" API via app delegation which was then admin consented to then posted to the API using this body:
{
"userIds": [
"d9460130-07f0-43a9-9faa-df8c6635f4b7",
"faff0a2a-143e-431d-bd44-99db3f4fc30d"
]
}
and got back:
{
"error": {
"code": "BadRequest",
"message": "Invalid user ids.",
"innerError": {
"request-id": "a1dcf05e-bbf2-436a-9614-2a2d5b5d0fc0",
"date": "2019-12-06T19:59:03"
}
}
}
I triple checked those IDs are valid, also tried all lower case in the attribute name.
At a loss for what to do next, anyone have any thoughts and/or where I can post to github to open a ticket against the code?
Turns out a bunch of issues here. The PowerShell code didnt work because somehow I authorized read not readwrite on my first goes at it.
But thats not the whole story, next up, both the API and PowerShell were returning user object IDs for users no longer in Azure AD. These can never be dismissed via code nor the actual Azure Portal. I have a MS Case open for this.
Related
I'm using One drive for business. The /_api/v2.0/drive/view.sharedWithMe return a folder, and I try to access this folder detail.
I tried several solutions listed here but it seems like nothing is working.
When I try to add the folder to the user's drive, I got the following error:
{
"error": {
"code": "-2147024891, System.UnauthorizedAccessException",
"message": "Access denied. You do not have permission to perform this action or access this resource."
}
}
When I try to "enumerate the content of a shared folder", I got the following one:
{
"error": {
"code": "unauthenticated",
"message": "The caller is not authenticated."
}
}
Thank you
When using shared items and OneDrive for Business, you need a different permission scope. The Files.ReadWrite scope provides access to only the content's of a user's OneDrive for Business. To access shared items, you need to request Sites.ReadWrite.All, which shows up in the Azure Portal as "Read and write items in all site collections". Once you have this scope on your app, and the user has consented to the scope, those calls should work.
I'm using Sails with Passport for authentication. I'm using passport-google-oauth(OAuth2Strategy) and passport-facebook for enabling Google Sign-in.
I'm not too well-versed with Passport, so pardon me if this is a rookie question. I've set up login via Facebook and it works just fine. With Google, I do receive an authorization code after allowing access to the app, but the I'm eventually not authenticated. I'm guessing the same code should work for both Facebook and Google since the strategies are both based on oauth2.
I'm not even sure what code to share, since I'm using the auto-generated code from sails-generate-auth, but do let me know if there's anything else I can share.
Any ideas on why this might be happening? The app is locally hosted but that's unlikely to be the problem since I am getting to the authorization stage anyway.
I faced the same problem and it was located here in in api/services/passport.js:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
The Google service was not returning a profile.username property.
Because of it, the user is not saved in the database and cannot be authenticated. Then the passport callback receives an empty user, so the function that handles errors is fired and the user is redirected to the login page.
This change allows to use the displayName property as the username:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
/** Content not generated BEGIN */
// If the username property was empty and the profile object
// contains a property "displayName", add it to the user.
if (!user.username && profile.hasOwnProperty('displayName')) {
console.log(profile); // <= Use it to check the content given by Google about the user
user.username = profile.displayName;
}
/** Content not generated END */
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
You could also use the profile.id property because profile.displayName is not necessarily unique (ie: two Google accounts can have an identical displayName). But it is also true accross different services: a Twitter account could also have the same username than a Facebook account. If both register on your application, you will have a bug. This is a problem from the code generated by sails-generate-auth and you should adapt it with the behavior that you want.
I will propose a PR if this solution works for you too.
Alright, so this ultimately turned out to be a known issue with the API.
TL;DR: Enable the Google+ API and the Contacts API as mentioned here. (The Contacts API isn't required, as #AlexisN-o pointed out in the comments. My setup worked as desired with Contacts API disabled. This obviously depends on what scope you're using.)
I believe it's not a nice way of failing since this was an API error that was prevented from bubbling up. Anyway, I dug into passport.authenticate to figure out what was going wrong. This eventually calls the authenticate method defined in the package corresponding to the strategy (oauth2 in this case). In here (passport-google-oauth/lib/passport-google-oauth/oauth2.js) I found that the accessToken was indeed being fetched from Google, so things should be working. This indicated that there was a problem with the requests being made to the token urls. So I ventured a little further into passport-oauth2/lib/strategy.js and finally managed to log this error:
{ [InternalOAuthError: failed to fetch user profile]
name: 'InternalOAuthError',
message: 'failed to fetch user profile',
oauthError:
{ statusCode: 403,
data: '{
"error": {
"errors": [{
"domain": "usageLimits",
"reason": "accessNotConfigured",
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration.",
"extendedHelp": "https://console.developers.google.com"
}],
"code": 403,
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration."
}
}'
} }
This was the end of the hunt for me and the first result for the error search led to the correct answer. Weird fix though.
In the Graph API Explorer tool I'm using this query:
search?q=myemail#gmail.com&type=user
But for whatever reasons I'm getting this returned.
{
"error": {
"message": "(#200) Must have a valid access_token to access this endpoint",
"type": "OAuthException",
"code": 200
}
}
The access token is there. And other requests work, like this one:
me?fields=id,name
Here's the return value
{
"id": "somelongnumber",
"name": "my name"
}
Not sure what I'm doing wrong, are there additional permissions that I have to setup to get search to work?
Edit: Here's the screenshot of my user permissions:
I have also tried using an application token, but same thing.
More updates:
Querying for names seem to work just fine:
search?q=FirstName LastName&type=user
returns valid results, but email returns me oath exception. Did facebook change the way they allow for email searches?
Even though it was possible, you can't search users by their e-mail addresses anymore. As the doc states, the q value must refer to the name of a user.
Available Search Types
Type: user
Description: search for a person (if they allow their name to be searched for)
q value: name
Also the dot character which is/are present in every e-mail address would also break your Graph request. In the current Graph API syntax, . marks the beginning of a subfield, for instance:
/me?fields=friends.limit(10)
^
How would the email be delimited? As you can see,
/search?q=john#gmail&type=user "works"
whereas
/search?q=john#gmail.com&type=user doesn't.
Edit: This feature has been disabled in April 2013 and Facebook reported:
This functionality was deprecated because
of low utilization, and we have no current plans to re-enable it. If
you have a valid use case for this feature please describe it here for
consideration. Marie Hagman — Facebook Team
Source: https://developers.facebook.com/x/bugs/453298034751100/
Yesterday I started a new app on Facebook. Today I got the message that when people copy the link to Twitter they get an error. This is what you get:
{
"error": {
"message": "Unknown path components: /your_namespace:your_action",
"type": "OAuthException",
"code": 2500
}
}
What does this mean? What could be the problem?
Are you actually sending the POST action link to Twitter? Why?
I think you misunderstood how Open Graph works. Basically, you should be the one publishing actions when users take an action using your service. You can use a server-side or a client-side language to POST request (when you click a link, your browser actually makes a GET request, not a POST) to https://graph.facebook.com/me/namespace:action?access_token=ACCESS_TOKEN&OBJECT_PATH=OBJECT_URL
Note that you need to create an app, use it to authenticate users to get the access token and also set your custom actions / objects. These will need to be approved before you can actually use them.
You should start by taking a look at the sample apps to see how they work: https://developers.facebook.com/docs/samples/
I'm running into a situation where requesting a list of permissions that a user has granted to a canvas application intermittently returns an empty array.
The graph request would look something like this:
https://graph.facebook.com/[uid]?access_token=[token]&fields=permissions
Typically, a normal response would look something like this:
"permissions": {
"data": [
{
"installed": 1,
"email": 1,
"bookmarked": 1,
"publish_actions": 1
}
]
}
Occasionally though the response looks like this:
"permissions": {
"data": [
]
}
The code equates this situation to the user having not granted any permissions and restarts the auth flow. The problem appears to be intermittent, because the users eventually make their way into the application and if I manually retry some of the failed requests I find in logs the permissions are returned as expected.
Looking at the User API docs (http://developers.facebook.com/docs/reference/api/user/), it looks like permissions that are not granted are excluded. It's not clear from the documentation what happens when no permissions are granted. One would assume an empty map, which would render a response something like:
"data": [
{
}
]
However, even if the response is an empty array, the point in the code where this request is made should not be reachable without accepting a least some permissions.
This leaves me with a few questions that I'm hoping someone with relevant knowledge can answer:
Are there any circumstances under which the permissions granted by the user to the application are not available via the Graph API?
Are there any circumstances under which a canvas application can be authorized by the user without granting any permissions? (cancelling the auth dialog results in a request with additional query string params, which is handled differently)
Are there any circumstances under which a user can revoke initially-granted permissions without de-authorizing the application?
Edit:
Based on the discussion below I would like to clarify that my app requires the email permission, which does not appear to be revocable. The app has always required the email permission, so there shouldn't be a case of an older install without that permission.
Nope, not to my knowledge.
That situation is called basic permissions, where no additional permissions are specified in the scope parameter during login
Yes, the app user can revoke certain permissions. Go to (http://www.facebook.com/settings?tab=applications) and click edit on one of the apps (for example Groupon or Music or YouTube) and you can see there's certain permissions that can be removed by the user at any time. So it is good your app reads the permissions it still has available to it. It might save you some wasted graph calls to objects/actions you're no longer able to get.