Loopback Angular SDK Login Issue - javascript

I created a "user" named model with base class "User". I'm trying to login a user in Angular App using lb-ng generated service but it's not logging in.
In my Login controller I invoked User.login() providing email and password but its giving some weird error.
Even I included this code in my app.js
// Use a custom auth header instead of the default 'Authorization'
LoopBackResourceProvider.setAuthHeader('X-Access-Token');
// Change the URL where to access the LoopBack REST API server
LoopBackResourceProvider.setUrlBase('http://.../api');
In loginController
console.log(User.login({ email: "shah.khokhar#hotmail.com", password: "12345" }));
But it's giving this validation error:
Kindly help me on this.
Thanks,

If you could post your user.json file and your actual angular code then it would be more clear. But as far as I can see, there are things you are doing wrong.
You are making a request to User model instead of your custom user model which obviously won't work as your user data is present in your custom model and not the built in User model
You are most probably making a POST request to a wrong method than login method as login method request url looks something like this
http://localhost:3000/api/users/login
Here's a working sample code for login function which I use for my project
self.login = function () {
var data = {
email: self.email,
password: self.password
};
users.login(data).$promise
.then(function (user) {
$state.go('home');
})
.catch(function (err) {
$state.go('auth.register');
});
};
Hope this helps.

Related

Laravel + Angular - Get 401 unauthenticated on 1 GET method

I'm developing a Laravel + Angular app and i'm getting 401 Unauthorized in only 1 GET request.
Here I explain how I developed my authentication and how it work on Backend and Frontend. I wish you can help me.
I use Laravel Sanctum for manage authentication in my app. Here is how I program the backend.
I get users from my BD table:
Note: I have created a separate controller, to separate the authentication functions from the user functions, even so, I have tried to put this function in my AuthController and it has not given me any result.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class UsersController extends Controller
{
public function getAllUsers()
{
return User::all();
}
}
As I want you to only be able to retrieve all the DB users if you are authenticated, in my api.php file I put the path inside the middleware:
Route::middleware('auth:sanctum')->group(function()
{
Route::post('logout', [\App\Http\Controllers\AuthController::class, 'logout']);
Route::get('getAuthUser', [\App\Http\Controllers\AuthController::class, 'getAuthUser']);
//Admin actions
Route::post('createUser', [\App\Http\Controllers\AuthController::class, 'createUser']);
Route::get('getAllUsers', [\App\Http\Controllers\UsersController::class, 'getAllUsers']);
});
If I make the request from the Postman everything works correctly, if I am not authenticated it gives me an error and if I have previously authenticated it returns all the DB users just as I expected. By the way, I am using cookies to send the jwt to the Frontend.
The problem is when in my Angular app I request my backend with the GET method to retrieve these users and display them in a table. In addition, the code to retrieve the users is within a condition in which it is looking at whether the user is authenticated or not. The truth is that I do not understand what may be happening.
getUsers(): void
{
//Check if user is authenticated
this.http.get('http://localhost:8000/api/getAuthUser', { withCredentials: true }). subscribe(
(res: any) =>
{
Emitters.authEmitter.emit(true);
Emitters.roleEmitter.emit(res.role);
//Get all users
this.http.get('http://127.0.0.1:8000/api/getAllUsers', { withCredentials: true }). subscribe(
res =>
{
this.users = res;
}
)
},
err =>
{
Emitters.authEmitter.emit(false);
Emitters.roleEmitter.emit("none");
alert("You should be authenticated for this.");
}
);
}
The first request that you see above getAuthUser, makes the request to the Backend in the same way as the second request getAllUsers and the first one works perfectly and the second one does not, it is in which I get an err. I call the getUsers() method in the ngInit().
I hope I have explained myself well. Any information you need to know let me know. Thank you.
The solution was in the request that gave the error to change the path of the api, instead of putting 127.0.0.1 putting localhost.

Angular post request sending empty body to node.js server

