Προς το περιεχόμενο

Δε μπορω να παρω cookies απο middleware σε node/angular


slevinkelevra

Προτεινόμενες αναρτήσεις

Καλησπερα

Χρησιμοποιω nodejs, express, cookie-parser and angular 6. Η angular τρεχει στο  http://localhost:4200 και το node/express στο http://localhost:3000. Επισης εχω βαλει 

const cookieParser = require('cookie-parser');
const cors = require('cors');

app = express();

app.use(cors());
app.use(cookieParser());

στο app.js του node, για να μιλανε μεταξυ τους η angular  και ο node και για τα cookies.

 

Στο Login route φτιαχνω ενα http-only cookie που θα περιεχει ενα jw token, μετα απο ενα επιτυχες Login. Επισης στελνω στον client ενα json με διαφορα

res.cookie("SESSIONID", token, {httpOnly:true, secure:true}); 
res.json({ success:true, msg:'you are logged in', userid: resolved.id});

Τωρα, υποτιθεται οτι το cookie μπαινει απο μονο του σε καθε επομενο request, οποτε δε χρειαζεται να το βαλω εγω πριν οποιοδηποτε request προς τον server.

 

Εχω ενα middleware για να τσεκαρει το token , οποτε κανω

const cookieParser = require('cookie-parser'); //pano stin apelpisia
const token = req.cookies.SESSIONID; 
console.log('token from validate : ', token); 
//check token and expiration, either next(); or redirect back

στα routes που θελω να προστατεψω βαζω

router.get('cms/account', myMiddleware.required(), (req, res)=>{
   res.json({ msg:'profile data'}); 
});

Το angular profile service επικοινωνει με το account route του node

import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { map } from "rxjs/operators";

@Injectable({
  providedIn: 'root'
})
export class ProfileService {

  constructor(private http:Http) { }
  getProfile(){    
    return this.http.get('http://localhost:3000/cms/account').pipe(map(res => res.json()));
  }
}

και το angular profile component τυπωνει καποια profile data

import { Component, OnInit } from '@angular/core';
import { ProfileService } from '../../services/profile.service';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {

  constructor(    private profileService: ProfileService) { }

  ngOnInit() {
    this.profileService.getProfile().subscribe((data) =>{
      console.log('profileService -- ', data);
    })

  }
}

Τελεια. Παω στο 

http://localhost:4200/cms/login

κανω login, με φορμα κανονικα και με angular service/component, κανενα λαθος πουθενα. Μου στελνει και τη json πισω, παιρνω το user id και το βαζω localStorage, ολα καλα.
Παω στο 

http://localhost:4200/cms/profile

και το SESSIONID cookie που φτιαχνω κατα το Login δεν ειναι εκει. 

Τουλαχιστον ξερω οτι η angular φτανει επιτυχως μεχρι το middleware. 

Αλλα ομως το 

console.log('token from validate : ', token); 

απο το middleware μου δινει undefined. Επισης 

console.log('req.cookies : ', req.cookies); console.log('req.signedCookies : ', req.signedCookies); 

δινουν πισω απλα {}

δοκιμασα και να φτιαξω και ενα πιο απλο cookie ως 

res.cookie("SESSIONID", token, {httpOnly:false, secure:false});

τα ιδια. 

Τι μπορει να φταει? Δεν οριζετε εξ αρχης το cookie? Εχω λαθος καπου στη συνταξη μου? Μηπως επειδη η angular τρεχει στον δικο της σερβερ και σε αλλη θυρα και ο node τρεχει σε αλλη θυρα? Υποτιθεται ομως οτι ειναι στο ιδιο root domain επειδη και τα 2 ειναι στο localhost. Τι,οχι ? 

 

Ευχαριστω

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Με μια πρόχειρη ματιά, νομίζω σου λείπει ένας interceptor / http decorator που θα βάζει το header που θες σε κάθε request.

 

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
 
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        let user = // pairneis ton user apo localstorage i opou iparxei, px JSON.parse('...')
        if (user && user.token) { // i opou allou kaneis store to token
            request = request.clone({
                setHeaders: { 
                    Authorization: `Bearer ${user.token}`
                }
            });
        }
 
        return next.handle(request);
    }
}

 

Προφανώς θα χρησιμοποιήσεις τα service που έχεις ήδη για τα αντίστοιχα user data και θα δηλώσεις τον interceptor στο app.module

