Ldap authentication in Loopback 4 -- 'Missing credentials' - node.js

I have followed the tutorials for adapting passport authentication strategies to Loopback 4, and have successfully gotten passport-http to work. But, when trying to get passport-ldapauth to work with loopback 4, I am consistently getting the following error Http response (using postman):
{
"error": {
"statusCode": 401,
"name": "UnauthorizedError",
"message": {
"message": "Missing credentials"
}
}
}
I have confirmed the online LDAP test server works with my setup (used a plain Express app with passport-ldapauth, with total success). Using the same LDAP config in Loopback 4, however, produces the above error.
My test Loopback app is here: https://replit.com/#woff2/CarefulGreenBits
It seems to me that I am doing something wrong with passing the verifyFn in to the AuthenticationStragegy.
Can anyone see what I am doing wrong? I have been at this for three or four days now!
It would be of great benefit to the community to solve this. I have seen many people online wanting the same auth method to work in Loopback over the past week.
UPDATE: I've narrowed it down to the request body not being processed. Whether the request body contains the username/password pair or not, the same 'Missing credentials' error results.

I found out that the username/password tuple must be passed as params on the http request. This information was contained in source-code comments of the passport-ldapauth package. Note however that when using passport-ldapauth with Express framework, passing the tuple in the request body does work.

Related

Api is working fine with postman but not working in react

Nodejs api is working fine with postman but while i'm trying it with react i'm getting some errors like message: "Request aborted", name: "AxiosError", code: "ECONNABORTED"
I haven't added the authentication yet in my api so that is not needed i guess.
I tried to send it in various ways even i tried to handle preflight problem of cors but not sure if i handled that or not! the api is working with postman absolutely ok response as expected.
make sure you don't pass credentials query params in you get request. if you have added credentials in your get request replace your http method with post.

Not getting data of GITHUB api using npm module sync-request

