I am trying to make User Authentication with Angular and ASP.NET Core.
I am following the tutorial found here:
https://fullstackmark.com/post/10/user-authentication-with-angular-and-asp-net-core
I followed all the steps with no errors.
The app runs, but when I go to "/register" or "/login" routes, I get
NodeInvocationException: Uncaught (in promise): ReferenceError: localStorage is not defined
ReferenceError: localStorage is not defined
the service that uses it is:
import { Injectable, Inject } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { UserRegistration } from '../shared/models/user.registration.interface';
import { ConfigService } from '../shared/utils/config.service';
import { BaseService } from "./base.service";
import { Observable } from 'rxjs/Rx';
import { BehaviorSubject } from 'rxjs/Rx';
//import * as _ from 'lodash';
// Add the RxJS Observable operators we need in this app.
import '../rxjs-operators';
@Injectable()
export class UserService extends BaseService {
baseUrl: string = '';
// Observable navItem source
private _authNavStatusSource = new BehaviorSubject<boolean>(false);
// Observable navItem stream
authNavStatus$ = this._authNavStatusSource.asObservable();
private loggedIn = false;
constructor(private http: Http, private configService: ConfigService) {
super();
this.loggedIn = !!localStorage.getItem('auth_token');
// ?? not sure if this the best way to broadcast the status but seems to resolve issue on page refresh where auth status is lost in
// header component resulting in authed user nav links disappearing despite the fact user is still logged in
this._authNavStatusSource.next(this.loggedIn);
this.baseUrl = configService.getApiURI();
}
register(email: string, password: string, firstName: string, lastName: string,location: string): Observable<UserRegistration> {
let body = JSON.stringify({ email, password, firstName, lastName,location });
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.baseUrl + "/accounts", body, options)
.map(res => true)
.catch(this.handleError);
}
login(userName: any, password: any) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http
.post(
this.baseUrl + '/login',
JSON.stringify({ userName, password }),{ headers }
)
.map(res => res.json())
.map(res => {
localStorage.setItem('auth_token', res.auth_token);
this.loggedIn = true;
this._authNavStatusSource.next(true);
return true;
})
.catch(this.handleError);
}
logout() {
localStorage.removeItem('auth_token');
this.loggedIn = false;
this._authNavStatusSource.next(false);
}
isLoggedIn() {
return this.loggedIn;
}
}
the register ts is:
import { Component, OnInit, Inject } from '@angular/core';
import { Router } from '@angular/router';
import { UserRegistration } from '../../shared/models/user.registration.interface';
import { UserService } from "../../services/user.service";
declare var localStorage: any;
@Component({
selector: 'app-registration-form',
templateUrl: './registration-form.component.html'
})
export class RegistrationFormComponent implements OnInit {
errors: string;
isRequesting: boolean;
submitted: boolean = false;
constructor(private userService: UserService, private router: Router) {
}
ngOnInit() {
}
registerUser({ value, valid }: { value: UserRegistration, valid: boolean }) {
this.submitted = true;
this.isRequesting = true;
this.errors='';
if(valid)
{
this.userService.register(value.email,value.password,value.firstName,value.lastName,value.location)
.finally(() => this.isRequesting = false)
.subscribe(
result => {if(result){
this.router.navigate(['/login'],{queryParams: {brandNew: true,email:value.email}});
}},
errors => this.errors = errors);
}
}
}
the login is:
import { Subscription } from 'rxjs';
import { Component, OnInit,OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Credentials } from '../../shared/models/credentials.interface';
import { UserService } from '../../services/user.service';
@Component({
selector: 'app-login-form',
templateUrl: './login-form.component.html'
})
export class LoginFormComponent implements OnInit, OnDestroy {
private subscription: Subscription;
brandNew: boolean;
errors: string;
isRequesting: boolean;
submitted: boolean = false;
credentials: Credentials = { email: '', password: '' };
constructor(private userService: UserService, private router: Router,private activatedRoute: ActivatedRoute) { }
ngOnInit() {
// subscribe to router event
this.subscription = this.activatedRoute.queryParams.subscribe(
(param: any) => {
this.brandNew = param['brandNew'];
this.credentials.email = param['email'];
});
}
ngOnDestroy() {
// prevent memory leak by unsubscribing
this.subscription.unsubscribe();
}
login({ value, valid }: { value: Credentials, valid: boolean }) {
this.submitted = true;
this.isRequesting = true;
this.errors='';
if (valid) {
this.userService.login(value.email, value.password)
.finally(() => this.isRequesting = false)
.subscribe(
result => {
if (result) {
this.router.navigate(['/home']);
}
},
error => this.errors = error);
}
}
}
I tried the solution from:
localStorage is not defined (Angular Universal)
but it does not work...
What am I missing
If you're used to working with client-only applications, it may come as a surprise that you can't access localStorage from the server. This is because localStorage is not defined on the window object, and Next. js performs a server render before the client render.
What is localStorage in JavaScript? localStorage is a property that allows JavaScript sites and apps to save key-value pairs in a web browser with no expiration date. This means the data stored in the browser will persist even after the browser window is closed.
You cannot save to localStorage on Node. js, but you can do it on a browser, possibly after sending from a server, for your case from a server on Node. js. You should send the token from the server (running on Node.
You can use standard API for localstorage, like
localStorage.setItem(key, val)
and
localStorage.getItem(key)
but If you want a angular solution for this and find a good library for localstorage, one I'm using is this
https://github.com/marcj/angular2-localstorage
also
https://www.npmjs.com/package/angular2-cool-storage
is cool to use.
The standard localStorage API should be available.
No need to declare it.
to set
localStorage.setItem('name', 'storingSomething');
to get
localStorage.getItem('name');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With