How to handle the Internal server error? Nestjs - javascript

How to handle the error so that if the user does not provide a token, then an UnauthorizedException is thrown.
At the moment I am getting this error:
{
"statusCode": 500,
"message": "Internal server error"
}
ts:
canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest();
try {
const jwt = request.headers.authorization.split(' ')[1];
if (!jwt) {
throw new UnauthorizedException('Token is not provided.');
}
return this.jwtService.verify(jwt);
} catch (e) {
return false;
}
}

You can try to recreate auth module from the documentation.
Or try to console.log() on each line.
By default, JWT internal module works well. It can encode and decode all that you need automatically.
https://docs.nestjs.com/security/authentication

I use a middleware for this purpose. I'll share a basic version of it.
auth-middleware.ts
import {HttpStatus,Injectable,Logger,LoggerService,NestMiddleware,} from '#nestjs/common';
import { NextFunction } from 'express';
import { Request, Response } from 'express';
#Injectable()
export class AuthMiddleware implements NestMiddleware {
constructor(
private readonly authenticationService: AuthService,
// (I use Firebase auth. You can inject JWT service here instead)
private readonly logger: LoggerService, // Good'ol logger
) {}
public async use(req: Request, res: Response, next: NextFunction) {
// Checks if req has authorization header
const header = req.headers['authorization'];
if (!header) {
// If no headers are present, returns a 401.
// I use problem+json
// Thats why you are seeing more fields in the response instead of just a
// code and message
return res
.status(HttpStatus.UNAUTHORIZED)
.json({
title: 'Unauthorized',
detail: 'Invalid Token',
type: 'https://app-site.com/login',
status: HttpStatus.UNAUTHORIZED,
instance: 'login/null',
})
.setHeader('Content-Type', 'application/problem+json');
}
// Splitting "Bearer token" to ["Bearer","token"]
const token = header.split(' ')[1];
// Validating token with auth service
// It returns a "tuple" for me...you can have it return whatever you want
const [
authClaims, // Custom claims that is extracted from the JWT
result, // JWT Validation result (boolean)
authProviderUid, // Firebase UID
] = await this.authenticationService.verifyToken(token);
if (
!result || // If JWT is invalid
authClaims.accountStatus === AccountStatusList.Banned ||
authClaims.accountStatus === AccountStatusList.Suspended
) {
// You shall not pass
return res
.status(HttpStatus.UNAUTHORIZED)
.json({
title: 'Unauthorized',
detail: 'Invalid Token',
type: 'https://app-site.com/login',
status: HttpStatus.UNAUTHORIZED,
instance: 'login/null',
})
.setHeader('Content-Type', 'application/problem+json');
}
// Attaches the claims, result and UID with req for the next middleware(s)/controller
req['authResult'] = { authClaims, result, authProviderUid };
//Reassuring
this.logger.log('Token verified', AuthMiddleware.name);
// next function from express
next();
}
}
Next, In the module(s) your controllers are declared,
api.module.ts
import { MiddlewareConsumer, Module, NestModule, RequestMethod, } from '#nestjs/common';
#Module({
imports: [
//...
],
controllers: [
AuthController,
ProfileController,
SubscriptionController
],
providers: [
//...
],
})
export class ApiModule implements NestModule {
public async configure(consumer: MiddlewareConsumer) {
consumer
.apply(AuthMiddleware)
// Exclude some paths
.exclude({ path: '/api/v1/auth/sign-up', method: RequestMethod.POST })
.forRoutes( // Your controller classes you want to run the middleware on
ProfileController,
SubscriptionController,
AuthController
);
}
}
How it works
Every request goes through the specified middleware (if path not excluded). If the request is unauthorized, throws an error before it reaches the controller.
If the request is at the controller, the request is authenticated. You have to take care of the authorization part with guards etc...
Authentication and Authorization are different.
I'd suggest to use middleware for authentication and guards for authorization.
Links :
NestJS Middleware Documentation
Problem Details

Related

Error: This is caused by either a bug in Node.js or incorrect usage of Node.js internals

