400 BadRequest: Missing Credential feathersjs authentication-local - node.js

I'm trying to authenticate a user using #feathersjs/authentication-local, Though I'm giving proper username & password, I get following response
{
"name": "BadRequest",
"message": "Missing credentials",
"code": 400,
"className": "bad-request",
"data": {
"message": "Missing credentials"
},
"errors": {}
}
DB property of user entity is username & password. My configuration is as following
const settings = {
secret: 'super&secret',
usernameField: 'username',
passwordField: 'password',
entityUsernameField: 'username',
entityPasswordField: 'password'
};
app.configure(authentication(settings))
.configure(local());
app.service('authentication').hooks({
before: {
create: [authentication.hooks.authenticate(['local', 'jwt'])],
remove: [],
}
});
I've added "strategy": "local" on request body. What am I missing? Please help.

This usually happens when there is no Express bodyParser middleware registered. As shown in the feathers-chat it has to be set up before authentication.

Missing Credential feathersjs authentication-local, this error may occur due to following reasons:
You are missing fields when sending the request. Usually, if there is any data present it throws an error as NotAuthenticated: Invalid login if the credentials are not correct.
Escape fields in default.json to avoid referring to system environmental variables. Refer to this.

Related

How to create draft in gmail api

I am trying to create a new draft for a user with the gmail api, however i am getting an error I dont understand.
I searched but can't find a way to fix this error in gmail api, i know how to fix it please help
error
code: 403,
errors: [
{
message: 'Insufficient Permission',
domain: 'global',
reason: 'insufficientPermissions'
}
]
my code
async function sendMessage() {
const gmail = google.gmail({ version: 'v1', auth: oauth2Client });
var drafts = await gmail.users.drafts.create({
userId: "me",
requestBody: {
id: "",
message: {
raw: "LS0tLQpGcm9tOiBKb2huIERvZSA8c0BnbWFpbC5jb20+ClRvOiBNYXJ5IFNtaXRoIDxzQGdtYWlsLmNvbT4KU3ViamVjdDogU2F5aW5nIEhlbGxvCkRhdGU6IEZyaSwgMjEgTm92IDE5OTcgMDk6NTU6MDYgLTA2MDAKTWVzc2FnZS1JRDogPDEyMzRAbG9jYWwubWFjaGluZS5leGFtcGxlPgoKaGVsbG8KLS0tLQ=="
}
}
}).catch((v) => {
console.log(v)
})
}
message: 'Insufficient Permission', domain: 'global', reason: 'insufficientPermissions'
Means that when you authorized this user you did not request enough scopes of authorization in order to use this method.
The Quick start for node.js
Has you use
const SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'];
While users.drafts.create requires one of the following scopes
Which means you need to change the scope in your code reauthorize your application which will request the proper scope from your user.
tip
To remove authorization make sure to delete the file in token.json it contains the users access token and refresh token, once deleted it will request authorization of your application again
const TOKEN_PATH = path.join(process.cwd(), 'token.json');

AuthenticationFailed when authenticating via nodejs app and package #azure/msal-node

