Saml Strategy Verify callback not getting called - passport-saml

As per the passportjs documentation, the verifier function is supposed to be called.
But I am not seeing this call back.
I am testing this with okta. In okta the app is configured to send the saml response to /fromokta
The okta is redirecting to /fromokta
What am I missing?
const saml = require('passport-saml').Strategy;
var strategy = new saml({
entryPoint: "<some oktka entiry point>",
issuer: "http://www.okta.com/foobar",
protocol: "http://"
},(profile, done) => {
console.log(">>>> callback from okta");
console.log(profile);
done(profile)
})
app.post('/login', function(req, res) {
passport.authenticate(
'saml',
{
//successRedirect: '/success',
failureRedirect: '/'
}
)}
)
app.post('/fromokta', function(req, resp){
// this gets called
})

This most likely means your POST /login route never gets the request. Look at the network requests and see if there is indeed a POST /login to the URL, make sure the protocol is the same too (http and https)

Related

Facebook webhook verification response structure

This is my first time posting the question so please feel to provide feedback to improve the question.
Facebook webhook mentions that the endpoint should be first verified before the webhook endpoint can receive any event notifications.
The docs for Verification Request does not provide a response structure for the API. It simply tells us to send back the hub.challenge parameter.
As I am using NodeJS, I am trying with the code below. However, it does not verify the webhook from facebook dashboard.
How should we send back the response to the verify the webhook?
app.get('/webhook', (req, res) => {
const challenge = req.query['hub.challenge'];
const verify_token = req.query['hub.verify_token'];
if (verify_token === process.env.FACEBOOK_VERIFICATION_TOKEN) {
return res.status(200).send({message: "Success", challenge: challenge});
}
return res.status(400).send({message: "Bad request!"});
})
The verification endpoint of Facebook requires the response Content-Type to be text/html. This is not mentioned on the docs;they should have provided a structure. You can set the header to use text/html explicitly.
However, when you are using express, you can directly return just the challenge value.
app.get('/webhook', (req, res) => {
const challenge = req.query['hub.challenge'];
const verify_token = req.query['hub.verify_token'];
if (verify_token === process.env.FACEBOOK_VERIFICATION_TOKEN) {
return res.status(200).send(challenge); // Just the challenge
}
return res.status(400).send({message: "Bad request!"});
})
If you are using fastify set:
res.header('Content-Type', 'text/html; charset=utf-8');
return res.send('' + challenge);

How to specify redirectUrl after logout for Ambassador OAuth2 Filter with Keycloak?