providers: [
		...
        { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
 		...
    ],

Εναλλακτικά, μπορείς να παίξεις και με decorator, άλλο ένα παράδειγμα που είναι angular 2 και σίγουρα θέλει αλλαγές αλλά δεν θυμάμαι τι, ουσιαστικά κάνεις import το http service, το κάνεις 'decorate' με κάτι που θες να αλλάξεις ή να συμπληρώσεις και μετά χρησιμοποιείς αυτό σαν http service provider όπου θες να υπάρχει η αντίστοιχη λειτουργικότητα, εδώ δεν είναι για JWT αλλά η λογική είναι η ίδια

 

import { Injectable}  from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
import { XCSRF } from './../services/tokens'

@Injectable()
export class HttpClient {
  constructor(http: Http) {
    this._http = http;
  }
  private _http: Http;
  private createAuthorizationHeader(headers:Headers) {
		let token = XCSRF.toString().replace('Token ', '');
		headers.append('Accept', 'application/json');
		headers.append('X-Csrf-Token', token);
  }

  get(url) {
    let headers = new Headers();
    this.createAuthorizationHeader(headers);
    return this._http.get(url, {
      headers: headers
    });
  }

  post(url, data) {
    let headers = new Headers();
    this.createAuthorizationHeader(headers);
    return this._http.post(url, data, {
      headers: headers
    });
  }
}

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Καταρχας εφτιαξα καποια views στον node και μαζι με τα routes εκανα Login μεσα στον node και οχι απο την angular. Οποτε ολη η λειτουργικοτητα ηταν στο localhost : 3000. Και παλι δε μπορουσα να παρω cookies. Οποτε αυτο σημαινει οτι μαλλον δε φταιει που η angular τρεχει στον δικο της σερβερ και σε αλλη θυρα και ο node τρεχει σε αλλη θυρα.

 

Απο κει και περα, συμφωνα με ενα αλλο παραδειγμα που ειχα δει και ετσι εχω φτιαξει καποια αλλα post, στο profile service εχω κανει

  getProfile(){
    console.log('in profile service');
    let headers = new Headers();
    headers.append('Content-Type','application/json');
    return this.http.get('http://localhost:3000/cms/account', {headers:headers}).pipe(map(res => res.json()));
  }

Στα αλλα post δεν υπηρξε καποιο θεμα, εδω ομως το ιδιο προβλημα παραμενει. Βεβαια, τα αλλα post δεν εχουν σχεση με login users, απλα στελνω καποια πραγματα στον σερβερ. Δε νομιζω οτι σ αυτη τη περιπτωση πρεπει να κανω append το token στα headers μου γιατι εχω φτιαξει http-only cookie. Συμφωνα με αυτο εδω : "if we store the JWT in a cookie, we will not need any further client logic for sending back the cookie to the application server with each request, assuming the login page and the application share the same root domain."

 

Anyhow, ευχαριστω για τη βοηθεια, συνεχιζω να το κοιταω και εγω. Δε θελω να παω σε localStorage λυση γμτ.

 

Thanks

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ελα φιλε. Γιατι οχι cookies? Μια χαρα λυση ειναι. Εχω προσπαθησει και με 

res.cookie("SESSIONID", token, {httpOnly:false, secure:false});

και παλι δεν εγινε τπτ, ειχα το ιδιο προβλημα. Τεσπα, κατσε να ξαναδοκιμασω

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

12 λεπτά πριν, slevinkelevra είπε

Ελα φιλε. Γιατι οχι cookies? Μια χαρα λυση ειναι.

Security-wise υπάρχουν tradeoffs και δεν θα το πιάσω από εκεί το θέμα, προσωπικά, προτιμάω να έχω πρόσβαση στο jwt μέσα στην JS και να χρησιμοποιώ το payload του JWT για να ξέρω π.χ. τα access levels ή κάποια άλλα user data που είναι σημαντικά για τη λειτουργία της εφαρμογής και δεν θέλω να κάνω queries σε κάθε request.

  • Thanks 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ναι sorry, εχεις δικιο, αμα κανω 

res.cookie("SESSIONID", token, {httpOnly:true, secure:false});

δουλευει μονο αν κανω Login μεσα απο node (ολα απο localhost : 3000), αλλα μεσω angular παλι δε βλεπω το cookie. Αρα ειναι θεμα domain τωρα πια ? Υπαρχει κανα workaround γ αυτο? 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το cookie δεν λαμβάνει υπόψιν καθόλου το  port,  δεν θα έπρεπε να έχεις τέτοιο πρόβλημα. Μήπως παίζει κάτι μεταξύ 127.0.0.1 και localhost, δηλαδή από angular το request είναι για 127.0.0.1 πχ?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ελα, εφτιαχνα form validation. 

Δεν εχω ιδεα. Πως μπορω να το τσεκαρω αυτο? Μπορω να δω κατι στα settings? Το μονο που ειχα κανει οταν το εστηνα, ηταν να βαλω 

"outputPath": "../public",

στο angular.json για να βαλει την compiled angular στον Public φακελο του Node οταν την κανω compile. Απο κει και περα δεν εχω πειραξει κατι. 

Επισης στα angular services, τα url τα δινω καρφωτα , πχ

return this.http.post('http://localhost:3000/cms/signup'.......

Πως μπορω να τσεκαρω αυτο που λες?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Γυρνα το σε jwt...Αν θες να κανεις universal τοτε κρατα τα cookies.

Αυτο που λεει ο alou ειναι μηπως καποια req απο ng τα κανεις με 127.0.0.1 και οχι με localhost.

Επισης, για να διευκολυνεις τον εαυτο σου κατα το production, τα urls βαλτα σε μεταβλητες σε ενα config και καντες import στα services. Με αυτο το τροπο θα αλλαζεις μονο μια γραμμη πριν το production και ολα σου τα http reqs θα κοιτανε στο σωστο endpoint/domain.

Επεξ/σία από Predatorkill
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Οχι, ολα καρφωτα τα βαζω , πχ

http://localhost:3000/cms/signup

Δε ξερω τι αλλο μπορει να παιζει. Και δε ξερω τι αλλο μπορω να τσεκαρω, δε μου κοβει να τσεκαρω κατι αλλο, συν του οτι εχω εκνευριστει, που δε βοηθαει καθολου. 


Μα και τωρα jwt ειναι, απλα επιλεγω να το αποθηκευσω σε cookie λογω της δυνατοτητας για http-only και αφηνω μονο το user id σε localStorage για πιο ευκολα προσβασιμο. Στη τελικη και να κλαπει δε μπορουν να κανουν και πολλα με ενα id μονο.

Το localStorage γενικα δε μου φαινετε κ πολυ ασφαλες, ζηταμε πολλα πραγματα απο κατι που καταρχας εχει συγκεκριμενο quota. 

Οπως και να χει, μαλλον θα χρησιμοποιησω LocalStorage τελικα αντι για cookie, μιας και δε βλεπω προκοπη με τα cookies. 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ευχαριστω κα παλι, δοκιμαζω κατι απλο οπως

res.cookie('name', 'tobi', { httpOnly:false, secure:false, domain: null, maxAge: new Date(Date.now() + 900000) });

που εχει κ στο παραδειγμα  των docs. Εχω δοκιμασει με domain null, localhost, .localhost, ..localhost και χωρις να καθοριζω τιποτα καθολου και δεν βλεπω κανενα cookie ουτε καν στην κονσολα. Υποθετω δηλαδη οτι θα επρεπε να το βλεπω μιας και χω μονιμα false το HttpOnly και το secure. Ειμαι στη φαση που εχω εξαντλησει τι θα μπορουσε να ειναι και απλα δοκιμαζω οτι λυση η συμβουλη βρω μπροστα μου. 

Παιζει να ειναι και καποια αλλη βλακεια με το localhost, δε ξερω. Ουτε παει ο νους μου, απλα εκανα copy/paste απο ενα παραδειγμα που θα επρεπε να δουλευει. Node και angular εχω στησει απλα , με τις λεπτομερειες που εχω πει παραπανω.  Σε development φαση ειμαι, ολα τοπικα. Αν κανω Login και μετα παω να παρω τα cookies μονο μεσω node routes και node views , τοτε δουλευει κανονικα. Να υπαρχει καποια ρυθμιση σε καποιο ξεχασμενο json αρχειο ξερω γω?

Εχω βγει εξω, εχω τραμπουκισει ενα τυχαιο περαστικο, μετα πηγα σε ενα πιτσιρικι κ του πηρα το παγωτο, εβαλα τις φωνες στο γειτονα, μπηκα στο αμαξι μου κ εκανα επιτηδες burn-out να γεμιζει καπνο η γειτονια και να βρωμισει ο τοπος λαστιχο, εβαλα τερμα μουσικη, βρεχω του περαστικους απο το μπαλκονι....τα νευρα μου δηλαδη καπως, οσο να πεις, ετσι λιγουλακι. 

 

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Κατι τετοιο δοκιμασες;

https://www.npmjs.com/package/ngx-cookie-service

Δες και τουτο (ng5)

μυριζομαι cors issue αλλα και session storage misconfig. Απο τη στιγμη που παιζεις απο node views αλλα οχι απο ng serve κατι τετοιο παιζει.

Επεξ/σία από Predatorkill
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...