I am trying to get data of below url using sync-request module.
https://api.github.com/repos/rethinkdb/rethinkdb/stargazers
I get the data when i call it in browser or through postman.
But i am getting 403 forbidden error when calling it using sync-request in my node api.
My code looks like this.
var request = require("sync-request");
var response = request('GET', 'https://api.github.com/repos/rethinkdb/rethinkdb/stargazers', {
headers: {},
json: true
});
I am able to fetch data of many other api's but not this one. Please help.
Response body already contains the explanation:
Request forbidden by administrative rules. Please make sure your request has a User-Agent header (http://developer.github.com/v3/#user-agent-required). Check https://developer.github.com for other possible causes.
It will work like:
var response = request('GET', 'https://api.github.com/repos/rethinkdb/rethinkdb/stargazers', {
headers: { 'User-Agent': 'Request' },
json: true
});
The use of sync-request is strongly discouraged because synchronousness is achieved via a hack and may block the process for a long time.
For sequential execution request-promise can be used together with async..await.
Try to use an access token along with the GitHub API call
like this
[https://api.github.com/repos/rethinkdb/rethinkdb/stargazers?access_token=f33d1f112b7883456c990028539a22143243aea9]
As you say the API works in the browser it should not be an issue.
When you use too many calls through the GitHub API they they give the following message
{
"message": "API rate limit exceeded for 192.248.24.50. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
"documentation_url": "https://developer.github.com/v3/#rate-limiting"
}
To overcome this issue you can use an access token using an access token you can to access the private repositories in your account as well .
Here is the link for to get an access token [https://github.com/settings/developers]

Can I use the passport-google callback to authenticate android/ios users?

I have a node.js server which authenticates using google-passport-oauth2. My server-side code looks like that from the documentation:
app.get('/auth/google',
passport.authenticate('google', { scope:
[ 'https://www.googleapis.com/auth/plus.login',
, 'https://www.googleapis.com/auth/plus.profile.emails.read' ] }
));
app.get( '/auth/google/callback',
passport.authenticate( 'google', {
successRedirect: '/auth/google/success',
failureRedirect: '/auth/google/failure'
}));
I figure that /auth/google redirects to google's login, and when permissions are recieved, the google profile and token are sent to the callback /auth/google/callback.
Now I am making an android app which wants to authenticate with this API. I'm using the directions for integrating Google Sign-In to do the authentication on google's end. Now my android app has the profile and token and wants to verify it with my server.
I've tried doing this with passport-google-token and passport-google-id-token (not sure the difference...), but it didn't work for whatever reason. Now I'm looking at other possibilities, like a Google Client API library for node.js, but it seems bulky. Then there's the tokeninfo endpoint, which involves an extra request and more latency. Or maybe I should look at express-jwt?
And suddenly, I wonder... couldn't I just pass the token from my android app to the server at auth/google/callback? That would make things a little simpler. I think this must be a pipe dream, because I haven't found any information about doing it. But if it's possible, how should I format the token/profile data in the request so the passport.authenticate() method recognizes it? (JSON, form data, headers)
If this can't be done, I'm taking suggestions for well-documented token verification libraries for node...
I still don't know about reusing the google-passport-oauth2 route, but I did figure out how to validate Google's idToken using passport-google-id-token.
The documentation says:
The post request to this route should include a JSON object with the
key id_token set to the one the client received from Google (e.g.
after successful Google+ sign-in).
But it only works if it's sent as a query string (GET or POST works).
https://localhost:8888/auth/googletoken?id_token=xxxxxxxxxx
I have a feeling this is not the most secure method, but I'll have to deal with that later.
EDIT: It turns out, the token is useless without the client ID (in your app), so it's OK to send it by querystring.
EDIT 2: One of the google-id-token devs has reminded me that the JSON will only be received if body-parser has been installed.

What are some best practices for translating internal server error messages to client readable messages in Node.js?

Lets say I have couple of modules that handle authentication, One for each authentication provider (Google, Facebook, Email etc).
I also have a router that uses these modules to authenticate users request.
Lets say now that one of the users tries to authenticate and one of the auth module sees that the token is expired. I create an error inside that module with an internal message "token expired" or something like that, then pass it back to the calling router module. The router wants to send back a client readable message like "Your session has expired, please try to log out and in again".
So the problem is where to translate the error messages from their internal representation to their client readable versions.
There are two options the way I see it:
Do it inside each of the auth modules since they know best what was the problem. Downside - breaks the module abstraction, the module now has to deal with clients messages.
Do it in the router. Downside - need to create error codes / names and use an error handler with long list of case arguments to map each internal error to the client error. Might need to handle specific auth module errors as well, for example in email authentication the activation link in the email can be expired and the action needed is different then Facebook expired token.
What are some best practices to solve this problem, are there any Node / Express modules that help in some way ?
Many thanks
I think a good solution would be to use Express middleware for error handling.
function (err, req, res, next) {
// error translation and response sending
}
use a lang folder where the index file exposes specific language message files.
Suppose for English eng.js should be like:
module.exports = {
VALIDATION_ERROR_IN: 'Validation error in',
NOTHING_UPDATED: 'Nothing Updated',
UPDATE_NON_EXISTING_DOCUMENT_FAILED: 'can\'t update a non-existing document',
ID_REQUIRED: '\'_id\'is required',
USERID_REQUIRED: '\'userId\'is required'
}
and index.js should be like:
module.exports = require('./eng');
if you need any other language you can create new files like eng.js where the object keys remain the same but the values are language specific.
Catch the server errors and use this as follows:
var message=require('message') // suppose the folder name is 'message'
//....
res.send(message.FIELD_REQUIRED);

Inserting google plus moment using googleapis node.js api (google-api-nodejs-client)

Using the example here: https://developers.google.com/+/api/latest/moments/insert
and everyauth to handle the oauth login:
(with the .withAuth() added)
Or using my own simpler example I'm getting an "Invalid Value" status code: 400 error.
{"domain":"global","reason":"invalid","message":"Invalid Value"}
Has anyone been able to post a Google + moment using the google-api-nodejs-client library?
I use everyauth to handle oauth and login. My initialization code is below:
everyauth.google
.appId(conf.googlehybrid.clientId)
.appSecret(conf.googlehybrid.clientSecret)
.scope('https://www.googleapis.com/auth/plus.login\
https://www.googleapis.com/auth/plus.moments.write')
.findOrCreateUser( function (sess, accessToken, extra, googleUser) {
googleUser.refreshToken = extra.refresh_token;
googleUser.expiresIn = extra.expires_in;
return usersByGoogleId[googleUser.id] || (usersByGoogleId[googleUser.id] = addUser('google', googleUser));
})
.redirectPath('/');
The code above produces the following url:
https://accounts.google.com/o/oauth2/auth?client_id=507792786278.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fgoogle%2Fcallback&response_type=code&access_type=offline&approval_prompt=auto&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.moments.write&request_visible_actions=http:%2F%2Fschemas.google.com%2FCreateActivity
Note: I am using the "request-visible-actions" parameter in the url. Also note that the moment type matches the type specified in the code below as well as the schema.org specification for that type of moment.
The scopes seem to be processed correctly. The login sequence prompts me to approve
This app would like to:
-Know your basic profile info and list of people in your circles. (Edit list)
-Make your creative activity available via Google, visible to:...
My code:
var moment = {
"type":"http://schemas.google.com/CreateActivity",
"target": {
"id": "target-id-2",
"type": "http://schema.org/CreativeWork",
"name": "Test moment",
"description": "This is a sample moment",
"text": "samplpe g+ posting!"
}
}
gapi.client.plus.moments.insert(
{
'userId': 'me',
'collection': 'vault',
'resource': moment
})
.withAuthClient(authObject)
.execute(callback);
}
I have not had any problems interacting with Google+ or making authorized requests to Google services otherwise but can't seem to get the Google+ moments to insert. Has anyone been able to insert a Google+ moment using the google-api-nodejs-client library?
If so, please tell me what I'm doing wrong.
i've ran into a similar problem with the youtube api and it seems that way we should call the api from the node library is not the same as specified on the api docs.
specifically instead of doing this:
gapi.client.plus.moments.insert(
{ 'userId' : 'me',
'collection' : 'vault',
'resource' : payload
}
).execute(function(result){
console.log(result);
});
you have to make the following call:
gapi.client.plus.moments.insert(
{ 'userId' : 'me', 'collection' : 'vault'},
payload
).execute(function(result){
console.log(result);
});
the parameters of the requests are passed in the first parameter, and the request body is passed in the second parameter of the function.
I've been able to get this example to work using the same exact moment object and OAuth URL using Google's API in Python.
It appears there is some bug in how google-api-nodejs-client is packaging my request to insert a moment.
I don't have time to examine further so I'm going to stick with Python.
I would still prefer to use Node.
If anyone comes out with a bug fix or a solution to make this work in the Node api please let me know.

Resources