I was creating authentication mechanism for my service. And at some moment I had problem with cookies. More you can find here, so I solved this.
The problem was that I was trying to send cookie through 2 requests. My Next.js front-end sends request to its internal API, and only then, internal API sends this request to back-end.
The solution of this problem was very easy, what I had to do - is to set cookie on back-end and return it in headers. Here is how flow looks, like.
This is how it looks like, endpoint in Next.js front-end. Except of data in response, it receives header, where cookie is set (response from back-end) and send it in header of response, that will be send on front-end, where cookie will be set:
import { NextApiRequest, NextApiResponse } from "next";
import { AxiosError } from "axios";
import { api } from "../../../api";
export default async (
req: NextApiRequest,
res: NextApiResponse
) => {
try {
const { data, headers } = await api.post('/user/sign-in', req.body)
if (headers["set-cookie"]) {
res.setHeader("Set-Cookie", headers["set-cookie"]);
}
return res.json(data)
} catch (error) {
return res
.status((error as AxiosError).response?.status as number)
.json((error as AxiosError).response?.data);
}
}
And endpoint on back-end:
import { Response as Res } from 'express';
import * as dayjs from 'dayjs';
...
async signIn(#Body() signInUserDto: SignInUserDto, #Response() res: Res) {
const { _at, _rt } = await this.userService.signIn(signInUserDto);
res.cookie('_rt', _rt, {
httpOnly: true,
expires: dayjs().add(7, 'days').toDate()
});
return res.send(_at);
}
And here is the problem, because of this Response class of express I keep getting this warning:
Error: This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
Please open an issue with this stack trace at https://github.com/nodejs/node/issues
at new NodeError (node:internal/errors:371:5)
at assert (node:internal/assert:14:11)
at ServerResponse.detachSocket (node:_http_server:249:3)
at resOnFinish (node:_http_server:819:7)
at ServerResponse.emit (node:events:390:28)
at onFinish (node:_http_outgoing:830:10)
at callback (node:internal/streams/writable:552:21)
at afterWrite (node:internal/streams/writable:497:5)
at afterWriteTick (node:internal/streams/writable:484:10)
at processTicksAndRejections (node:internal/process/task_queues:82:21)
It is definitely because of how this signIn function looks like, because I was trying to return just like this - return this.userService.signIn(signInUserDto) - and it worked, but I can't cookie in this case.
So, my question is - what is this error? Can I just ignore it? If not, then how can I fix it?
Thanks in advance!
TL;DR
Finally, I was able to fix this error, first of all, as I said, my goes through 2 API's, from back-end to front-end API, and only then, this front-end API sends this request to actual front-end.
So, what I did, is just returned 2 tokens - refresh and access - as body.
#ApiOperation({ summary: 'Resource for sign in user.' })
#ApiResponse({ status: 200, type: TokensDto })
#Post('/sign-in')
async signIn(#Body() signInUserDto: SignInUserDto) {
return this.userService.signIn(signInUserDto);
}
Then, on front-end, I installed cookie and #types/cookie and in this front-end endpoint, in headers, I just serialized this refresh token from body payload, and removed from it.
import { NextApiRequest, NextApiResponse } from "next";
import { AxiosError } from "axios";
import { api } from "../../../api";
import { serialize } from 'cookie';
export default async (
req: NextApiRequest,
res: NextApiResponse
) => {
try {
const { data } = await api.post('/user/sign-in', req.body)
res.setHeader('Set-Cookie', serialize(
'_rt',
data._rt,
{ path: '/', httpOnly: true })
);
delete data._rt
return res.json(data)
} catch (error) {
return res
.status((error as AxiosError).response?.status as number)
.json((error as AxiosError).response?.data);
}
}
And it works perfectly fine, I don't have this Node.js error any more because of response with Express response class, and I'm able to set cookie.
EDIT
I have improved this code in even better way by using fastify and in the whole pipeline cookie is set in header. First of all, on back-end install #fastify/cookie and #nestjs/platform-fastify. Then, add this in file, where you start you Nest.js app:
import {
FastifyAdapter,
NestFastifyApplication
} from '#nestjs/platform-fastify';
import { fastifyCookie } from '#fastify/cookie';
async function bootstrap() {
const PORT = process.env.PORT || 3002;
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter()
);
await app.register(fastifyCookie, {
secret: 'my-secret'
});
This will allow you to use FastifyReply from fastify, this will eliminate this Node.js error as response class:
import { FastifyReply } from 'fastify';
#ApiTags('User')
#Controller('user')
export class UserController {
constructor(private userService: UserService) {}
#Post('/sign-in')
async signIn(
#Body() signInUserDto: SignInUserDto,
#Res({ passthrough: true }) res: FastifyReply
) {
const { _at, _rt } = await this.userService.signIn(signInUserDto);
res.setCookie('_rt', _rt);
return res.send(_at);
}
...
And the last step, on front-end endpoint, using cookie, parse this cookie and send it to front.
const { data, headers } = await api.post('/user/sign-in', req.body)
if (headers["set-cookie"]) {
const refreshToken = headers["set-cookie"][0].split('=')[1];
res.setHeader('Set-Cookie', serialize(
'_rt', refreshToken, { path: '/', httpOnly: true })
);
}
return res.json(data)
And this is the best way, that I've found, because it allows you to send cookie in header though all pipeline, not in body and then delete it, and this solution eliminates this strange Node.js error.

How do I bubble up a non asynchronous error

I'm trying to bubble up an error that comes from the verify function in jsonwebtoken, however, it wraps it in another Internal 500 Status error, rather than an Unauthorized error, that I want it to be.
Most of the components are built in loopback-next authentication components. The class below is a provider for a class called AuthenticationStrategy. AuthenticationStrategy is just a class with a passport strategy that returns an Authentication Strategy, which is passed on the metadata of a route. In the class below (the provider of type Authentication strategy, value() is the function returned when calling the provider. The passport strategy verification function has to first be converted to an Authentication strategy first, then returned through the value function to the Provider. When value() is called, the verify function runs on the metadata of the route, in this case, the bearer token. The Function cb below is the same as the 'done' function in a normal passport strategy, and returns (error, object), respectively
import {AuthenticateErrorKeys} from '../error-keys';
import {RevokedTokenRepository, UserRepository} from '../../../repositories';
import {repository} from '#loopback/repository';
import {Strategy} from 'passport-http-bearer'
import {HttpErrors} from '#loopback/rest';
import {StrategyAdapter} from '#loopback/authentication-passport'
import {AuthenticationStrategy} from '#loopback/authentication'
import {inject, Provider} from '#loopback/context'
var verify = require('jsonwebtoken').verify
export const BEARER_AUTH_STRATEGY = 'bearer';
export class PassportBearerAuthProvider implements Provider<AuthenticationStrategy> {
constructor(
#repository(RevokedTokenRepository)
public revokedTokenRepository: RevokedTokenRepository,
#repository(UserRepository)
public userRepository: UserRepository,
){}
value(): AuthenticationStrategy {
const bearerStrategy = new Strategy(this.verify.bind(this));
return this.convertToAuthStrategy(bearerStrategy);
}
async verify (token: string, cb: Function){
try{
if (token && (await this.revokedTokenRepository.get(token))) {
throw new HttpErrors.Unauthorized(AuthenticateErrorKeys.TokenRevoked);
}
const userAuthToken = await verify(token, process.env.JWT_SECRET as string, {
issuer: process.env.JWT_ISSUER,
})
let authUser = await this.userRepository.getAuthUser(userAuthToken.id)
return cb(null, authUser)
}
catch(error) {
if (error.name && error.name === "JsonWebTokenError") {
return cb(new HttpErrors.Unauthorized(AuthenticateErrorKeys.TokenInvalid), null)
}
if (error.name && error.name === "TokenExpiredError") {
return cb(new HttpErrors.Unauthorized(AuthenticateErrorKeys.TokenExpired), null)
}
if (error.code && error.code === "ENTITY_NOT_FOUND") {
return cb(new HttpErrors.Unauthorized(`${AuthenticateErrorKeys.UserDoesNotExist}, id: ${error.entityId}`), null)
}
return cb(error, null)
}
}
// Applies the `StrategyAdapter` to the configured basic strategy instance.
// You'd better define your strategy name as a constant, like
// `const AUTH_STRATEGY_NAME = 'basic'`
// You will need to decorate the APIs later with the same name
convertToAuthStrategy(bearer: Strategy): AuthenticationStrategy {
return new StrategyAdapter(bearer,BEARER_AUTH_STRATEGY);
}
}
The sequence below is run every time someone makes an API request. If above the route, the route is decorated with #authenticate[BEARER_AUTH_TOKEN], the provider above is called, and the verify function is run on the metadata.
export class MySequence implements SequenceHandler {
constructor(
#inject(SequenceActions.FIND_ROUTE) protected findRoute: FindRoute,
#inject(SequenceActions.PARSE_PARAMS) protected parseParams: ParseParams,
#inject(SequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod,
#inject(SequenceActions.SEND) public send: Send,
#inject(SequenceActions.REJECT) public reject: Reject,
#inject(AuthorizationBindings.AUTHORIZE_ACTION)
protected checkAuthorisation: AuthorizeFn,
#inject(AuthenticationBindings.AUTH_ACTION)
protected authenticateRequest: AuthenticateFn,
) {}
async handle(context: RequestContext) {
try {
const {request, response} = context;
const route = this.findRoute(request);
const args = await this.parseParams(request, route)
const authUser = await this.authenticateRequest(request).catch(error => {
Object.assign(error, {statusCode: 401, name: "NotAllowedAccess", message: (error.message && error.message.message)? error.message.message: "Unable to Authenticate User" });
throw error
})
console.log(authUser)
const isAccessAllowed: boolean = await this.checkAuthorisation(
authUser && authUser.permissions,
request,
);
if (!isAccessAllowed) {
throw new HttpErrors.Forbidden(AuthorizeErrorKeys.NotAllowedAccess);
}
const result = await this.invoke(route, args);
this.send(response, result);
} catch (error) {
this.reject(context, error);
}
}
}
But when it catches the error, the status is 500 and the 401 Unauthorized error is wrapped in the Internal Status error. How can I instead return the 401 error?
I have a lot more cases like this where the error is deeper, so I'm trying to have a rigorous implementation.

Show login modal on unauthorized response angular 7

I need to show a login modal every time the server returns a http unauthorized status (401), and in that case, stop the page loading... for example, I'm logged in but trying to access an protected resource that only admin users can do it.. so in that case I would like to show an modal with login and password to the user. It could be on navigating to a protected route or on delete event for example.
I tried to do it in an ApiInterceptor:
#Injectable({providedIn: 'root'})
export class ApiInterceptor implements HttpInterceptor {
constructor(
...
) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
req = req.clone({ url: environment.baseUrl + req.url });
if (this.authService.validToken) {
req = req.clone({ headers: req.headers.set('Authorization', `Bearer ${this.authService.validToken}`) });
}
if (!req.headers.has('Content-Type')) {
req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
}
return next.handle(req).pipe(catchError(resp => this.handleError(resp)));
}
private handleError(httpError: HttpErrorResponse) {
if (httpError.status === this.UNAUTHORIZED) {
// opening login modal here, but can't stop the request to prevent user to se unauthorized data, and after login, how can I redirect user to the same resource he tried to access?
}
return throwError(httpError);
}
}
Need help here, if someone have an idea in how to do it will be appreciated!
Your ApiInterceptor looks like it's for adding a bearer token to the request. I'd call this the TokenInterceptor or similar, and create a new one for handling unauthorised requests.
I'd create a new interceptor and call this UnauthorisedRequestInterceptor. Something similar to this:
#Injectable({ providedIn: 'root' })
export class UnauthorisedRequestInterceptor implements HttpInterceptor {
constructor(private router: Router) { }
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
map(event => {
return event;
}),
catchError((error: HttpErrorResponse) => {
if (error.status === 401) {
this.router.navigate(['/auth/login']);
}
return throwError(error);
})
);
}
}
This will intercept every http request, and if the returned status is 401, it will redirect you to your login page.
Then add this into your list of providers in app.module.ts:
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: UnauthorisedRequestInterceptor,
multi: true
}
]
As for redirecting users on access to a protected route, this should be done in your auth guard.
Every protected data that need roles or permissions should be on the server & have specific authorization to access it, if there is already protected data on your application you should consider moving it onto your server or add at least a guard.
If you want to redirect the user after a 401 you have to inject the Router service in your interceptor & use the navigate function (cf this.router.navigate(['/myRoute']); )

