I receive method options and return undefined - json

I'm writing my login form which provides for a put request to the server.
The communication protocol is JSON
I have to send username and password hashes, using CryptoJS with SHA-256 hash algorithm.
Authentication data must be stored encrypted in the browser as a cookie, and each request is sent to the server as the basis for authentication, when you close the browser window, the data must be deleted.
example put request:
PUT my api adress
{"loginRequest": {
"username": "admin",
"hash": "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"
}}
Response OK
Code: 200
{"loginResponse": {
"username": "admin",
"name": "Example Admin",
"roles": [
"USER", "ADMIN"
],
"lastLogin": "2014-02-17+01:00",
"backendVersion": "katconnect-backend-0.0.1-SNAPSHOT"
}}
Response Data Validation Error (URI username <> JSON username)
Code: 400
{"error": {
"code": "400",
"message": "the message of the error"
}}
Response Authentication Error (username or hash is null, user not found, wrong hash value)
Code: 401
{"error": {
"code": "401",
"message": "Username or password false"
}}
Here is my code:
angular.module('validationApp')
.controller('loginCtrl',function ($scope,$http,Base64,$cookieStore) {
$scope.login = function () {
var user = {
username: $scope.username,
hash: CryptoJS.SHA256($scope.password)
};
var loginRequest = JSON.stringify(user);
var credentials = Base64.encode($scope.username + ':' + $scope.password);
$http({
method: 'PUT',
url: url+'/users/'+ $scope.username +'/login',
data: loginRequest,
headers:{'Content-Type': 'application/json'}
})
.success(function (){
$http.defaults.headers.common['Authorization'] = 'Basic ' + credentials;
$cookieStore.put( authCookieKey ,credentials);
})
.error(function(code){
if (401 === code) {
$scope.invalidUsernamePassword = true;
}
})
};
})

You are doing a cross domain request to the API server. The browser first sends a options request to see if the HTTP method is allowed. Have you setup up CORS middleware from your server? If yes check if the method PUT is in whitlist.
http://better-inter.net/enabling-cors-in-angular-js/

Related

How to get access token of an account to invoke google appscript apis programatically?

I would want to get the ID token to be consumed in google appscript web app (which needs my account) in order to access the API.
My end goal is to know how can I achieve getGoogleIDTokenToInvokeAppScriptEndPoint (I have added in my sample code).
What exactly needs to be done to programatically access ID Token to invoke AppScript APIs from external service.
I am not sure how to generate the same programatically. Do I need to create a service account on my behalf?
Lets say I created a google account as abc#gmail.com, so I need to access the service account programatically for this user only and not some other service account. I then want to get the ID token and invoke my appscript services using the same.
Here's what I have already done:
Created my doPost request and deployed it like this:
Now the URL that I get can only be invoked if it has a bearer ${token}, where token is my ID token.
My question is how to possibly get this ID token programatically from an external service? I am using Node Application and I would like something like:
// External Script from where I am invoking AppScript API
const token = getGoogleIDTokenToInvokeAppScriptEndPoint();
// Now Since I got my ID Token, I could use the same
// to invoke my appScript app:
fetch(appScriptEndpoint,
{
method:"POST",
headers: {
Authorization: `Bearer ${token}` // Token I got from first step
}
}).then(res => res.json().then(data => data))
Here's how my appscript looks like (though not much relevant here, but still adding for detailing):
// AppScript Script
const doPost = (request = {}) => {
const { _, postData: { contents, type } = {} } = request;
let query = {};
if (type === 'application/json') {
query = JSON.parse(contents);
} else if (type === 'application/x-www-form-urlencoded') {
contents
.split('&')
.map((input) => input.split('='))
.forEach(([key, value]) => {
query[decodeURIComponent(key)] = decodeURIComponent(value);
});
} else if (type === 'text/plain') {
try {
query = JSON.parse(contents);
} catch (e) {
return ContentService.createTextOutput(
JSON.stringify({
error: true,
statusCode: 400,
msg: 'Unable to Parse JSON',
type: type,
requestBody: contents,
payload: {}
})
).setMimeType(ContentService.MimeType.JSON);
}
} else
return ContentService.createTextOutput(
JSON.stringify({
error: true,
statusCode: 400,
msg: 'Unknown Request Type',
type: type,
requestBody: contents,
payload: {}
})
).setMimeType(ContentService.MimeType.JSON);
const apiKey = query.apiKey;
const isAuthenticated = authenticate({apiKey});
if(!isAuthenticated) return ContentService.createTextOutput(
JSON.stringify({
error: true,
statusCode: 401,
msg: 'User not authorized to make the Request.',
type: type,
requestBody: contents,
payload: {}
})
).setMimeType(ContentService.MimeType.JSON);
else {
const {opType,opProps} = query;
const result = requestHandler({opType, opProps});
return ContentService.createTextOutput(
JSON.stringify({
error: false,
statusCode: 200,
msg: 'Connection Established',
type: type,
requestBody: contents,
payload: result
})
).setMimeType(ContentService.MimeType.JSON);
}
};
Please note that I already know how to invoke it by keeping my web app open however, I want to invoke it when authentication is required as shown in the above configuration.

