How to login into Onelogin via custom UI and redirect to a preconfigured APP - node.js

We need to be able to login to onelogin and redirect to an APP on clicking a button in our home page. We should also be able to send some custom params. We tried using passport-saml for this but we are getting
The SAMLResponse ID was already processed
Any leads/documentation on how to proceed would be helpful.
Our passport code looks like
passport.use(new SamlStrategy(
{
callbackUrl: '/app/agent-websites/onelogin/callback',
entryPoint: entryPointUrl,
issuer: issuerUrl,
cert: cert,
},
function(profile: any, done: any) {
console.log(profile);
return done(null, profile);
})
);

Related

Passport SAML Reply URL/callback switches from https to http

I have tried to find answers for this issue before posting the question but unfortunately those solutions have not worked for me so I am posting my questions after exhausting my options
Similar Question
Similar Question 2
I am trying to authenticate my node js app with passport saml and Azure AD and I am trying this for the first time.
I have configured the app and following attributes in the Azure portal:
Entity ID https://sampleserver.com/
Reply URL https://sampleserver.com/login/saml/callback
Logout URL https://sampleserver.com/logout
This is my passport config
passport.use(
new SamlStrategy(
{
path: "/login/saml/callback",
entryPoint: "https://my-azure-server/ls/adfs,
issuer: "https://sampleserver.com/",
decryptionPvk: fs.readFileSync('privateKey.pem'),
cert: fs.readFileSync('publicCert.pem')
},
function (profile, done) {
console.log("This is what is returned by Saml", profile);
return done(null, {
id: profile.uid,
email: profile.mail,
displayName: profile.givenname,
firstName: profile.givenname
});
}
)
);
The decryptionPvk is the key is used to create my server
The cert is the certificate I got from my IDP i.e. Azure
Problem: When I hit the URL https://sampleserver.com it navigates me to the login URL configured in the application but after the authentication, it gives me the following error:
AADSTS50011: The reply URL 'http://sampleserver.com/login/saml/callback' specified in the request
does not match the reply URLs configured for the application 'https://sampleserver.com/'
The callback URL should be https://sampleserver.com/login/saml/callback but for some reason the request builds the absolute URL to be http://sample...... instead of https://sample...
I am not able to understand why it picks http vs https
I have been stuck on this for a couple of days now and I have tried to read as much as possible before posting this question. I would really appreciate some help with this.
I hope this helps someone who is facing a similar issue but after going through each and every attribute of SamlStrategy from the documentation I found something that resolved my issue. Instead of setting path in the passport config I set the callbackUrl attribute which was the absolute path of the call back URL which made it work
So my config looks as follows:
passport.use(
new SamlStrategy(
{
callbackUrl: "https://sampleserver.com/login/saml/callback",
entryPoint: "https://my-azure-server/ls/adfs,
issuer: "https://sampleserver.com/",
decryptionPvk: fs.readFileSync('privateKey.pem'),
cert: fs.readFileSync('publicCert.pem')
},
function (profile, done) {
console.log("This is what is returned by Saml", profile);
return done(null, {
id: profile.uid,
email: profile.mail,
displayName: profile.givenname,
firstName: profile.givenname
});
}
)
);

access_token not present in the passport-github2 request

I have registered an OAuth App via my Github account. I am basically trying to authorize my node requests(by sending access_token as part of request cookies) so I can access few APIs on another server. Hence I am using the github-passport2 package. I have setup the github strategy etc. & it seems to be all according to the doc. The flow works well too.
My Issue
After logging into Github(authorized) & getting redirected back to my /auth/github/callback, I ideally should be authorized and should have an access_token in the req. But I don't have it! Because of this I am not able to authorize my future requests with an access_token.
Important to note is that, this access_token is automatically attached when the request is initiated from a browser/client(using withCredentials: true parameter). The same access_token via node doesn't seem to be retrievable.
passport.use(new GitHubStrategy({
clientID: GITHUB_CLIENT_ID,
clientSecret: GITHUB_CLIENT_SECRET,
callbackURL: "http://localhost:8080/auth/github/callback",
},
function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
return done(null, profile);
});
}
));
app.get('/auth/github', passport.authenticate('github', { scope: [ 'user:email' ] }), function(req, res){
// The request will be redirected to GitHub for authentication, so this
// function will not be called.
});
app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/login' }), function(req, res) {
console.log(req); // <- This ideally should have the access_token? but doesn't
});
I have struggling for days on this. Any help is much appreciated.

