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

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.

Related

Google OAuth2 authentication in Swagger for a Node,js application

I have created a simple NodeJS application which is using Passport for handling OAuth2 authentication using Google. I created credentials in Google API, configured the Google strategy ...
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
passport.serializeUser((user , cb) => {
cb(null , user);
})
passport.deserializeUser(function(user, cb) {
cb(null, user);
});
passport.use(new GoogleStrategy({
clientID: process.env.CLIENTID,
clientSecret: process.env.CLIENTSECRET,
callbackURL: process.env.CALLBACK,
passReqToCallback: true
},
function(request, accessToken, refreshToken, profile, cb) {
return cb(null, profile);
}
));
app.use(passport.initialize());
app.use(passport.session());
The application works great and credentials allow me to control access to the application.
I have also configured Swagger to provide a way to test the REST API's provided by the application.
var options = {
validatorUrl : null,
oauth: {
clientId: process.env.CLIENTID,
clientSecret: process.env.CLIENTSECRET,
appName: "MyApp",
}
};
var swaggerUi = require('swagger-ui-express');
swaggerDocument = require('./swagger.json');
app.use(
'/api-docs',
swaggerUi.serve,
swaggerUi.setup(swaggerDocument,false,options)
);
Swagger also works fine, but some of the API's require authentication, so I also need to have that OAUth2 authentication working with Google.
In my swagger.json (Swagger 2.0) I have configured the securityDefinitions section following some examples I have found:
"securityDefinitions": {
"google_oauth": {
"type": "oauth2",
"flow": "implicit",
"authorizationUrl": "https://accounts.google.com/o/oauth2/v2/auth",
"tokenUrl": "https://www.googleapis.com/oauth2/v4/token",
"scopes": {
"https://www.googleapis.com/auth/userinfo.profile": "All user operations requiring authentication."
}
}
},
Note: I have tried both with 'implicit' and 'authorizationCode' values for the flow.
And I have added security configuration to those API's which require credentials to be executed.
"/favourites/User/{user}/City/{city}": {
"post": {
"summary": "Adds the selected city as a new favourite for that user.",
"tags": ["Favourites"],
"security": [
{"google_oauth": ["https://www.googleapis.com/auth/userinfo.email"]}
],
In Swagger now the Authorize button is displayed and when clicked I get redirected to Google (in a new tab).
I provide my credentials and I am returned to the original Swagger tab.
But now, if I try to execute the protected API, my REST code is receiving a Bearer token (which I have not configured my application to handle).
I thought I might be using a wrong configuration for Swagger, so I changed the security definitions in the swagger.json file using the auth URL for my application (which is being called when using the application and not swagger).
"securityDefinitions": {
"google_oauth": {
"type": "oauth2",
"flow": "implicit",
"authorizationUrl": "http://www.myapp.es/auth",
"scopes": {
"favourites": "All user operations requiring authentication."
}
}
},
But this is not working either.
Any ideas? I think I am close and only some attribute is missing for having OAuth2 working in Swagger.
Thanks in advance.

How to login into Onelogin via custom UI and redirect to a preconfigured APP

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);
})
);

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.

Microsoft ad b2c issue: policy is missing

I made a chat bot which I want to authorize user using Azure ad b2c using OIDCStrategy. In the console, it always logs authentication failed due to: In collectInfoFromReq: policy is missing. The policy has been set in Azure. And I can't find somewhere to declare the policy in the code. Here is my server:
server.get('/login',
passport.authenticate('azuread-openidconnect',
{
failureRedirect:'/fail'
}),
function(req,res,next){
console.log('Login was called');
res.redirect('/',next);
}
)
server.post('/api/auth', passport.authenticate('azuread-openidconnect'));
And connection to the azure ad b2c:
passport.use(new OIDCStrategy({
redirectUrl:'http://localhost:3978/api/auth',
allowHttpForRedirectUrl:true,
clientID:'5fe844d7-e4d1-4c4c-ba70-078297b00abc',
clientSecret:'?aTvTEbwcNfUF2,^',
identityMetadata: 'https://login.microsoftonline.com/nuffieldbot.onmicrosoft.com/v2.0/.well-known/openid-configuration',
skipUserProfile: true,
responseType: 'code',
responseMode: 'form_post',
isB2C:true,
scope:['email','profile','offline_access','https://outlook.office.com/mail/read'],
loggingLevel:'info',
tenantName:'nuffieldbot.onmicrosoft.com',
passReqToCallback:true
},function(req, iss, sub, profile, accessToken, refreshToken, done){
log.info('Example:Email address we received was:', profile.email);
process.nextTick(function(){
findByEmail(profile.email,function(err,user){
if (err) {
return done(err);
}
if (!user){
users.push(profile);
return done(null, profile);
}
return done(null, user);
})
})
}
));
Where can I declare this policy in my code?
For B2C, we must have policy , if you have not set policy name in query string of request , it will throw error : In collectInfoFromReq: policy is missing . Please refer to source code of oidcstrategy.js :
// for B2C, we must have policy
if (self._options.isB2C && !params.policy)
return next(new Error('In collectInfoFromReq: policy is missing'));
You must set policy in request :
Sign In
You could also refer to code sample : Azure Active Directory OIDC Web Sample

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);
});
}
));

Resources