I'd like to subscribe to user deletions, so that whenever a user is deleted in Azure AD, our app can react accordingly.
Here's my subscription request:
const now = new Date();
const threeDaysLater = new Date(now.getTime() + 3 * 24 * 58 * 60 * 1000);
request.post({
auth: {
bearer: {...},
},
headers: {
Accept: 'application/json',
},
json: {
changeType: 'updated,deleted',
clientState: {...},
expirationDateTime: threeDaysLater.toISOString(),
notificationUrl: 'https://{...}.ngrok.io/api/azure/webhook',
resource: 'users',
latestSupportedTlsVersion: 'v1_2',
},
url: 'https://graph.microsoft.com/v1.0/subscriptions',
});
After sending this request, I receive a request to my notificationUrl, which I respond back to with the validation token.
I then receive the following response from the initial request:
{
'#odata.context':
'https://graph.microsoft.com/v1.0/$metadata#subscriptions/$entity',
id: {...},
resource: 'users',
applicationId: {...},
changeType: 'updated,deleted',
clientState: {...},
notificationUrl: 'https://{...}.ngrok.io/api/azure/webhook',
expirationDateTime: '2020-03-22T11:52:36.328Z',
creatorId: {...},
latestSupportedTlsVersion: 'v1_2'
}
However, when I actually go into Azure AD and delete users, I never receive any requests to my endpoint... Any ideas what I'm doing wrong here?
I've seen Not receiving a request on our MS Graph Webhook for deleting a User in AAD, but I've both waited 30 minutes, and tried soft + hard deletes. Neither seems to trigger any sort of request to my endpoint.
Okay, so apparently I was just not being patient enough. It can take hours for MS to send these notification requests.
If you're developing your webhook endpoint, and looking to test/debug it, do the action in Azure AD, then do something else for a few hours until you finally get the request. 🙄
Related
I started using OAuth2 server with oidc in node js. Github link
My goal is simple, to access https://myserver/me which is UserInfo endpoint.
While trying to learn how to use the server I also used this guide enter link description here
Where I found that I could create token by sending request to endpoint /token.
Into the configuration I added this code(full server code is below):
{
client_id: 'test_oauth_app',
client_secret: 'super_secret',
grant_types: ['client_credentials'],
redirect_uris: [],
response_types: [],
}
In postman I was able to get my the access_token by this request
POST /token
Headers:
Content-Type: application/x-www-form-urlencoded
Authorization: Basic dGVzdF9vYXV0aF9hcHA6c3VwZXJfc2VjcmV0
Body:
grant_type=client_credentials&scopes=api1
I get this as a response:
{
"access_token": "zdjmZo7_BQSIl4iK9IMcBbKffxGO-wQ3jLzzQXTlyws",
"expires_in": 600,
"token_type": "Bearer"
}
When I checked the token by /token/introspection I found out that the token equals to jti.
So I think it actually returns token_id and by that I cannot access /me endpoint.
Here is the whole sample of server that I use:
const { Provider } = require('oidc-provider');
const configuration = {
features: {
introspection: { enabled: true },
clientCredentials: { enabled: true },
userinfo: { enabled: true },
jwtUserinfo: { enabled: true },
},
formats: {
AccessToken: 'jwt',
},
clients: [{
client_id: 'test_oauth_app',
client_secret: 'super_secret',
grant_types: ['client_credentials'],
redirect_uris: [],
response_types: []
}],
scopes: ['api1']
};
const oidc = new Provider('http://localhost:3000', configuration);
oidc.proxy = true
// express/nodejs style application callback (req, res, next) for use with express apps, see /examples/express.js
oidc.callback
// koa application for use with koa apps, see /examples/koa.js
oidc.app
// or just expose a server standalone, see /examples/standalone.js
const server = oidc.listen(3000, () => {
console.log('oidc-provider listening on port 3000, check https://localhost:3000/.well-known/openid-configuration');
});
The proxy is set to true because I have https set up on apache redirecting to this server.
I tried to change response_types, but than it required redirect_uri which I do not want to have in my scenario.
Here is the request I am trying to post it like so:
POST /me
Headers:
Content-Type: application/json
Authorization: Bearer zdjmZo7_BQSIl4iK9IMcBbKffxGO-wQ3jLzzQXTlyws
The response:
{
"error": "invalid_token",
"error_description": "invalid token provided"
}
Did anyone have a similar problem? I found almost the same problem here
but with no solution, unfortunately.
In case someone encounters the same problem. I was able to solve it.
I did not have enough information and I did not know what client_credentials grant type does.
It actually does not authorize the user, but rather some app. So you have no info about the user, hence you cannot get data about the user through the userinfo endpoint.
So if you want to get info about the user, you probably want to use grant type authorization_code.
I found a page where a lot of things is written pretty clearly, so if you are starting with
OAuth server you might want to give this a try.
https://oauth2.thephpleague.com/authorization-server/auth-code-grant/
I want to send push notification to multiple devices at once. Can i pass array of tokens?
Is it possible to do using google api? Please help me with this.
request(
{
method: 'POST',
uri:
'https://fcm.googleapis.com/v1/projects/projectId/messages:send',
headers: {
'content-type': 'application/json',
Authorization: `Bearer ${token}`,
'apns-priority': 'high',
content_available: true
},
body: {
message: {
token: token,
notification: {
body: 'This is an FCM notification message!',
title: 'FCM Title'
},
android: {
notification: {
sound: 'default'
}
}
}
},
json: true
},
async function(error, response, body) {
if (error) {
console.log(error);
}
console.log(body);
}
);
If you want to make the POST requests by yourself, you can prefer to:
1) Use the legacy HTTP server protocol. With that you will be able to use the "registration_ids" field which expects an array of token strings in POST body. Docs here.
2) Stick to HTTP v1 API that you're using right now, but since "token" field is expecting only string, you can first subscribe your users to a specific topic and use that topic in "topic" field in POST body.
Additionally, you may prefer to use Admin SDK to send batch notifications. You can check for further here.
I've registered as the Web app as required by the Reddit API for the Oauth access with identity, edit, flair, history, modconfig, modflair, modlog, modposts, modwiki, mysubreddits, privatemessages, read, report, save, submit, subscribe, vote, wikiedit, wikiread scopes.
I'd authorized my app and have exchanged the generated code for the access_token with 3600 seconds validity.
'use strict';
let request = require('request');
const USER_AGENT = 'web:com.example.server:v0.0.1 (by /u/sridharrajs)';
const token = '<my access_token within 3600 seconds validity>';
request({
method: 'POST',
url: 'https://www.reddit.com/api/vote',
headers: {
'User-Agent': USER_AGENT,
'Authorization': `bearer ${token}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
id: "t1_9qy47p",
dir: "1"
},
json: false
}, function (error, response, body) {
if (error) {
console.log('error', error);
} else if (body.error) {
console.log('body.error', body);
}
return console.log(body);
});
But when I try to upvote a reddit submission using API, I get an error.
{"message": "Forbidden", "error": 403}
The link that I'm trying to upvote is Tim Cook warns of ‘data-industrial complex’ in call for comprehensive US privacy laws
I tried switching both bearer and Bearer as per the answer in Reddit API returns HTTP 403, and tried using different User-Agent as suggested in 403 error when trying to get data from Reddit API. Nothing seem to work.
What am I missing?
Solved. I need to use https://oauth.reddit.com instead of www.reddit.com.
You may now make API requests to reddit's servers on behalf of that user, by including the following header in your HTTP requests:
Authorization: bearer TOKEN
API requests with a bearer token should be made to https://oauth.reddit.com, NOT www.reddit.com.
bellow is my node js script to get google user details using accessToken
var accessToken = req.body.accessToken;
console.log(accessToken)
var google = require('googleapis');
//google api
var plus = google.plus('v1');
var OAuth2 = google.auth.OAuth2;
var oauth2Client = new OAuth2(
config.google.clientID,
config.google.clientSecret,
config.google.redirect_uri
);
oauth2Client.setCredentials({access_token: accessToken});
plus.people.get({
userId: 'me',
auth: oauth2Client
}, function (err, response) {
// handle err and response
if (err) {
reject(err)
} else {
console.log(response);
resolve(response)
}
});
need to get google login user details using accessToken. what is wrong in code?
The most likely cause is the user in question has not created a google+ profile. Here are a few more options.
I am not sure what information you are trying to get but the best way to get user info is to authecate a user using the profile scope then request the data directly of the user info endpoint
Request
GET /userinfo/v2/me HTTP/1.1
Host: www.googleapis.com
Content-length: 0
Authorization: Bearer uzG4XqnvucBFk3jylgxnbtNhoOt2wCc3QvUcjk7PZhJ5m6G7ibtlBwbAQntJjJtLsxZfoDjhbASpzLmcFnlZ9o4qoMd2fCV2eRb4O5XrKRAXC
Response
{
"family_name": "Lawton",
"name": "Linda Lawton",
"picture": "https://lh5.googleusercontent.com/-a1CWlFnA5xE/AAAAAAAAAAI/AAAAAAAAl1I/UcwPajZOuN4/photo.jpg",
"locale": "en",
"gender": "female",
"link": "https://plus.google.com/+LindaLawton",
"given_name": "Linda",
"id": "117200475532672775346"
}
You can also go though the google people api using the same profile scope
GET /v1/people/me HTTP/1.1
Host: people.googleapis.com
Content-length: 0
Authorization: Bearer NuzG4XqnvucBFk3jylgxnbtNhoOt2wCc3QvUcjk7PZhJ5m6G7ibtlBwbAQntJjJtLsxZfoDjhbASpzLmcFnlZ9o4qoMd2fCV2eRb4O5XrKRAXC
But this endpoint reads from Google+ so if the user has not filled anything out on their Google+ profile you wont see much data here.
You can use request module to get the user detail on your node server.
But Before requesting the user data, make sure you have authorized the API by giving it the desired scope. In your case, you need to give https://www.googleapis.com/auth/userinfo.profile in the scope.
When you receive your accessToken, use that token to call this google api
https://www.googleapis.com/oauth2/v1/userinfo
const request = require('request');
// use any api you want to call.
request({
url: 'https://www.googleapis.com/oauth2/v1/userinfo',
method: 'GET',
headers: {
'Authorization': `Bearer ${YourAccessToken}`,
'Accept': 'application/json'
}
}, function(err, response, _user) {
console.log('User Data', _user);
})
I hope this will solve your problem. If still there is some problem, you can test your Google APIs on OAuth 2.0 Playground
I try to listen on my calendar change events (google-apps/calendar/v3/reference/events/watch).
I did everything from Google console side, domains - OK, everything is verified and I succeeded to create channel. Also i succeeded to get sync message with right headers (see below). From docs:
Sync message
After creating a new notification channel to watch a resource, the
Google Calendar API sends a sync message to indicate that
notifications are starting. The X-Goog-Resource-State HTTP header
value for these messages is sync. Because of network timing issues, it
is possible to receive the sync message even before you receive the
watch method response.
That mean that notifications are starting
However when I change something in snaggs#comp.com account -
nothing happens, no request sends to callback : 'https://dev-api.mycompany/google-watch/'
This is my working code:
var google = require('googleapis');
var googleAuth = require('google-auth-library');
var _ = require('underscore-node');
var uuid = require('node-uuid');
// ......
var channel_id = uuid.v1();
_auth.credentials = {
access_token: _token.access_token,
token_type: _token.token_type,
refresh_token: _token.refresh_token,
expiry_date: _token.expiry_date
};
var data = {
auth: _auth,
calendarId: _token.provider_email,
singleEvents: true,
orderBy: 'startTime',
resource: {
id: channel_id,
token: 'email='+_token.provider_email,
address: 'https://dev-api.mycompany/google-watch/',
type: 'web_hook',
params: {
ttl: '36000'
}
}
};
calendar.events.watch(data, function (err, response) {
if (err) {
console.error('The API returned an error: ' + err);
return;
}
});
When I start above mentioned snippets of code i get response:
{
"kind": "api#channel",
"id": "277fa000-d4b6-12e5-ab58-e7afaf85ea65",
"resourceId": "C7vFL07CYfqaHy3vDss4qugWDfk",
"resourceUri": "https://www.googleapis.com/calendar/v3/calendars/snaggs#comp.com/events?orderBy=START_TIME&singleEvents=true&alt=json",
"token": "email=snaggs#comp.com",
"expiration": "1455667451000"
}
And in 'https://dev-api.mycompany/google-watch/' URL I get sync message regards to documents, like (See google-apps/calendar/v3/push):
{
"host": "dev-api.mycompany",
"accept": "*/*",
"accept-encoding": "gzip,deflate",
"user-agent": "APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)",
"x-goog-channel-expiration": "Tue, 16 Feb 2016 22:44:51 GMT",
"x-goog-channel-id": "277fa000-d4b6-12e5-ab58-e7afaf85ea65",
"x-goog-channel-token": "email=snaggs#comp.com",
"x-goog-message-number": "1",
"x-goog-resource-id": "C7vFL07CYfqaHy3vDss4qugWDfk",
"x-goog-resource-state": "sync",
"x-goog-resource-uri": "https://www.googleapis.com/calendar/v3/calendars/snaggs#comp.com/events?orderBy=START_TIME&singleEvents=true&alt=json",
"x-forwarded-for": "56.102.7.132",
"x-forwarded-port": "443",
"x-forwarded-proto": "https",
"content-length": "0",
"connection": "keep-alive"
}
but not exists message
Do I miss something?
please help,
We have been using Push Notifications for a few years and noticed that for the last 24 hours we did not receive any notifications across several thousand calendars.
Like you we can create/stop a channel but no notifications are received for changes as normal.
As of about an hour ago we are receiving them again. Please try your channel again as it may be a glitch on the Google Push side of things that has been resolved.