Angular2 Http Call not firing

Context :
Following several tutorials, I am testing authentication with Angular2 and JWT. I come with a component and a service :
app.component.ts
user.service.ts
App component (and template) contains the subscription to an observable that shows the user logged in status. The Observable item is kept in the user service, and changes (fine) when user logs in and out.
The authentication token is written in "localStorage" as "auth_token". It contains a validity value (time) that should force the user to login again after a time.
What I'd like to do is to CHECK the token validity on app init. First, I tried to do it from the user.service CONSTRUCTOR, then (fail), I tried to do it from ngOnInit in the app.component, then (fail again), I tried to do it on event call (click on a button) from the app component, but fails again!
Some shortened code :
//app.component.html
//...
<a md-button class="app-icon-button" aria-label="checklogin" (click)="checkLogin()">
<md-icon svgIcon="check"></md-icon>
</a>
//...
//app.component.ts
//...
checkLogin(){
console.log('CHECK LOGIN FUNCTION');
let token = localStorage.getItem('auth_token');
if(token){
console.log('TOKEN FOUND');
this.userService.checkToken(token);
}else{
console.log('NO TOKEN FOUND');
}
}
//...
//user.service.ts
//...
checkToken(token){
console.log('CHECK TOKEN FUNCTION');
console.log('TOKEN : '+token);
let headers = new Headers();
headers.append('Content-Type','application/json');
return this.http
.post(
'/url/script.php',
JSON.stringify(token),
{ headers }
)
.map(res => res.json())
.map((res) => {
console.log('SCRIPT RESULT : ');
if(res.valid){
console.log('TOKEN IS VALID');
return true;
}else{
console.log('TOKEN NOT VALID');
return false;
}
});
}
//...
I did skip the observable part, and subscription.
Problem :
The problem actually is that the app NEVER CALLS the script!
When I do click on the "checkLogin" button (when token exists),
console shows 'CHECK LOGIN FUNCTION',
console shows 'TOKEN FOUND',
console shows 'CHECK TOKEN FUNCTION',
console shows 'TOKEN : '****************************** (token),
But it never shows 'SCRIPT RESULT',
and when using firebug to check if the http call is done, there is NO CALL to the script.php. Looks like the this.http part is just ignored...
Thanks for reading/help
Service starts working when subscription used only when consumer subscribe to output result, using .subscribe method.
You need: this.userService.checkToken(token).subscribe()
Your checkToken() method is returning an Observable that you need to subsrcibe to. An observable will never to execute unless it's subscribed to.
checkLogin(){
console.log('CHECK LOGIN FUNCTION');
let token = localStorage.getItem('auth_token');
if(token){
console.log('TOKEN FOUND');
this.userService.checkToken(token).subscribe(result => {
console.log(result);
}),
error => {
console.log(error);
});
} else {
console.log('NO TOKEN FOUND');
}
}
Ajax call's which use Observables will work only if you have an subscriber.
So you need to subscribe to that Observable. It is an Angular 2 feature. When you don't subscribe the Observable, it will never make that call.
And also you don't need to return anything from the subscriber, because you actually can't return anything.
this.userService.checkToken(token).subscribe((res) => {
console.log('SCRIPT RESULT : ');
if(res.valid) {
console.log('TOKEN IS VALID');
} else {
console.log('TOKEN NOT VALID');
}
});
checkToken(token){
console.log('CHECK TOKEN FUNCTION');
console.log('TOKEN : '+token);
let headers = new Headers();
headers.append('Content-Type','application/json');
return this.http
.post(
'/url/script.php',
JSON.stringify(token),
{ headers }
)
.map(res => res.json());
}
Have You tried using Postman and try to call function you need?
Also, why do You need to validate a token if angular2-jwt can do this for You?
You can do just like this:
install angular2-jwt with npm.
Include in app.module.ts:
import { AUTH_PROVIDERS } from 'angular2-jwt';
add to providers:
providers: [
AUTH_PROVIDERS,
],
and for example auth.service.ts looks like this:
import { Injectable, Inject } from '#angular/core';
import { Http, Response, Headers, RequestOptions, RequestMethod } from '#angular/http';
import { Router } from '#angular/router';
import { Observable } from 'rxjs/Observable';
import { Configuration } from '../../app.config';
import { RegisterViewModel } from '../../model/viewModel/registerViewModel';
import { LoginViewModel } from '../../model/viewModel/loginViewModel';
import { tokenNotExpired, AuthHttp } from 'angular2-jwt';
#Injectable()
export class AuthService {
private actionUrl: string;
constructor(private _http: Http, private _config: Configuration, private _router: Router, private _authHttp: AuthHttp){
this.actionUrl = _config.apiUrl;
}
register(user: RegisterViewModel){
let headers = new Headers({ 'Content-Type': 'application/json' });
//Admin in this system can only register users. that is why auth
return this._authHttp.post(this.actionUrl + '/Account/Register', JSON.stringify(user), { headers : headers })
.do(response => {
console.log(response.toString());
});
}
login(user: LoginViewModel) {
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
return this._http.post('http://localhost:56181/api/token', "username=" + user.userName + "&password=" + user.password + "&userId=" + user.userId, { headers : headers })
.do(response => {
if(response){
let authResult = response.json();
this.setUser(authResult);
this._router.navigate(['']);
}
});
}
public isAuthenticated(): boolean {
//angular2-jwt has this function to check if token is valid
return tokenNotExpired();
}
private setUser(authResult: any): void {
localStorage.setItem('id_token', authResult.id_token);
}
public logout(): void {
localStorage.removeItem('id_token');
this._router.navigate(['']);
}
}
also remember that angular2-jwt has default name for token in localstorage as id_token or else you will have to use angular2-jwt help class to specify other token name.
You can check if it is working by simply doing this:
in app.component.ts:
export class AppComponent {
constructor(private _auth: AuthService){
}
}
and in app.component.html:
<li>
<a class="nav-link" [routerLink]="['/login']" *ngIf="!_auth.isAuthenticated()">Login</a>
</li>
<li>
<a class="nav-link" (click)="_auth.logout()" *ngIf="_auth.isAuthenticated()">Log Out</a>
</li>
also You can read a little bit documentation about it in:
https://auth0.com/blog/introducing-angular2-jwt-a-library-for-angular2-authentication/

