EMQX http ACL auth - broker isn't available - mqtt

I use EMQ X Broker v4.0.1. Simple http auth is work fine, but when I try to use http ACL auth - it doesn't work for me, despite the fact that settings are very close. When I try to refer to the broker via Eclipse Paho I get the error with status code 3 that means the broker isn't available. I turned on emqx_auth_http from dashboard. This is my EMQX settings for http ACL auth:
emqx.conf
listener.tcp.external = 1884
plugins/emqx_auth_http.conf
auth.http.auth_req = http://127.0.0.1:8991/mqtt/auth
auth.http.auth_req.method = post
auth.http.auth_req.params = clientid=%c,username=%u,password=%P
auth.http.super_req = http://somesite.com/mqtt/superuser
auth.http.super_req.method = post
auth.http.super_req.params = clientid=%c,username=%u
auth.http.acl_req = http://somesite/mqtt/acl
auth.http.acl_req.method = post
auth.http.acl_req.params = access=%A,username=%u,clientid=%c,ipaddr=%a,topic=%t,mountpoint=%m
auth.http.request.retry_times = 3
auth.http.request.retry_interval = 1s
auth.http.request.retry_backoff = 2.0
Endpoints(http://somesite.com/mqtt/superuser, http://somesite/mqtt/acl) are working fine and I can get access to it from Postaman app. May be you could tell me where I do something wrong in my configuration or somewhere else?

Maybe uou need to provide your HTTP server code.
http respose status 200 is ok
http respose status 4xx is unauthorized
http respose status 200 and body is ignore means break
This is a project just passed the test:
egg-iot-with-mqtt
/**
* Auth
*/
router.post('/mqtt/auth', async (ctx, next) => {
const { clientid, username, password } = ctx.request.body
// Mock
// 200 means ok
if (clientid === '' || 'your condition') {
ctx.body = ''
} else {
// 4xx unauthorized
ctx.status = 401
}
})
/**
* ACL
*/
router.post('/mqtt/acl', async (ctx, next) => {
/**
* Request Body
* access: 1 | 2, 1 = sub, 2 = pub
* access in body now is string !!!
{
access: '1',
username: 'undefined',
clientid: 'mqttjs_bf980bf7',
ipaddr: '127.0.0.1',
topic: 't/1',
mountpoint: 'undefined'
}
*/
const info = ctx.request.body
console.log(info)
if (info.topic === 't/2') {
// 200 is ok
ctx.body = ''
} else {
// 4xx is unauthorized
ctx.status = 403
}
})

Related

Salesforce Authentication in NodeJs

I am trying to authenticate Salesforce to NodeJS application.I getting error Like Error: invalid_grant - authentication failure .What else I am missing here. Do I need to do any configurations from salesforce side. Here is my code. Could Someone help me on this?
app.js
var nforce = require('nforce');
const client_id = '**'
const client_secret = '****'
const redirect_uri = 'https://***.sandbox.my.salesforce.com/services/oauth2/success'
const sfdc_user = '*****'
const sfdc_pass = '***'
const credentials = {
client_id :client_id,
client_secret:client_secret,
grant_type:"password",
username:sfdc_user,
password:sfdc_pass
}
async function getConnection(){
const loginUrl = "https://***.sandbox.my.salesforce.com/services/oauth2/token";
var org = nforce.createConnection({
clientId: credentials.client_id,
clientSecret: credentials.client_secret,
redirectUri: redirect_uri,
});
console.log('org >>'+JSON.stringify(org));
let oauth= await org.authenticate({ username: credentials.username, password: credentials.password});
console.log('oauth >>'+oauth); //Couldnt get this console
const access_token = oauth.access_token;
const sf_auth_url = oauth.instance_url + '/services/data/v48.0/'
sf_auth = {
'Authorization':'Bearer ' + access_token,
'Content-type': 'application/json',
'Accept-Encoding': 'gzip'
}
return { sf_auth,sf_auth_url }
}
module.exports = { getConnection }
main.js
const f = require('./app');
const https = require('https')
const fs = require('fs')
const port = 3000
const server = https.createServer(function(req,res){
res.writeHead(200,{'Content-Type': 'text/html'})
res.end();
})
server.listen(port,function(error){
if(error){
console.log('Something Went Wrong!')
}else{
console.log('Server is listening on port '+port)
f.getConnection();
}
})
Usually when I have received this error it's due to not having the user's security security token appended to the end of the password field. This is the token sent to you via email when you first set your password or performed your last password reset. If you need to reset it you can do so via Personal Settings > Reset My Security Token
Reset Your Security Token
In the event it's not that, this username/password authentication documentation should help.
OAuth 2.0 Username-Password Flow for Special Scenarios

Cloudflare Workers Geolocation

We have an Cloudflare Enterprise plan and want to pass in the regionCode (state abbreviation) into the header response back to the client. The Cloudflare request is req.cf.regionCode but for whatever reason I constantly get an error when I try to assign it to a variable so there is something wrong with the syntax.
Ultimately the header output should be:
state: CA (would show the state abbreviation from the client's IP lookup, in this case it would be California)
addEventListener("fetch", event => {
event.respondWith(fetchAndReplace(event.request))
})
async function fetchAndReplace(request) {
const res = await fetch(request)
let modifiedHeaders = new Headers()
let state = (req.cf.regionCode)
modifiedHeaders.set('Content-Type', 'text/html')
modifiedHeaders.append('Pragma', 'no-cache')
modifiedHeaders.append("state", `${state}`)
//Return maint page if you're not calling from a trusted UA
if (request.headers.get("User-Agent") !== "Preprod")
{
// Return modified response.
return new Response(maintPage, {
status: 503,
headers: modifiedHeaders
})
}
else //Allow users from trusted into site
{
//Fire all other requests directly to our WebServers
return fetch(request)
}
}
let maintPage = `
This is a test
`;

Use MSAL in Microsoft Teams not work JS

I work on an MS Teams app with a connection to MS Graph.
I'm trying to get an access token for MS Graph in MS Teams. To get a token I'm using MSAL js.
If I run the App with gulp serve I receive a valid token and I have access to the MS Graph endpoints. But if I build the app and install it in MS Teams the function userAgentApplication.acquireTokenSilent(config) is never executed. I tested it with a console.log before and after the call. There is no error thrown.
Do you have any idea why the above snippet is not executed in MS Teams (app and webapp)?
NEW:
On Home:
export function login() {
const url = window.location.origin + '/login.html';
microsoftTeams.authentication.authenticate({
url: url,
width: 600,
height: 535,
successCallback: function(result: string) {
console.log('Login succeeded: ' + result);
let data = localStorage.getItem(result) || '';
localStorage.removeItem(result);
let tokenResult = JSON.parse(data);
storeToken(tokenResult.accessToken)
},
failureCallback: function(reason) {
console.log('Login failed: ' + reason);
}
});
}
On Login
microsoftTeams.initialize();
// Get the tab context, and use the information to navigate to Azure AD login page
microsoftTeams.getContext(function (context) {
// Generate random state string and store it, so we can verify it in the callback
let state = _guid();
localStorage.setItem("simple.state", state);
localStorage.removeItem("simple.error");
// See https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-implicit
// for documentation on these query parameters
let queryParams = {
client_id: "XXX",
response_type: "id_token token",
response_mode: "fragment",
scope: "https://graph.microsoft.com/User.Read openid",
redirect_uri: window.location.origin + "/login-end.html",
nonce: _guid(),
state: state,
login_hint: context.loginHint,
};
// Go to the AzureAD authorization endpoint (tenant-specific endpoint, not "common")
// For guest users, we want an access token for the tenant we are currently in, not the home tenant of the guest.
let authorizeEndpoint = `https://login.microsoftonline.com/${context.tid}/oauth2/v2.0/authorize?` + toQueryString(queryParams);
window.location.assign(authorizeEndpoint);
});
// Build query string from map of query parameter
function toQueryString(queryParams) {
let encodedQueryParams = [];
for (let key in queryParams) {
encodedQueryParams.push(key + "=" + encodeURIComponent(queryParams[key]));
}
return encodedQueryParams.join("&");
}
// Converts decimal to hex equivalent
// (From ADAL.js: https://github.com/AzureAD/azure-activedirectory-library-for-js/blob/dev/lib/adal.js)
function _decimalToHex(number) {
var hex = number.toString(16);
while (hex.length < 2) {
hex = '0' + hex;
}
return hex;
}
// Generates RFC4122 version 4 guid (128 bits)
// (From ADAL.js: https://github.com/AzureAD/azure-activedirectory-library-for-js/blob/dev/lib/adal.js)
function _guid() {...}
on login end
microsoftTeams.initialize();
localStorage.removeItem("simple.error");
let hashParams = getHashParameters();
if (hashParams["error"]) {
// Authentication/authorization failed
localStorage.setItem("simple.error", JSON.stringify(hashParams));
microsoftTeams.authentication.notifyFailure(hashParams["error"]);
} else if (hashParams["access_token"]) {
// Get the stored state parameter and compare with incoming state
let expectedState = localStorage.getItem("simple.state");
if (expectedState !== hashParams["state"]) {
// State does not match, report error
localStorage.setItem("simple.error", JSON.stringify(hashParams));
microsoftTeams.authentication.notifyFailure("StateDoesNotMatch");
} else {
// Success -- return token information to the parent page.
// Use localStorage to avoid passing the token via notifySuccess; instead we send the item key.
let key = "simple.result";
localStorage.setItem(key, JSON.stringify({
idToken: hashParams["id_token"],
accessToken: hashParams["access_token"],
tokenType: hashParams["token_type"],
expiresIn: hashParams["expires_in"]
}));
microsoftTeams.authentication.notifySuccess(key);
}
} else {
// Unexpected condition: hash does not contain error or access_token parameter
localStorage.setItem("simple.error", JSON.stringify(hashParams));
microsoftTeams.authentication.notifyFailure("UnexpectedFailure");
}
// Parse hash parameters into key-value pairs
function getHashParameters() {
let hashParams = {};
location.hash.substr(1).split("&").forEach(function (item) {
let s = item.split("="),
k = s[0],
v = s[1] && decodeURIComponent(s[1]);
hashParams[k] = v;
});
return hashParams;
}
Even though my answer is quite late, but I faced the same problem recently.
The solution is farely simple: MSALs silent login does not work in MSTeams (yet) as MSTeams relies on an IFrame Approach that is not supported by MSAL.
You can read all about it in this Github Issue
Fortunately, they are about to release a fix for this in Version msal 1.2.0 and there is already an npm-installable beta which should make this work:
npm install msal#1.2.0-beta.2
Update: I tried this myself - and the beta does not work as well. This was confirmed by Microsoft in my own Github Issue.
So I guess at the time being, you simply can't use MSAL for MS Teams.

Dart servers refusing connection in local network

I have Dart running on Mac Mavericks and Ubuntu Linux. I am just getting started;and, none of the examples will function through my local network. When I install a server on Ubuntu and try to access with the mac- nothing happens. When I try to access from Ubunutu, I get a "java.net Connection Refused error" Same goes for Curl on either machine, (connection refused). All of the samples run fine as client/server from localhost. Neither, Client apps or Browsers are able to connect. All other servers/clients working normally in the home network. Firewall is ok, and I double checked port numbers. There are no conflicting servers on the desired ports. I tried about 5 different scripts from the Dart site and others, each with a CORS function, but nothing connects, including the sample below, SimpleServer
-Github
Sample Code
/* A simple web server that responds to **ALL** GET requests by returning
* the contents of data.json file, and responds to ALL **POST** requests
* by overwriting the contents of the data.json file
*
* Browse to it using http://localhost:8080
*
* Provides CORS headers, so can be accessed from any other page
*/
import 'dart:io';
final HOST = "127.0.0.1"; // eg: localhost
final PORT = 8080;
final DATA_FILE = "data.json";
void main() {
HttpServer.bind(HOST, PORT).then((server) {
server.listen((HttpRequest request) {
switch (request.method) {
case "GET":
handleGet(request);
break;
case "POST":
handlePost(request);
break;
case "OPTIONS":
handleOptions(request);
break;
default: defaultHandler(request);
}
},
onError: printError);
print("Listening for GET and POST on http://$HOST:$PORT");
},
onError: printError);
}
/**
* Handle GET requests by reading the contents of data.json
* and returning it to the client
*/
void handleGet(HttpRequest req) {
HttpResponse res = req.response;
print("${req.method}: ${req.uri.path}");
addCorsHeaders(res);
var file = new File(DATA_FILE);
if (file.existsSync()) {
res.headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
file.readAsBytes().asStream().pipe(res); // automatically close output stream
}
else {
var err = "Could not find file: $DATA_FILE";
res.write(err);
res.close();
}
}
/**
* Handle POST requests by overwriting the contents of data.json
* Return the same set of data back to the client.
*/
void handlePost(HttpRequest req) {
HttpResponse res = req.response;
print("${req.method}: ${req.uri.path}");
addCorsHeaders(res);
req.listen((List<int> buffer) {
var file = new File(DATA_FILE);
var ioSink = file.openWrite(); // save the data to the file
ioSink.add(buffer);
ioSink.close();
// return the same results back to the client
res.add(buffer);
res.close();
},
onError: printError);
}
/**
* Add Cross-site headers to enable accessing this server from pages
* not served by this server
*
* See: http://www.html5rocks.com/en/tutorials/cors/
* and http://enable-cors.org/server.html
*/
void addCorsHeaders(HttpResponse res) {
res.headers.add("Access-Control-Allow-Origin", "*");
res.headers.add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
res.headers.add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
}
void handleOptions(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
print("${req.method}: ${req.uri.path}");
res.statusCode = HttpStatus.NO_CONTENT;
res.close();
}
void defaultHandler(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
res.statusCode = HttpStatus.NOT_FOUND;
res.write("Not found: ${req.method}, ${req.uri.path}");
res.close();
}
void printError(error) => print(error);
data.json
{
"language":"DART",
"targets":["dartium","javascript","Android?"],
"website":{
"homepage":"www.dartlang.org",
"api":"api.dartlang.org"
}
}
I think this is because the Dart server is configured to listen to only the clients on the localhost. You need to make it to listen to any IPv4/v6 client in order to receive any response from the server over the network.
Change the line final HOST = "127.0.0.1"; to final HOST = InternetAddress.ANY_IP_V4;
or final HOST = InternetAddress.ANY_IP_V6;
It should make it work.

Dart mailer returning success or error to client

I'm learning dart and have created a simple contact form - based on the forms tutorial on the dart site, using mailer to send a mail.
So far so good - the client post the message, the server picks up the post data, creates an envelope and sends the mail... but I want to display a comforting message to the person filling out the form, or warn them if it were not sent.
The problem is that the http response is sent before the future that sends the email is completed -
Chris Storm talks about using completers to solve this problem, I think - here: testing error conditions with dart and again in a chapter in Dart for Hipsters, but i am finding it hard to work out how to apply it here.
Here is the complete server code - the comments in the sendMail function show the problem.
import 'dart:io';
import 'dart:convert';
import 'package:mailer/mailer.dart';
final HOST = '127.0.0.1'; // eg: localhost
final PORT = 4040; // a port, must match the client program
void main() {
HttpServer.bind(HOST, PORT).then(gotMessage, onError: printError);
}
void gotMessage(_server) {
_server.listen((HttpRequest request) {
switch (request.method) {
case 'POST':
handlePost(request);
break;
case 'OPTIONS':
handleOptions(request);
break;
default: defaultHandler(request);
}
},
onError: printError); // .listen failed
print('Listening for GET and POST on http://$HOST:$PORT');
}
/**
* Handle POST requests
*
*/
void handlePost(HttpRequest req) {
HttpResponse res = req.response;
print('${req.method}: ${req.uri.path}');
addCorsHeaders(res);
req.listen((List<int> buffer) {
// Create a new string from the characters in the buffer and convert this into a map
Map postData = JSON.decode(new String.fromCharCodes(buffer));
res.write(sendMail(postData));
res.close();
},
onError: printError);
}
/**
* Add Cross-site headers to enable accessing this server from pages
* not served by this server
*
* See: http://www.html5rocks.com/en/tutorials/cors/
* and http://enable-cors.org/server.html
*/
void addCorsHeaders(HttpResponse res) {
res.headers.add('Access-Control-Allow-Origin', '*, ');
res.headers.add('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.headers.add('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
}
void handleOptions(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
print('${req.method}: ${req.uri.path}');
res.statusCode = HttpStatus.NO_CONTENT;
res.close();
}
void defaultHandler(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
res.statusCode = HttpStatus.NOT_FOUND;
res.write('Not found: ${req.method}, ${req.uri.path}');
res.close();
}
void printError(error) => print(error);
sendMail(postData) {
String sentMsg = 'I am waiting for a result to report'; //initialised value
var options = new GmailSmtpOptions()
..username = 'my.mailt#gmail.com' //shove real values in here to test
..password = 'my_password';
var transport = new SmtpTransport(options);
// Create the envelope to send.
var envelope = new Envelope()
..fromName = postData['name']
..from = postData['fromEmail']
..recipients = ['the_recipient#somedomain.com']
..subject = 'Message from contact form'
..text = postData['contactMessage'];
transport.send(envelope)
.then((success) => sentMsg = 'Message sent, thank you.' ) //this will not be returned...
.catchError((e) => sentMsg = 'Message not sent; the reported error was: $e'); // nor will this
return sentMsg; // Sadly the initial value will be returned as the future (transport.send) will not have completed
}
If I get it right, you want to send a response based on the result on transport.send(). If so you can just return it, like
return transport.send(envelope)
.then((success) => sentMsg = 'Message sent, thank you.' )
.catchError((e) => sentMsg = 'Message not sent; the reported error was: $e');
Or using Completer
var c = new Completer();
transport.send(envelope)
.then((success) => sentMsg = 'Message sent, thank you.' )
.then(c.complete)
.catchError((e) => sentMsg = 'Message not sent; the reported error was: $e');
return c.future;
And since you are returning a Future, you have to change how you send your response to client, from
res.write(sendMail(postData));
res.close();
to
sendMail(postData)
.then((result) {
res.write(result);
res.close();
});
Your code doesn't look bad :)
As far as I can see there isn't missing much (haven't tried to execute it though).
request.response.write('Hello, world');
request.response.close();
either in handlePost() (where you have req available or
return the result that you want to return to the client from handlePost() to gotMessage() and add above lines there.
Also take a look at An Introduction to the dart:io Library - Writing web servers

Resources