Handling authentication in Nodejs with passport-facebook-token, request coming from frontend Facebook SDK

I am working on a Unity App. For login, there are two methods, one using Email and another using Facebook. In case of login separately, I do not have any problem. Registration and Login with Email works perfectly. And Login with Facebook works perfectly as well. Here's the workflow, I created just to make you clear.
tl;dr [read update]
There's another schema for account, which is used for login.
var Account = new Schema({
email: String,
password: String,
facebookId: String
});
Things to know about the backend API.
Passport is used for Authentication
Successful login returns email and token to the client through API.
On client, token is most to play game and use the overall features.
As I said, I have already covered the part when if a client registers and login using email, then client can use the app. But my confusion is handling the logins with Facebook. Facebook SDK is already integrated with the Unity App, and Login is success.
Now, how can I use the Facebook login information that is generated by the Facebook SDK onto my back end, so that I can authorize the user throughout the system, as done in email login.
Going through other questions in SO and Google, I came across passport-facebook-token, I also tried using the plugin but could not came up with the logic and flow for handling the data from SDK into the Nodejs API. Can someone me help understand how it is done?
Update 1: Using passport-facebook-token
Strategy on index.js
passport.use(new FacebookTokenStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET
}, function(accessToken, refreshToken, profile, done) {
Account.findOrCreate({facebookId: profile.id}, function (error, user) {
return done(error, user);
});
}
));
Controller API
api.post('/auth/facebook/token',
passport.authenticate('facebook-token'),
function (req, res) {
console.log(req.user);
// do something with req.user
res.sendStatus(req.user? 200 : 401);
}
);
Now, there is no error shown, but the data is not inserted into Account Schema, I have this findOrCreate() function in Model.
Account.statics.findOrCreate = function findOrCreate(profile, cb){
var userObj = new this();
this.findOne({facebookId : profile.id},function(err,result){
if(!result){
userObj.facebookId = profile.id;
//....
userObj.save(cb);
}else{
cb(err,result);
}
});
};
you can use facebook-passport for that, you can check the documentation here: https://github.com/jaredhanson/passport-facebook but basically, after you have already set up your developer account and got your keys from the developer site of facebook you can implement a FacebookStrategy object like following where you have to specify your credential and also a callback that in the documentation example is an http request to another resource of an express server where you can then save the data to mongo
passport.use(new FacebookStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ facebookId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));

Passport - Azure AD - Application is not supported for this API version