I'm using the Ambassador OAuth2 Filter to perform OAuth2 authorization against Keycloak.
For the logout I use the the RP-initiated logout as described in the Docs of Ambassador
The logout works fine. However I could not figure out how to provide the redirect url needed for Keycloak to redirect to the Login page after successfully logged out. As a result the user stays on the blank logout page of keycloak.
The RP-initiated logout looks as follows
const form = document.createElement('form');
form.method = 'post';
form.action = '/.ambassador/oauth2/logout?realm='+realm;
const xsrfInput = document.createElement('input');
xsrfInput.type = 'hidden';
xsrfInput.name = '_xsrf';
xsrfInput.value = getCookie("ambassador_xsrf."+realm);
form.appendChild(xsrfInput);
document.body.appendChild(form);
form.submit();
I expected that Ambassador provides a way to add the redirect url as a query param or something, but I couldn't find a solution.
Are there any suggestions or workarounds?
I found this in the Ambassador documentation that could be overlooked as I did several times:
Ambassador OAuth2 Settings
protectedOrigins: (You determine these, and must register them with your identity provider) Identifies hostnames that can appropriately set cookies for the application. Only the scheme (https://) and authority (example.com:1234) parts are used; the path part of the URL is ignored.
You will need to register each origin in protectedOrigins as an authorized callback endpoint with your identity provider. The URL will look like {{ORIGIN}}/.ambassador/oauth2/redirection-endpoint.
So it looks like ambassador hard codes the redirection-endpoint (redirect_uri) that you need add to your OAuth2 client in Keycloak.
I found a solution for that, is not the best solution but you will logout using a button.
async function logout() {
const data = new URLSearchParams("realm=keycloak-oauth2-filter.ambassador")
data.append('_xsrf', getCookie("ambassador_xsrf.keycloak-oauth2-filter.ambassador"));
fetch('/.ambassador/oauth2/logout', {
method: 'POST',
body: data
})
.then(function (response) {
if (response.ok) {
return response.text()
} else {
throw "err";
}
})
.then(function (text) {
console.log(text);
})
.catch(function (err) {
console.log(err);
});
}

Using Axios as an Alternative to request in nodejs

I am building a flutter application that requires oauth 1 authorization for one of the third party services I am using. Because flutter oauth 1 package is restricted I decided to use the oauth 1 package that npm provides. This is the code that is used to access the user generated access token from the site.
I previously used request to make a call to the api endpoint first, to access the token and secondly to use the token recieved to make another call to a different resource endpoint
How can I use axios to make the same request, emphasis on the fact that each request needs a hmac-sha1 signed signature in the header.
Thank you.
consumer: {
key: CONSUMER KEY,
secret: CONSUMER SECRET,
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
return crypto
.createHmac('sha1', key)
.update(base_string)
.digest('base64')
},
})
const request_data = {
url: 'https://www.instapaper.com/api/1/oauth/access_token/',
method: 'POST',
data: { x_auth_username : USERNAME , x_auth_password : PASSWORD , x_auth_mode : 'client_auth' },
}
request(
{
url: request_data.url,
form: request_data.data,
method: request_data.method,
headers: oauth.toHeader(oauth.authorize(request_data)),
},
function(error, response, body) {
// Process your data here
console.log(error);
console.log(response);
console.log(body);
}
)
Finally found the answer for this link to the issue created on github
https://github.com/axios/axios/issues/2771

How to access params from URL after redirect to different site (Express)

The SurveyMonkey API (documentation) requires implementation of oauth to let the user decide which scopes of their account the developer has access to.
I have the following code (adapted from this question) as a means to implement the first two steps in their documentation:
app.get('/surveymonkey/oauth', function (req, res) {
const code = req.query.code;
const post_body = querystring.stringify({
"client_secret": <client_secret>,
"redirect_uri": "https://b2e3b137.ngrok.io/surveymonkey/oauth",
"grant_type": "authorization_code",
"code": code
});
const options = {
hostname: 'api.surveymonkey.net',
port: 443,
path: 'oauth/authorize?api_key=<api_key>&redirect_uri=https%3A%2F%2Fb2e3b137.ngrok.io%2Fsurveymonkey%2Foauth&response_type=code&client_id=<client_id>',
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(post_body)
}
};
res.redirect('https://api.surveymonkey.net/oauth/authorize?api_key=<api_key>&redirect_uri=https%3A%2F%2Fb2e3b137.ngrok.io%2Fsurveymonkey%2Foauth&response_type=code&client_id=<client_id>');
console.log(req.params);
console.log(req.body);
console.log(req.query);
req.on('error', function(e) {
console.error(e);
});
});
When I fire up an ngrok server (ngrok http 443), everything is going fine, except when I hit the '/surveymonkey/oauth' route and validate the scopes (acting as the user), I get redirected to the route I specified in my SurveyMonkey App console, which contains the short-lived 'code' param that I'm trying to assign to the user, but I cannot get access to the 'code' param in the query string since it's been redirected to a different site.
The problem I'm currently facing looks similar to this and this, and I'm trying to get meaningful data back from req, but as you can see in the comments above, all of the data is undefined.

Passport and SailsJS, how to get isAuthenticated() test to pass

My code keeps failing here when the user tries to login:
isAuthenticated: function (req, res) {
if (req.isAuthenticated()) { return res.json(req.user); }
else { return res.send(401); }
},
It FAILS and I get GET http://localhost:1337/user/authenticated 401 (Unauthorized) in the console, even though the user has entered in a correct email and password.
Where in the code makes that test pass?
I have the related StackOverflow question with more info HERE.
The problem was that my frontend application has a different origin than my backend application, so the AJAX requests will not include the session cookie and req.isAuthenticated() will never return true.
Use the withCredentials options to force it.
$http({ withCredentials: true, ... })