I have an Azure app registered . I am trying to authenticate to that app . I am able to do that and successfully get the accesstoken and idtoken.
However, when I use that token and try to make a request to list subscriptions API (https://management.azure.com/subscriptions?api-version=2020-01-01) , the request fails and give response "AuthenticationFailed". I have also tried changing the scope to https://management.azure.com/.default but the same error is there. Below is the nodejs code and I am also attaching the API permissions of app
const config = {
auth: {
clientId: 'xxx',
authority: 'https://login.microsoftonline.com/organizations',
clientSecret: 'yyy',
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: msal.LogLevel.Verbose,
},
},
};
// Create msal application object
const pca = new msal.ConfidentialClientApplication(config);
// Create Express App and Routes
const app = express();
app.get('/', (req, res) => {
const authCodeUrlParameters = {
scopes: ['user.read','https://management.azure.com/user_impersonation'],
redirectUri: REDIRECT_URI,
};
// get url to sign user in and consent to scopes needed for application
pca
.getAuthCodeUrl(authCodeUrlParameters)
.then((response) => {
res.redirect(response);
})
.catch((error) => console.log(JSON.stringify(error)));
});
The response I am getting is
{
"error": {
"code": "AuthenticationFailed",
"message": "Authentication failed."
}
}
The error "AuthenticationFailed" usually occurs if you are using different scope token to call the API.
I tried to generate access token with the same scope as you
via Postman and got the same error while calling the query like below:
Please note that,
user.read audience is Microsoft Graph API
https://management.azure.com/user_impersonation audience is Azure Service Management.
As you have given two different scopes with different audiences, it will consider the first scope (user.read) to generate the token as mentioned in this SO Thread which was solved by me.
When you call the query https://management.azure.com/subscriptions?api-version=2020-01-01 with the above token, you will get the error as it is intended for MS Graph audience.
I tried to generate the token with scope https://management.azure.com/user_impersonation only, removing user.read like below:
With the above generated token, I am able to call the API successfully like below:
If you want token with different scopes, then you have to generate two access tokens separately.

how to initialize firebase-admin with oauth token

The following piece of code works locally (i.e. on my computer, while logged in on gcloud with a personal account):
import { initializeApp, applicationDefault } from 'firebase-admin/app'
initializeApp({
credential: applicationDefault(),
projectId: project,
})
But it fails when running from the CI. For the CI login, I'm using oidc authentication with a service account. Running gcloud auth list from the CI shows that it's properly logged in. I have credentials file set up, and can get a oauth2 token. When running the above code, however, I got the following error:
{
...
errorInfo: {
code: 'app/invalid-credential',
message: 'Invalid contents in the credentials file'
},
codePrefix: 'app',
}
I tried using the refreshToken function istead of applicationDefault, but it seems the credentials that I got from oidc-login do not match the requirements. They look like
{
"type": "external_account",
"audience": "//iam.googleapis.com/projects/xxx/locations/global/workloadIdentityPools/xxx/providers/xxx",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"token_url": "https://sts.googleapis.com/v1/token",
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/xxx#xxx.iam.gserviceaccount.com:generateAccessToken",
"credential_source": {
"url": "https://pipelines.actions.githubusercontent.com/xxx",
"headers": { "Authorization": "xxx" },
"format": { "type": "json", "subject_token_field_name": "value" }
}
}
I also tried to create a Credential object manually, by passing an access token (gcloud auth print-access-token does generate an oauth2 token), but I couldn't make anything work so far.
It looks to me that I have credentials that work with gcloud cli, but I can't do anything with them in nodejs. Any Idea on how to do this properly ?

Custom response Express Validator as JSON

I'm using Express Validator for validate user req. I'm trying to create custom response like this:
{
"code": 300,
"status": false,
"message": "Your email is not valid",
"param": "email",
"value": "kevin"
}
but what I got is
[
{
"code": 300,
"status": false,
"message": "Your email is not valid",
"param": "email",
"value": "kevin"
}
]
Here is my code:
controller.js:
const errors = validationResult(req).formatWith(utils.error);
if(!errors.isEmpty()){
res.status(300).json(errors.array());
}
ResUtils.js
error({msg, param, value, nestedErrors}) {
var code = 300;
var format = {code, status:false, message:msg, param:param, value:value, nestedErrors:nestedErrors};
return format;
}
How do I can get the response as Json, without [].
Thankyou.
Well, this state is good in my opinion, there is possibility of multiple errors so you should process all messages in a frontend app (or mobile or whatever) to give user informations about all invalid fields (or options or whatever). If you really need only a object, you can pick a first error message from an array for example.
if(!errors.isEmpty()){
const errorsArray = errors.array();
res.status(300).json(errorsArray[0]);
}
But as I said it is better approach to handle all error messages.

Battle.net API returns 401 Error using OAuth Token