When I use NPM package "passport-azure-ad" to try and connect to Azure AD, I am getting the error below. I have successfully connected to Facebook, Google, and MSFT Live, successfully, but cannot figure out why Azure AD doesn't like my configuration.
What does this error mean???
Error:
Application xxx is not supported for this API version.
I've looked at quite a few articles and the GitHub repo, but each is slightly different, and doesn't make it clear which options are required.
https://github.com/AzureADQuickStarts/B2C-WebApi-Nodejs/blob/master/node-server/app.js
https://github.com/Azure-Samples/active-directory-node-webapp-openidconnect/blob/master/app.js
Here's my configuration:
var OIDCStrategy = require('passport-azure-ad').OIDCStrategy;
var WINDOWS_AD_CLIENT_ID = "xxxx"
var WINDOWS_AD_CLIENT_SECRET = "xxxx"
passport.use(new OIDCStrategy({
callbackURL: "/dealer/auth/azuread/callback"
, realm: 'xxxxx' //tenant Id
, clientID: WINDOWS_AD_CLIENT_ID
, clientSecret: WINDOWS_AD_CLIENT_SECRET
, identityMetadata: 'https://login.microsoftonline.com/common/.well-known/openid-configuration'
//, tenantName: 'xxxx.onmicrosoft.com'
//, policyName: 'B2C_1_DealerSignin'
//, validateIssuer: true
//, audience: 'http://localhost:3000/dealer'
//oidcIssuer: config.creds.issuer,
, skipUserProfile: true // for AzureAD should be set to true.
, responseType: 'id_token' // for login only flows use id_token. For accessing resources use `id_token code`
, responseMode: 'form_post' // For login only flows we should have token passed back to us in a POST
//scope: ['email', 'profile'] // additional scopes you may wish to pass
},
function(iss, sub, profile, accessToken, refreshToken, done) {
console.log("Windows AD Profile retrieved")
return done(null, profile);
}
));
And Routes:
router.get('/auth/azuread',
passport.authenticate('azuread-openidconnect', { scope: 'email profile' }),
function(){
console.log("Azure AD endpoint invoked.")
});
router.post('/auth/azuread/callback',
function(req, res, next) {
console.log("Azure AD Auth callback is invoked")
next()
},
passport.authenticate('azuread-openidconnect'),
function(req, res) {
console.log("Azure AD Auth callback is finished")
res.redirect('/dealer');
}
);
I ran into the same issue whenever I created my application under:
Portal.Azure.com -> Azure AD -> App Registrations
or the equivalent on the Classic Portal.
I had to create my app under:
apps.dev.microsoft.com
For it to work. Hopefully this helps someone else.

passport.js - facebook strategy logout issue

I'm trying to set up facebook authentication using this login example. Example works but when I log out and try to log in again passport automatically lets me in without giving me an option to change facebook user. Any idea on how to change this behaviour?
By default, if you have already authorized login with Facebook, subsequent requests to authenticate will be automatic and won't prompt the user to authorize again. There are three options to change this behavior:
1. Log the user out of Facebook
This is undesirable, since you only want to log the user out of your application and not Facebook entirely.
2. De-authorize the user from your Facebook application
This is your best bet. To do this, make an HTTP DELETE call to https://graph.facebook.com/me/permissions with a valid Facebook access token. Read more at https://developers.facebook.com/docs/reference/api/user/#permissions.
3. Force the user to re-authenticate each time you log them in
Facebook supports an auth_type parameter, which will prompt the user to login each time when set to reauthenticate. Read more at https://developers.facebook.com/docs/howtos/login/client-side-re-auth/.
Passport.js does not support passing this parameter out of the box, so you might have to do a little hacking to get it working in your application, or submit a pull request to the passport-facebook GitHub project.
However, you can optionally prompt the user to reauthenticate each time by using a specific parameter. Working but hacky and not-recommended way of doing this below:
FacebookStrategy.prototype.authorizationParams = function (options) {
var params = {},
display = options.display,
auth_type = options.auth_type;
if (display) params['display'] = display;
if (auth_type) params['auth_type'] = auth_type;
return params;
};
passport.use(new FacebookStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/callback",
auth_type: "reauthenticate"
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
}
));
The Facebook Passport supports the auth_type, which will redirect the user to sign in again for the OAuth tokens for the app even the users have login on the browser.
To enable this re-login behaviour on Facebook, use the following code
passport.authenticate('facebook', {authType: 'reauthenticate', callbackURL:...
You need to logout from facebook too (or remove the application from the list in your settings). Otherwise facebook remembers that the user (you) has accepted to login into your app and returns to the application without asking you anything.
As when looked at the options , the value is {} , then i have added the field auth_type = "reauthenticate" in authorizationParams, instead of putting as options in the constructor or as Authenticate options( both didn't work for me ).
var fbStrategy = require('passport-facebook').Strategy;
fbStrategy.prototype.authorizationParams = function (options) {
var params = {};
params.auth_type = "reauthenticate";
// params.auth_nonce = hash.digest((new Date()).getTime());
// console.log(options,":options",params)
return params;
};
passport.use('facebook',new fbStrategy({
clientID: process.env.clientID,
clientSecret: process.env.clientSecret,
callbackURL: yourcallbackURL,
// this option to pass req
passReqToCallback : true
},
function (req, accessToken, refreshToken, profile, cb) {
......
}));

Resources