How to store token in cookies in reactjs frontend on call by login post method to server

this is my login post method in the reactjs frontend
const login = () => {
Axios.post("http://localhost:3001/api/users/login", {
email: values.email,
password: values.password,
}).then((response) => {
console.log(response.data);
}).catch(err =>{
console.log(err)
})
};
this is my expressjs server side, here i have login post method for reactjs frontend, where iam on response i want to send token to set in cookie whenever user post on login method, below is code for login post method
login: (req, res) => {
const body = req.body;
console.log("req.body :", req.body);
getUserByEmail(body.email, (err, results) => {
console.log("results :", results);
if (err) {
console.log(err);
return;
}
if (!results) {
res.json({
status: "failure",
msg: "Invalid email or password",
});
}
const result = compareSync(body.password, results.password);
const SECRET_KEY = "xyz123";
if (result) {
results.password = undefined;
const jsontoken = sign({ result: results }, SECRET_KEY, {
expiresIn: "1h",
});
// console.log(res)
res.cookie("token", jsontoken, {
httpOnly: true,
domain: "http://localhost:3000/login",
});
return res.json({
status: "Success",
msg: "login Successfully",
token: jsontoken,
});
} else {
return res.json({
status: "failure",
msg: "Invalid email or password",
});
}
});
},
What you could do, that is actually more secure, is tell the browser using headers on the response to create a cookie.
There is a header in HTTP called Set-Cookie, which is responsible to do just that, you can read more about it here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie.
The way you add it to your request on express is by calling the res.cookie function on your express request handler. I would suggest telling the cookie to be httpOnly in order for it to not be accessible through JS code, this is just a way to avoid XSS attacks.
Here you have an example to how to achieve that:
res.cookie('token', jsontoken, { httpOnly: true });
Then in order to access the cookie, you would need to use the cookieParser middleware which is responsible in putting all the cookies the client sent in req.cookies.
You use it this way:
app.use(express.cookieParser());

StrongLoop Client extending User Model Built-in log in error

