Sails.js API passport.js authentication - node.js

I am trying to develop an API backend in Sails.js.
The most basic thing which I require is authentication.
With that, I found the sails-generate-auth generator, I have followed all the steps listed at
sails-generate-auth .
Now, when I access http://localhost:1337/register, I see a simple registration form, same goes for login, and after logging in, I see a cookie set in my browser as sails.sid.
After inspecting the AuthController.js I see that it has been written for server rendered views.
How should I modify the controller/sailsApp so that it supports API based authentication.
I would ideally like to have:
A register route which would accept username and password via post
with content type application/json.
Login route which would accept username and password with
content-type application/json and return with a bearer token so that the frontend app can add it to its header the next time it makes a request.
All other routes under an auth ACL which would check if the bearer
token is present and is verified.

In your AuthController callback function replace this:
res.redirect('/');
with this:
console.log(user);
var userID = user.id;
Passport.find({user: userID}, function(err, items){
if(err) return err;
console.log(items[0].accessToken);
// Make sure you dont give them any sensetive data
res.json({userData: user, token: items[0].accessToken});
});
// Upon successful login, send the user to the homepage were req.user
//res.redirect('/');
Now when the client sends a login/register request the server will response with a JSON response. Make sure you request the token on your other sails app actions.

Ive been using these steps for a while now.
Step 1 ( Globals ): $ npm install -g sails
Step 2 ( App ): $ sails new myApp
Step 3 ( Files ): Copy every file in https://github.com/carlospliego/sails-token-auth-setup to its corresponding folder
Step 4 ( Policies ): Add this code to your config/policies.js
'*': "hasToken",
UserController: {
"create": true
},
AuthController: {
'*': true
}
Step 5: change the value of config/tokenSecret.js
Step 6: ( Dependencies )
npm install --save passport
npm install --save passport-local
npm install --save bcrypt-nodejs
npm install --save jsonwebtoken
npm install --save express-jwt
Your endpoints will look like this:
POST/GET/PUT/DELETE user/
POST auth/login
DELETE auth/logout
Here is a great guide on how to create token based authentication in sails: https://github.com/carlospliego/sails-token-auth-setup

Related

Cross-site POST form submissions are forbidden

My sveltekit app has a form which sends a POST request to server. The app is working fine on dev server but when I build and run the app it fails to send the form data via POST request. It shows the following error in the browser:
Cross-site POST form submissions are forbidden
You have to set the the ORIGIN env var like this
ORIGIN=http://localhost:3000 node build/index.js
https://github.com/sveltejs/kit/tree/master/packages/adapter-node#origin-protocol_header-and-host_header
This is a built-in protection against cross-site request forgery attacks in Sveltekit. Set csrf to false in svelte.config.js to allow cross-site post requests.
See csrf in the Sveltekit configuration docs
import adapter from '#sveltejs/adapter-node'
const config = {
kit: {
adapter: adapter(),
csrf: {
checkOrigin: false,
}
},
}
export default config
This works: node -r dotenv/config build after including your new variable in .env ORIGIN=https://yourwebsite.com (please install it with npm install dotenv command as pointed out here)

Querying information about specific version of scoped npm package

I can successfully query meta information for a specific version of a specific NPM package like this:
GET https://registry.npmjs.org/<name>/<version>
for example: https://registry.npmjs.org/camelcase/2.1.1
But for scoped packages like #angular/core this doesn't work. I tried all of the following, but they all fail:
https://registry.npmjs.org/#angular/core/6.1.10 - 401 Unauthorized
https://registry.npmjs.org/#angular%2Fcore/6.1.10 - 401 Unauthorized
https://registry.npmjs.org/%40angular%2Fcore/6.1.10 - 401 Unauthorized
https://registry.npmjs.org/%40angular%2Fcore%2F6.1.10 - 404 Not Found
What is the correct way for querying a specific version of a scoped package?
You can do this from a bash command:
npm view #angular/core/6.1.10
So npm is adding some authentication to the request for scoped packages. For this to work you have to have a valid package.json in the local directory.
Of course, worst case, you can do a process.spawn() to run the npm command.
FYI, I tried using the npm-registry-client package, with my npm credentials:
var RegClient = require('npm-registry-client')
var client = new RegClient({
username: 'mememe',
password: 'xxxxx'
})
var uri = "https://registry.npmjs.org/#angular/core/6.1.10"
var params = {timeout: 1000}
client.get(uri, params, function (error, data, raw, res) {
console.log(data);
})
and I got this:
info attempt registry request try #1 at 09:52:09
http request GET https://registry.npmjs.org/#angular/core/6.1.10
http 401 https://registry.npmjs.org/#angular/core/6.1.10
WARN notice ERROR: you cannot fetch versions for scoped packages
It appears they don't allow specific version querying, but per #RobC's comments below, they do allow grabbing the entire repository's information, so you can do this client-side:
url = 'https://registry.npmjs.org/#angular%2fcore';
const fetch = require('node-fetch');
fetch(url).then(response => response.json()).then(results => {
console.log(results.versions['6.1.10']);
});