I am trying to post form data from angular to node.js. The angular post request sends an empty body.
this is my post router
submit function is ts file
onSubmit( loginData ) {
if(!loginData) { return; }
this.userService.addUser( loginData as User )
.subscribe(user => {
this.users.push(user);
});
service used to post data
addUser(user: User): Observable<User> {
// console.log('this is '+user.email);
const url = `${this.usersUrl}/register`;
return this.http.post<User>(url, user).pipe(
tap((newUser: User) => this.log(`added user w/ email=${newUser.email}`)),
catchError(this.handleError<User>('addUser'))
);
}
Please check once by adding the debug whether the loginData is getting passed in the service or not.
If you don't know how to add debug point simply just print the data using console.log(user)
in the method addUser() as the first line.
And if not getting data then simply modify the method call by:
this.userService.addUser(loginData).subscribe(user => {
this.users.push(user);
});
I figured out the problem.
There is no problem in this angular code.
I also checked the network tab as suggested by David, and saw that the payload was being sent.
the problem was this line of code in my node.js server
app.use(express.static('public'))
Instead I had to use
app.use(exrpess.json())
I had copied the template from another application and somehow missed this. Anyway thanks for all your help!

How can i pass data from ReactJS submit form to AdonisJS

I have a form in ReactJS and every time i click the submit button, the data should pass to adonis api.
ReactJs file
async handleSubmit(e) {
e.preventDefault();
console.log(JSON.stringify(this.state));
await axios({
method: 'post',
url: 'http://127.0.0.1:3333/add',
data: JSON.stringify(this.state),
})
.then(function (response) {
console.log('response',response);
})
.catch(function (error) {
console.log('error',error);
});
}
"http://127.0.0.1:3333/add" is Adonis server with a route '/add'
i don't know how to write in Adonis to post state on that route
Can anybody explain me, please?
in controller's function in get value like this
const data = request.only(['data']) then you get data.
other method to get data like this
const alldata = request.all()
this console this result and view how many result you get
and get data from this alldata.data
First, create a simple controller to handle your data which would receive from your handleSubmit() method in ReactJS app.
Use the below command to create a simple controller:
adonis make:controller TestController --type http
Once created, open the TestController file and make an index method and add the followings which are inside the index method.
'use strict'
class TestController{
// define your index method here
index ({ request }) {
const body = request.post() // get all the post data;
console.log(body) //console it to see the passed data
}
}
module.exports = TestController
After that, register your /add route in start/routes.js file.
Route.post('/add', 'TestController.index') // controller name and the method
And finally, hit the Submit button in your ReactJS app, and test it.
Most likely you be getting CORS issues when you send the request
from your ReactJS app to Adonis server, If so you have to proxy the api request to Adonis server.
To do that, open up your package.json file in ReactJS App, and add the below proxy field.
"proxy": "http://127.0.0.1:3333",

Angular Auth against Laravel backend

I am creating an app using Laravel and building a small internal API to connect to with an Angular frontend.
I have the auth working, but wanted to ensure that this is an acceptable way to log in a user, and to make sure everything is secure.
Sessions Controller:
public function index() {
return Response::json(Auth::check());
}
public function create() {
if (Auth::check()) {
return Redirect::to('/admin');
}
return Redirect::to('/');
}
public function login() {
if (Auth::attempt(array('email' => Input::json('email'), 'password' => Input::json('password')))) {
return Response::json(Auth::user());
// return Redirect::to('/admin');
} else {
return Response::json(array('flash' => 'Invalid username or password'), 500);
}
}
public function logout() {
Auth::logout();
return Response::json(array('flash' => 'Logged Out!'));
}
Laravel Route:
Route::get('auth/status', 'SessionsController#index');
Angular Factory:
app.factory('Auth', [ "$http", function($http){
var Auth = {};
Auth.getAuthStatus = function() {
$http({
method: "GET",
url: "/auth/status",
headers: {"Content-Type": "application/json"}
}).success(function(data) {
if(!data) {
console.log('Unable to verify auth session');
} else if (data) {
console.log('successfully getting auth status');
console.log(data);
// return $scope.categories;
Auth.status = data;
return Auth.status;
}
});
}
return Auth;
}
]);
I would then essentially wrap the whole app in something like an "appController" and declare the 'Auth' factory as a dependency. Then I can call Auth.getAuthStatus() and hide / show things based on the user state since this will essentially be SPA.
I realize I also need to hide the /auth/status URI from being viewed / hit by anyone, and was wondering how to do that as well. Kind of a general question but any insight would be greatly appreciated. Thanks.
Great question. I've answered this same question before so I will say the same thing.
Authentication is a bit different in SPAs because you separate your Laravel app and Angular almost completely. Laravel takes care of validation, logic, data, etc.
I highly suggest you read the article linked at the bottom.
You can use Laravel's route filters to protect your routes from unauthorized users. However, since your Laravel application has now become an endpoint only, the frontend framework will be doing the heavy lifting as far as authentication and authorization.
Once you have route filters set, that doesn't prevent authorized users from attempting to do actions that they are not authorized to do.
What I mean by the above is for example:
You have an API endpoint: /api/v1/users/159/edit
The endpoint is one of the RESTful 7, and can be used to edit a user. Any software engineer or developer knows that this is a RESTful endpoint, and if authorized by your application, could send a request with data to that endpoint.
You only want the user 159 to be able to do this action, or administrators.
A solution to this is roles/groups/permissions whatever you want to call them. Set the user's permissions for your application in your Angular application and perhaps store that data in the issued token.
Read this great article (in AngularJS) on how to authenticate/authorize properly using frontend JavaScript frameworks.
Article: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

backbone.js - handling if a user is logged in or not

Firstly, should the static page that is served for the app be the login page?
Secondly, my server side code is fine (it won't give any data that the user shouldn't be able to see). But how do I make my app know that if the user is not logged in, to go back to a login form?
I use the session concept to control user login state.
I have a SessionModel and SessionCollection like this:
SessionModel = Backbone.Model.extend({
defaults: {
sessionId: "",
userName: "",
password: "",
userId: ""
},
isAuthorized: function(){
return Boolean(this.get("sessionId"));
}
});
On app start, I initialize a globally available variable, activeSession. At start this session is unauthorized and any views binding to this model instance can render accordingly. On login attempt, I first logout by invalidating the session.
logout = function(){
window.activeSession.id = "";
window.activeSession.clear();
}
This will trigger any views that listen to the activeSession and will put my mainView into login mode where it will put up a login prompt. I then get the userName and password from the user and set them on the activeSession like this:
login = function(userName, password){
window.activeSession.set(
{
userName: userName,
password: password
},{
silent:true
}
);
window.activeSession.save();
}
This will trigger an update to the server through backbone.sync. On the server, I have the session resource POST action setup so that it checks the userName and password. If valid, it fills out the user details on the session, sets a unique session id and removes the password and then sends back the result.
My backbone.sync is then setup to add the sessionId of window.activeSession to any outgoing request to the server. If the session Id is invalid on the server, it sends back an HTTP 401, which triggers a logout(), leading to the showing of the login prompt.
We're not quite done implementing this yet, so there may be errors in the logic, but basically, this is how we approach it. Also, the above code is not our actual code, as it contains a little more handling logic, but it's the gist of it.
I have a backend call that my client-side code that my static page (index.php) makes to check whether the current user is logged in. Let's say you have a backend call at api/auth/logged_in which returns HTTP status code 200 if the user is logged in or 400 otherwise (using cookie-based sessions):
appController.checkUser(function(isLoggedIn){
if(!isLoggedIn) {
window.location.hash = "login";
}
Backbone.history.start();
});
...
window.AppController = Backbone.Controller.extend({
checkUser: function(callback) {
var that = this;
$.ajax("api/auth/logged_in", {
type: "GET",
dataType: "json",
success: function() {
return callback(true);
},
error: function() {
return callback(false);
}
});
}
});
Here is a very good tutorial for it http://clintberry.com/2012/backbone-js-apps-authentication-tutorial/
I think you should not only control the html display but also control the display data. Because user can use firefox to change your javascript code.
For detail, you should give user a token after he log in and every time he or she visit your component in page such as data grid or tree or something like that, the page must fetch these data (maybe in json) from your webservice, and the webservice will check this token, if the token is incorrect or past due you shouldn't give user data instead you should give a error message. So that user can't crack your security even if he or she use firebug to change js code.
That might be help to you.
I think you should do this server sided only... There are many chances of getting it hacked unit and unless you have some sort of amazing api responding to it

Categories

Resources