Has anyone experienced extending the built-in model "user" in StrongLoop via Client?
The thing is, I can't skip the verification for the newly created clients. I have declared the Client with the option "emailVerificationRequired": false, but still I can't log in.
Error:
error: Object code: "LOGIN_FAILED_EMAIL_NOT_VERIFIED" message: "login
failed as the email has not been verified" name: "Error" stack:
"Error: login failed as the email has not been verified↵ at
C:\xampp\htdocs\loopback-getting-started\node_modules\loopback\common\models\user.js:248:21↵
at
C:\xampp\htdocs\loopback-getting-started\node_modules\loopback\common\models\user.js:312:9"
status: 401 statusCode: 401
If you don't want email verification PUT below code in
model-config.json
"user": {
"dataSource": "YOUR DATASOURCE",
"public": true,
"options": {
"emailVerificationRequired": false
},
"$promise": {},
"$resolved": true}
And other thing is, you manually stop verification doing below logic.
For example if users created by Admin.
user.beforeRemote('create' ,function(ctx, modelInstance, next)
{
if(ctx.req.query.key == "admin") // if users created by Admin.
{
ctx.args.data.emailVerified = 1;
}
next();
});
IN afterRemote
user.afterRemote('create', function(context, user, next) {
if(!user.emailVerified)
{
console.log('> user.afterRemote triggered');
var options = {
type: 'email',
to: user.email,
from: 'youremail,
subject: 'Thanks for registering.',
template: path.resolve(__dirname, '../../server/views/verify.ejs'),
redirect: '/verified',
user: user
};
user.verify(options, function(err, response) {
if (err) return next(err);
context.res.render('response', {
title: 'Signed up successfully',
content: 'Please check your email and click on the verification link ' +
'before logging in.',
redirectTo: '/',
redirectToLinkText: 'Log in'
});
});
}
else
{
next();
}
});

Error Refreshing Session "JSON text did not start with array or object and option to allow fragments not set."