I'm using Nodejs with express on the Battle.net API to generate an Oauth Token. https://develop.battle.net/documentation/guides/using-oauth
Generating the token itself works, as it returns me the token. But when I use the code to make a request to their API, for example:
https://eu.api.blizzard.com/wow/guild/Malfurion/The%20new%20Dimension?fields=members&locale=de_DE&access_token=HEREISMYTOKEN
I get a 401 Unauthorized Error Response, debug log:
{ url:
'https://eu.api.blizzard.com/wow/guild/Malfurion/The%20new%20Dimension?fields=members&locale=de_DE&access_token=HEREISMYTOKEN',
status: 401,
statusText: 'Unauthorized',
headers: Headers { [Symbol(map)]: [Object] } }
I'm trying to fetch the members of a guild via fetch().
I already tried:
Creating a new Application (with new Client Secret and ID)
setting every possible callback url in the battle.net settings:
https://localhost/
http://localhost/
https://localhost:443/
http://localhost:443/
https://localhost/auth/bnet/callback
http://localhost/auth/bnet/callback
https://localhost:443/auth/bnet/callback
http://localhost:443/auth/bnet/callback
creating a token manually by "trying out the api" (https://develop.battle.net/documentation/api-reference/world-of-warcraft-community-api), where you put in your Client ID and Secret and then get a temporary Token. THAT ONE works, also in my application.
You can compare response of those two urls (just use your browser):
First (Generated in my application): https://eu.api.blizzard.com/wow/guild/Blackmoore/The%20new%20Dimension?fields=members&locale=de_DE&access_token=EU7XD8E4K9IAJKBGJSP3MDBLAVCIU2BYXS
Second (Generated trying out the API on battle.net website where you fill out clientid and secret to test out the api): https://eu.api.blizzard.com/wow/guild/Blackmoore/The%20new%20Dimension?fields=members&locale=de_DE&access_token=US23su4g0hAeS5w3EUCkKA9MJPgJ8k8bzV
CODE
server.js, simple express app
var BNET_ID = "MYID";
var BNET_SECRET = "MYSECRET";
...
// Use the BnetStrategy within Passport.
passport.use(
new BnetStrategy(
{ clientID: BNET_ID,
clientSecret: BNET_SECRET,
scope: "wow.profile sc2.profile",
callbackURL: "https://localhost/",
region: "eu" },
function(accessToken, refreshToken, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
})
);
// bnet auth routes
app.get('/auth/bnet', passport.authenticate('bnet'));
app.get('/auth/bnet/callback',
passport.authenticate('bnet', { failureRedirect: '/' }),
function(req, res){
res.redirect('/');
});
controller.js
...
const res = await fetch(`https://eu.api.blizzard.com/wow/guild/${servers[iterator]}/The new Dimension?fields=members&locale=de_DE&access_token=${thetoken}`).then((res) => {
res.json();
// for debugging, shows 401 Error
console.log(res);
});
...
I actually expect a response such as this, because it works using a temporary Token:
status: 200 OK
body: {
"lastModified": 1546676373000,
"name": "The new Dimension",
"realm": "Blackmoore",
"battlegroup": "Glutsturm / Emberstorm",
"level": 25,
"side": 0,
"achievementPoints": 1005,
"members":
(......)
}
I managed to resolve the issue!
Very, very hacky but I managed to resolve the issue by hacking the oauth callback middleware like this:
set my used API token to the req.user.token.
app.get('/auth/bnet/callback',
passport.authenticate('bnet', { failureRedirect: '/?error' }),
function(req, res) {
req.session.bnettoken = req.user.token;
res.redirect('/');
}
);
I suspect that "code" or "token" is also used in my SessionStorage (express-session) to store the current session in my database. So I just hack the user.token out of the request and use that. Phew.. Hours of work.
From the documentation I can see that you need to pass the token into the Authorization header with value of : Bearer HEREISMYTOKEN.
More info on Authorization Header and Headers here:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Headers
Example on how to use it can be found in this SO answer

Resources