Angular 5 call api with CORS

Hello i am creating an Angular application that i need to call an API. I have run into the CORS Error. "No Access-Control-Allow-Origin" which I have found a few things on line about but I still do not understand where I am supposed to add the middlewhere. I wonder if someone could be specific on how to get this to work with angular cli.
If you open a command prompt and type ng new test then open that test folder up and type npm start. you add the code to call an api lets say localhost/someapi/api/people but because you're not calling localhost:4200 you get this error.
So just so that my question is clear, I understand that you need to add the cors middle where on the server. But the question is, where in the angular 5 app do I add this for node to read it and allow this to work?
Below is the code that I'm using to call api.
getToken():void{
let headers = new Headers({'Content-type': 'application/x-www-form-urlencoded'})
let params = new URLSearchParams();
params.append('username','some-username');
params.append('password', 'some-encripted-password');
params.append('grant_type', 'password');
let options = new RequestOptions();
options.headers = headers;
this.http
.post(this.appConfig.baseRoute + 'token',params.toString(), options)
.subscribe(result=>{ });
}
CORS headers should be set in server-side as per the answer in the link that you provided. There shouldn't be anything to set on the Angular client side other than maybe authentication tokens if you server requires them.
To ease your development locally, you could set up a proxy for ng serve.
Add this file in your root (folder with angular-cli.json)
proxy.conf.js
const PROXY_CONFIG = [
{
context: [
// what routes to proxy
"/api",
],
// your backend api server
target: "http://localhost:8000",
secure: false
}
]
module.exports = PROXY_CONFIG;
instead of calling ng serve, use ng serve --proxy-config proxy.conf.js

Download file sent in response angular2

I know it is a dumb question but can someone tell me how can I prompt the user to download a file that is sent by the backend in the response?
You have two possibilities:
If the backend sends the file directly to the browser by clicking a link then the backend should use the content type application/octet-stream in the headers. That causes the browser to ask the user how to save/open the file.
If you load the file from the backend through Angular code (Http Module) then you could use filesaver.js or a similar library. Then you have the full control and can prompt the user yourself.
npm install file-saver --save
... and the typings:
npm install #types/file-saver --save-dev
The code in the service:
public getFile(path: string):Observable<Blob>{
let options = new RequestOptions({responseType: ResponseContentType.Blob});
return this.http.get(path, options)
.map((response: Response) => <Blob>response.blob())
.catch(this.handleError);
}
For using FileSaver.js put the following import to your component:
import * as FileSaver from 'file-saver';
To trigger the download use that:
this.api.getFile("file.pdf")
.subscribe(fileData => FileSaver.saveAs(fileData, "file.pdf"));

yeoman 1.0 - make development server accept POST calls

I'm using yeoman for my application which consists of 2 parts - client site with js/html/css and the rest service.
During development I start rest service in Eclipse and start server for my static files with
grunt server
The problem is that I have to do a post request to root url '/' (it's a fake login POST request to make browsers prompt to save passwords).
It worked with yeoman 0.9 but after updating I get:
Cannot POST /
Is there a way to configure grunt server task to accept POST requests?
Thanks!
Leonti
I think you want the connect-rest middleware.
https://github.com/imrefazekas/connect-rest
npm install connect-rest --save-dev
Edit Gruntfile.js, at the top
var restSupport = require('connect-rest');
restSupport.post( { path: '/savequestion'}, function(req, content, next){
next(null, {result: 'OK'});
});
In your connect or livereload middleware section:
livereload: {
options: {
middleware: function (connect) {
return [
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app),
restSupport.rester( {'context': '/forms'} ),
rewriteRulesSnippet, // RewriteRules support
The key part is "restSupport.rester()", remove the context if you don't want it.
This simple function should just reply with the json object {result: 'OK'} to everything you post to /forms/savequestion . It should at least let you build out scaffolding in grunt server :9000 mode before you have build your templates. Without this you would have to $.get() each $.post() and then change it during or after the build.

Resources