Trying to refresh access tokens after 60 min limit. Running a local node server. To give context, I have successfully returned the following data from a spotify authentication endpoint. Currently storing the session in NSUserdefaults, not sure if I have to store the refresh token in another location..
Swap: tokenData { access_token: 'BQAzWk7KjBMtKLzuVtpstw0XWmRww6zs2j6TxoObMRh4P-cxW6SHQqnZWeBD9bE38Xz6ZUNlFdG-EVeTtHwgoRwA9GAqaooaQP5k4gFkEVCbhLcdGVc_IZjO1JH91FmB2O-l-YHeJqC9DzUIF7wWWCGfAxk2SJ2QFNkP4Mp13PXc9IlsnHnu-B9nfZaWYDoHDf4',
token_type: 'Bearer',
expires_in: 3600,
refresh_token: 'AQDmPiRX9WGwShK9aIVybZlG1qJyv0avmgZedUwfvz0hGGo5dheMKSpteVRCIItzt_l4gIflHPnFzLrxLmZNKSserU7ng8_3sSJPhdsibdskjbdkjbdkUDrOC4ZbEGPWNcJlmZgl4A' }
When session is expired in Xcode, I trigger this function in XCode
if !session.isValid() {
SPTAuth.defaultInstance().renewSession(session, withServiceEndpointAtURL: NSURL(string: tokenRefreshServiceURL), callback: { (error:NSError!, renewedsession:SPTSession!)
Which points to this..
app.post("/refresh", function(req,res){
console.log(req.body);
if(!req.body || !req.body.hasOwnProperty("refresh_token")) {
res.status(550).send("Permission Denied");
//THE BODY DOES NOT CONTAIN THE REFRESH TOKEN
return;
}
var encryptedToken = new Buffer(req.body.refresh_token, 'base64');//switched the underscore
var refresh_token = req.body.refresh_token;
console.log("refresh: refresh_token: %s", refresh_token);
var formData = {
"grant_type": "refresh_token",
"refresh_token": refresh_token
};
console.log("refresh: POSTing request to %s:", url.resolve(config.endpoint, "/api/token"), formData);
request.post({
url: url.resolve(config.endpoint, '/api/token'),
headers: {
"Authorization": AUTH_HEADER,
"Content-Type": "application/x-www-form-urlencoded"
},
form: formData
}, function(err, response, body) {
if(err) {
console.log("refresh: error: %s", err);
res.status(550).send("Internal Server Error");
return;
}
if (response.statusCode != 200) {
console.log("refresh: response: %s", response.statusCode);
res.status(550).send("Permission Denied");
return;
}
console.log("refresh: body: %s", body);
res.status(response.statusCode).set({
"Content-Type": "application/json"
}).send(body);
});
});
Receive the following error in Xcode:
Error Refreshing Token: JSONError refreshing session Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set."}
Not sure if I have to store the refresh token somewhere? I store all sessions in NSUser defaults.

Sails passport js integration using sails as REST API

I am trying to use passport js for authentication in my local mysql database. I am using postman extension to test the application.
I am sending two fields i.e. username and password for authentication. When any one of the field is blank then response is shown in json format as
{
"message": "Missing credentials",
"user": false
}
But when I pass values for both the fields I get 500 internal server error.
error: Sending 500 ("Server Error") response:
TypeError: Cannot read property 'message' of undefined
at d:\Test\api\controllers\AuthController.js:25:23
at Strategy.strategy.error (d:\Test\node_modules\passport\lib\middleware\authenticate.js:333:18)
at Strategy.authenticate (d:\Test\node_modules\passport-local\lib\strategy.js:94:17)
at attempt (d:\Test\node_modules\passport\lib\middleware\authenticate.js:341:16)
at authenticate (d:\Test\node_modules\passport\lib\middleware\authenticate.js:342:7)
at Object.module.exports.login (d:\Test\api\controllers\AuthController.js:37:7)
at bound (C:\Users*\AppData\Roaming\npm\node_modules\sails\node_modules\lodash\dist\lodash.js:729:21)
at routeTargetFnWrapper (C:\Users*\AppData\Roaming\npm\node_modules\sails\lib\router\bind.js:179:5)
at callbacks (C:\Users*\AppData\Roaming\npm\node_modules\sails\node_modules\express\lib\router\index.js:164:37)
at param (C:\Users*\AppData\Roaming\npm\node_modules\sails\node_modules\express\lib\router\index.js:138:11)
at pass (C:\Users*\AppData\Roaming\npm\node_modules\sails\node_modules\express\lib\router\index.js:145:5)
at nextRoute (C:\Users*\AppData\Roaming\npm\node_modules\sails\node_modules\express\lib\router\index.js:100:7)
at callbacks (C:\Users*\AppData\Roaming\npm\node_modules\sails\node_modules\express\lib\router\index.js:167:11)
at C:\Users*\AppData\Roaming\npm\node_modules\sails\lib\router\bind.js:187:7
at alwaysAllow (C:\Users*\AppData\Roaming\npm\node_modules\sails\lib\hooks\policies\index.js:207:11)
at routeTargetFnWrapper (C:\Users*\AppData\Roaming\npm\node_modules\sails\lib\router\bind.js:179:5) [TypeError: Cannot read property 'message' of undefined]**
Below is my AuthController
var passport=require('passport');
login:function(req,res){
passport.authenticate('local', function(err, user, info) {
if ((err) || (!user)) {
return res.send({
message:info.message,
user: user
});
}
req.logIn(user, function(err) {
if (err) res.send(err);
return res.send({
message:"User Loged In",//info.message,
user: user
});
});
})(req, res);
}
};
I am using the below model for testing
module.exports = {
tableName: 'users',
connection:'TestDB',
autoCreatedAt:false,
autoUpdatedAt:false,
attributes: {
username:{
type:'string',
required:true
},
password:{
type:'string',
required:true
},
toJSON: function() {
var obj = this.toObject();
delete obj.password;
return obj;
}
}
};
The table which contains the username and password also has other fields like country. Is there any way I can authenticate it using passport.
did you do the sixth step of this link
module.exports.http = {
middleware: {
passportInit : require('passport').initialize(),
passportSession : require('passport').session(),
order: [
'startRequestTimer',
'cookieParser',
'session',
'passportInit',
'passportSession',
'myRequestLogger',
'bodyParser',
'handleBodyParserError',
'compress',
'methodOverride',
'poweredBy',
'router',
'www',
'favicon',
'404',
'500'
],
}
};
maybe you want to see sails-hook-sanpassport, is easy and fast