Angular 2 Facebook Authentication

I´m triying to implement facebook authenticathion from my angular 2 app but I think I'm implenting in the wrong way and I can't find some tutorials about this and also I want to ask if ¿is Auth0 the only way to implement this?.
Well I have this:
Node JS server :
// FB authentication
authRoutes.get('/facebook', passport.authenticate('facebook', { session : false, scope: ['email'] }))
authRoutes.get('/facebook/callback', passport.authenticate('facebook', { session : false, failureRedirect: '/'}), ctrlAuthentication.facebookResponse)
these are the routes in the api and I'm using passportjs, all works when I call the api directly in the browser like: localhost:3000/api/auth/facebook and I get the user returned from the api in JSON format.
Now in the front I have angular 2 and this is
authentication.service.ts:
import {User} from '../_models/user'
#Injectable()
export class AuthenticationService {
public token : String;
public user : User;
constructor(private http: Http){
}
fbLogin() : Observable<User> {
let user = this.http.get('/api/auth/facebook')
.map(this.mapUser);
return user;
}
mapUser(response : Response) : User {
console.log(response)
let data = response.json();
this.token = data.token;
let user = <User>(data.user);
this.user = user;
localStorage.setItem('currentUser', JSON.stringify({ user: user, token: data.token }));
return user;
}
}
and this is the register.component.ts:
import {AuthenticationService} from '../_services/authentication.service'
import {User} from '../_models/user'
#Component({
selector: 'crowd-register',
templateUrl: 'app/RegisterComponent/register.component.html'
})
export class RegisterComponent {
private user : User;
constructor(
private authenticationService : AuthenticationService
) {}
fbLogin() {
this.authenticationService.fbLogin().subscribe(
user => {
this.user = user;
}
)
}
}
When I call fbLogin() from the app I get this error:
SyntaxError: Unexpected token < in JSON at position 0
MapSubscriber.AuthenticationService.mapUser [as project] (authentication.service.ts:46)
I think this is because I'm don't getting the user from my api, I'm getting the response from facebook and this isn't executing or something.
This is the picture of the console.log(response) and the error.
Thanks for all answers, sorry for my english.

Categories

Resources